正如 this 中所述帖子,我在序列化 Entity Framework 代理时遇到 Json 序列化错误:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.PurchaseOrder_446B939192F161CDBC740067F174F7A6059B0F9C0EEE68CD3EBBD63CF9AF5BD0'.
但不同的是,我的实体中没有循环引用,它仅出现在我们的生产环境中。本地一切正常...
我的实体:
public interface IEntity
{
Guid UniqueId { get; }
int Id { get; }
}
public class Entity : IEntity
{
public int Id { get; set; }
public Guid UniqueId { get; set; }
}
public class PurchaseOrder : Entity
{
public string Username { get; set; }
public string Company { get; set; }
public string SupplierId { get; set; }
public string SupplierName { get; set; }
public virtual ICollection<PurchaseOrderLine> Lines { get; set; }
}
public class PurchaseOrderLine : Entity
{
public string Code { get; set; }
public string Name { get; set; }
public decimal Quantity { get; set; }
}
我的 PurchaseOrderController 上的 GetCurrent 操作引发异常:
public class PurchaseOrderController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public PurchaseOrderController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public JsonResult GetCurrent()
{
return Json(EnsurePurchaseOrder(), JsonRequestBehavior.AllowGet);
}
private PurchaseOrder EnsurePurchaseOrder()
{
var company = RouteData.GetRequiredString("company");
var repository = _unitOfWork.GetRepository<PurchaseOrder>();
var purchaseOrder = repository
.Include(p => p.Lines)
.FirstOrDefault
(
p => p.Company == company &&
p.Username == User.Identity.Name
);
if (purchaseOrder == null)
{
purchaseOrder = repository.Create();
purchaseOrder.UniqueId = Guid.NewGuid();
purchaseOrder.Company = company;
purchaseOrder.Username = User.Identity.Name;
_unitOfWork.SaveChanges();
}
return purchaseOrder;
}
}
最佳答案
选项 1(推荐)
Try turning off Proxy object creation on your DbContext .
DbContext.Configuration.ProxyCreationEnabled = false;
这种情况通常是因为应用程序正在使用 POCO 对象(T4 Generated 或 Code-First)。当 Entity Framework 想要跟踪未内置于 POCO 对象中的对象中的更改时,就会出现问题。为解决此问题,EF 创建了缺少 POCO 对象中的属性且不可序列化的代理对象。
我推荐这种方法的原因;使用网站意味着您可能不需要对 Entity Framework 对象进行更改跟踪(有状态),它释放了内存和 cpu,因为更改跟踪被禁用,并且它将以相同的方式在所有对象上一致地工作。
选项 2
使用允许自定义序列化对象的序列化程序(如 JSON.Net,它已包含在 ASP.Net 4 中)。
我不推荐这种方法的原因是最终需要自定义对象序列化逻辑将代理对象序列化为其他对象类型。这意味着您依赖逻辑来向下游传递结果。更改对象意味着更改逻辑,并且在 ASP.Net MVC 项目(任何版本)中,除了更改 View 之外,您还需要更改一些其他内容,这些内容在首先编写逻辑的人之外并不容易知道。
选项 3( Entity Framework 5.x +)
使用 .AsNoTracking()这将禁用特定查询上的代理对象。如果您需要使用更改跟踪,这可以为解决方案 #1 提供一个很好的中间解决方案。
https://stackoverflow.com/questions/16949520/