Lea*_*ner 2 c# t-sql entity-framework-core asp.net-core
我有一个这样的表架构:
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)
)
Run Code Online (Sandbox Code Playgroud)
EF Core 生成了以下代码:
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; }
}
Run Code Online (Sandbox Code Playgroud)
及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");
});
}
Run Code Online (Sandbox Code Playgroud)
我编写了以下代码:
public override async Task<Products> GetById(int id)
{
return await DbContext.Products
.Include(p => p.IdCategoryNavigation)
.FirstOrDefaultAsync(p => p.Id == id);
}
Run Code Online (Sandbox Code Playgroud)
我有以下圆形导航属性,这些属性将被创建,直到我单击Products:

如何避免循环导航属性?请告诉我我做错了什么?这是预期的且正确的行为吗?
这是任何编程语言的预期部分,因为总是可以创建相互引用的对象。可视化此内容时,Visual Studio 中的调试器将仅显示其看到的链接,以响应您对对象树的导航
暂时离开实体框架,考虑通用集合类 LinkedList,它是 LinkedListNode 对象的链式集合。每个节点都有一个下一个和一个上一个,而列表本身有一个第一个和一个最后一个(因此链接是双向的)
如果您将两个项目“hello”和“world”放入列表中,然后在调试器中检查它,您会看到:
list.First LinkedListNode "hello"
.Next LinkedListNode "world"
.Previous LinkedListNode "hello"
.Next LinkedListNode "world"
Run Code Online (Sandbox Code Playgroud)
您可以整天来回走动,使调试器可视化器中的树越来越深。这不是一个错误或问题,它只是代码编写的概念视觉等效项:
list.First.Next.Previous.Next; //"world
Run Code Online (Sandbox Code Playgroud)
您也可以整天交替输入“下一个”和“上一个” - 这是有效的 C#,但可能没有必要,除非您正在走一棵有分支的树,并且您想在沿着不同的分支走之前先靠近根部
这种“循环”结构会在一个对象引用另一个对象(该对象引用原始对象)的任何地方出现 - 每个 DataTable 的 DataRow 都有一个 .Table 属性,该属性引用回拥有该行的表,依此类推。不是问题,不会导致您的代码在某些无限循环中崩溃 - EF 不会尝试保存客户,然后保存客户的订单,然后保存客户的订单的客户,然后保存客户的订单的客户的订单..等等。它知道何时停止保存客户订单对