【问题标题】:Self referencing loop detected for property when inserting into database插入数据库时​​检测到属性的自引用循环
【发布时间】:2019-07-09 18:24:52
【问题描述】:

我正在尝试学习 C# Fluent API,但我的模型设置遇到了问题(我认为)。我有三个表:OrderFile、Order、LineItem。错误:

检测到类型为“BaseService.WebApi.Order”的属性“order”的自引用循环。路径'orders[0].lineItems[0]'。

我的结构:

  • OrderFile 包含List<Orders>
  • 订单包含List<ListItems> 和导航属性OrderFile
  • ListItem 包含一个导航属性Order

它们与 Fluent API 中指定的 ForeignKey 约束绑定在一起。约束有问题吗?我试图关注这个example for Foreign keys

modelBuilder.Entity<OrderFile>(e =>
            {
                //many orders within one order file
                //the FK relates the OrderFile to the nav key of the Order
                e.HasMany(of => of.Orders)
                .WithOne(o => o.orderFile)
                .HasForeignKey(o => o.FileGuid);

                e.HasKey(o => o.FileGuid);
            });

            modelBuilder.Entity<Order>(e =>
            {
                //each order has an array of line items
                //each line item has one order (navigation property)
                //the foreign key of the line item ties it to the Parent (List<Order>)

                e.HasMany(o => o.LineItems)
                .WithOne(li => li.order)
                .HasForeignKey(o => o.OrderGuid); 

                e.HasKey(o => o.OrderGuid);
            });

型号

public class OrderFile
{
    public Guid FileGuid { get; set; }
    public virtual ICollection<Order> Orders { get; set; } //everything with same FileGuid
}

public class Order
{
    ....
    [JsonIgnore]
    public Guid FileGuid { get; set; }

    [Key]
    public Guid OrderGuid { get; set; }
    [JsonIgnore]
    public OrderFile orderFile { get; set; }
    public virtual ICollection<LineItem> LineItems { get; set; } //everything with same OrderGuid
    }

public class LineItem
{
       ....
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        public Guid OrderGuid { get; set; }
        public Order order { get; set; }

}

【问题讨论】:

  • LineItem 有流畅的标记吗?
  • 根据错误,订单进入订单项,订单项返回订单......这会导致循环依赖。
  • @TonyAbrams,不,我还是新手,但我虽然 LineItem 关系是根据父订单指定的。有错吗?
  • 我的经验是你需要选择一个实体来拥有关系和导航属性......否则你最终会出现自引用循环。
  • 请同时显示引发异常的代码,以及异常类型和EF版本。

标签: c# entity-framework fluent


【解决方案1】:

您的 LineItem 实体有一个对 Order 的引用,它没有 JsonIgnore 属性。

基本上,您的问题源于尝试序列化具有循环依赖关系(循环)的对象图,而您的设计问题是您在 API 中使用数据库实体类。面向客户端的模型应该是与您在数据库中持久化的实体不同的类。

【讨论】:

  • 这解决了我的问题,但我很想解释它为什么会起作用......我从未在任何 EF 核心文档中看到过 JsonIgnore
  • 好吧,如果你有一个父级引用它的子级和引用父级的子级,那么在尝试序列化它时你会得到一个循环引用:“Alice 有一个孩子 Bob 和一个母亲爱丽丝带着孩子鲍勃和妈妈爱丽丝……”。您可以通过添加 JsonIgnore 属性来解决此问题,因此序列化程序会忽略母亲或孩子,在这种情况下,您有“Alice 有一个孩子 Bob”或“Bob 有一个母亲 Alice”,就是这样,或者通过告诉序列化要做什么使用循环引用。见newtonsoft.com/json/help/html/ReferenceLoopHandlingIgnore.htm
  • 这是有道理的,但据我所知,我遵循了这种格式(除了我自己指定关系)。请注意,尽管他们不使用 JsonIgnore。我错过了什么? docs.microsoft.com/en-us/ef/core/modeling/relationships
  • 关系是实体框架,Json 属性是 JSON.Net。最佳做法是让实体类仅在您使用数据层时使用,然后在这些数据库对象之间进行某种转换,以在 API 中使用模型对象。
  • 假设您有一个 GetUser API 和一个 User 实体,其 Credentials 属性取自另一个表 Credentials,Department 属性取自 Departments。获取用户时,您不希望 API 中有密码,并且希望在 API 模型中拥有 DepartmentName 属性,而不是整个部门。也许您也不关心内部数据库 UserId。走得越远,模型和数据库实体类就会开始不同。
猜你喜欢
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 2021-12-26
  • 2016-11-27
  • 2020-01-07
  • 1970-01-01
相关资源
最近更新 更多