如何在Entity Framework Core中避免循环导航属性? [英] How to avoid circular navigation properties in Entity Framework Core?

查看:273
本文介绍了如何在Entity Framework Core中避免循环导航属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的表模式:

I have a such table schema:

CREATE TABLE Categories
(
    Id INT IDENTITY(1,1),
    Name varchar(100),
    CONSTRAINT PK_Category_Id PRIMARY KEY (Id)
)

CREATE TABLE Products
(
    Id INT IDENTITY(1,1),
    IdCategory INT NOT NULL
        CONSTRAINT FK_Products_IdCategory__Categories_Id FOREIGN KEY(IdCategory) REFERENCES Categories(Id),
    Name varchar(100), 
    Price decimal(18,2),
    ImageUrl varchar(256),
    CONSTRAINT PK_Product_Id PRIMARY KEY (Id)
)

EF Core生成以下代码:

EF Core generated the following code:

public partial class Categories
{
    public Categories()
    {
        Products = new HashSet<Products>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Products> Products { get; set; }
}

public partial class Products
{
    public Products()
    {
        OrderItems = new HashSet<OrderItems>();
        ShoppingCartItems = new HashSet<ShoppingCartItems>();
    }

    public int Id { get; set; }
    public int IdCategory { get; set; }
    public string Name { get; set; }
    public decimal? Price { get; set; }
    public string ImageUrl { get; set; }

    public virtual Categories IdCategoryNavigation { get; set; }
    public virtual ICollection<Items> Items { get; set; }        
}

OnModelCreating(ModelBuilder modelBuilder)方法:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");

    modelBuilder.Entity<Categories>(entity =>
    {
        entity.Property(e => e.Name)
            .HasMaxLength(100)
            .IsUnicode(false);
    });

    modelBuilder.Entity<Products>(entity =>
    {
        entity.Property(e => e.ImageUrl)
            .HasMaxLength(256)
            .IsUnicode(false);

        entity.Property(e => e.Name)
            .HasMaxLength(100)
            .IsUnicode(false);

        entity.Property(e => e.Price).HasColumnType("decimal(18, 2)");

        entity.HasOne(d => d.IdCategoryNavigation)
            .WithMany(p => p.Products)
            .HasForeignKey(d => d.IdCategory)
            .OnDelete(DeleteBehavior.ClientSetNull)
            .HasConstraintName("FK_Products_IdCategory__Categories_Id");
    });
}

我编写了以下代码:

public override async Task<Products> GetById(int id)
{   
    return await DbContext.Products
        .Include(p => p.IdCategoryNavigation)
        .FirstOrDefaultAsync(p => p.Id == id);
}

我有以下圆形导航属性和这些属性将一直创建,直到我单击产品

And I've got the following circular navigation properties and these properties will be created until I click on Products:

如何避免循环导航属性?请告诉我我做错了什么?

How can I avoid circular navigation properties? Please, tell me what I've done wrong? Is it expected and correct behaviour?

推荐答案

这是任何编程语言的预期组成部分,因为始终可以创建引用的对象对彼此。可视化该外观时,Visual Studio中的调试器将根据您对对象树的导航而显示链接中的链接

This is an expected part of any programming language because it's always possible to create objects that refer to each other. When visualising this the debugger In visual studio will just show the links as it sees it in response to your navigation of the object tree

暂时离开Entity Framework,考虑通用集合类LinkedList,它是LinkedListNode对象的链接集合。每个节点都有一个下一个和一个上一个,而列表本身有一个第一和最后一个(因此链接是双向的)。

Moving away from Entity Framework for a moment, consider the generic collection class LinkedList, which is a chained collection of LinkedListNode objects. Each node has a Next and a Previous, while the list itself has a First and a Last (the linking is hence bidirectional)

如果您在列表中放入两个项目,然后, hello和 world在调试器中对其进行检查:

If you put two items in your list, "hello" and "world" then examined it in the debugger you'd see:

list.First          LinkedListNode "hello"
  .Next             LinkedListNode "world"
    .Previous       LinkedListNode "hello"
      .Next         LinkedListNode "world"

您可以整天来回移动,使调试器可视化器中的树越来越深。这不是错误或问题,而只是概念上的可视化代码,类似于编写代码:

You could step back and forth all day, making the tree in the debugger visualiser deeper and deeper. It's not an error or a problem, it's just the conceptual visual equivalent of writing in code:

list.First.Next.Previous.Next; //"world

您也可以整天交替输入Next和Previous-它是有效的C#,尽管可能没有必要除非您走的是树枝状的树,并且您想在下一个分支之前向上接近根部

You could alternate typing Next and Previous all day too - it's valid C# though probably unnecessary unless you're walking a tree that branches out and you want to go up closer to the root before travelling down a different branch

这种周期性结构会在任何地方弹出对象引用另一个对象,该对象引用原始对象-一个DataTable的DataRows每个都有一个.Table属性,该属性返回引用拥有该行的表,依此类推。这没有问题,不会导致您的代码无休止地崩溃。循环-EF不会先保存客户,然后再保存客户订单,然后再保存客户订单的客户,然后再保存客户订单的客户订单...等等。它知道何时停止保存客户订单对

This "cyclical" structure pops up anywhere an object refers to another object that refers to the original - A DataTable's DataRows each have a .Table property that refers back to the table that owns the row and so on. Not a problem and won't cause your code to break down in some endless loop - EF won't try to save the Customers, then the Customer's Orders, then the Customer's Orders' Customers, then the Customer's Orders' Customers' Orders ... etc. It knows when to stop saving a Customer Order pair

这篇关于如何在Entity Framework Core中避免循环导航属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆