gpt4 book ai didi

c# - EFCore 删除引用的实体

转载 作者:太空宇宙 更新时间:2023-11-03 22:34:12 27 4
gpt4 key购买 nike

我在一个项目中有两个实体:SupplierFinishingItemProductOptionListItem

ProductOptionListItem 通过导航属性引用另一个。

当我尝试创建 1 个引用 SupplierFinishingItemProductOptionListItem 时,它起作用并将关系保存在数据库中。

但是当我尝试创建 2 个或更多引用相同 SupplierFinishingItemProductOptionListItem 时,只有第一个实体将关系保存到数据库中。其他的保存为 null 引用。

我设法在我力所能及的最小的控制台应用程序中重现了它:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;

namespace relationship_test
{
class Program
{
static void Main(string[] args)
{
using (var db = new DatabaseContext())
{
var finishing = new SupplierFinishingItem { Name = "Finishing"};
db.Finishings.Add(finishing);

db.SaveChanges();

db.Options.Add(new ProductOptionListItem { Name = "Option 1", SupplierFinishingItem = finishing });
db.Options.Add(new ProductOptionListItem { Name = "Option 2", SupplierFinishingItem = finishing });
db.Options.Add(new ProductOptionListItem { Name = "Option 3", SupplierFinishingItem = finishing });

db.SaveChanges();
}
}
}

public class DatabaseContext : DbContext
{
public DbSet<ProductOptionListItem> Options { get; set; }
public DbSet<SupplierFinishingItem> Finishings { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=entity-test;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProductOptionListItem>()
.HasOne(p => p.SupplierFinishingItem)
.WithMany(s => s.UsedBy)
.HasForeignKey(p => p.SupplierFinishingItemId)
.OnDelete(DeleteBehavior.Restrict);
}
}

public class ProductOptionListItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid? SupplierFinishingItemId { get; set; }
public SupplierFinishingItem SupplierFinishingItem { get; set; }
}

public class SupplierFinishingItem
{
private HashSet<ProductOptionListItem> _usedBy;

public Guid Id { get; set; }
public string Name { get; set; }
public IEnumerable<ProductOptionListItem> UsedBy => _usedBy?.ToList();
}
}

运行此代码后生成的数据库如下:

enter image description here

如您所见,只有选项 1 有一个 SupplierFinishingItemId,其他两个都是 NULL

我在这里错过了什么?

最佳答案

问题是由集合导航​​属性的实现引起的:

public IEnumerable<ProductOptionListItem> UsedBy => _usedBy?.ToList();

从 getter 返回新的列表实例会以某种方式混淆 EF Core 导航属性修复代码并产生上述效果(甚至在调用 SaveChanges() 之前)。

解决方案是修复实现,使其在每次调用时不返回新列表(无论如何这被认为是属性 getter 的不良做法),例如:

public IEnumerable<ProductOptionListItem> UsedBy => _usedBy ?? (_usedBy = new HashSet<ProductOptionListItem>());

或将 EF Core 配置为直接使用支持字段:

modelBuilder.Entity<ProductOptionListItem>()
.HasOne(p => p.SupplierFinishingItem)
.WithMany(s => s.UsedBy)
.HasForeignKey(p => p.SupplierFinishingItemId)
.OnDelete(DeleteBehavior.Restrict)
.Metadata.PrincipalToDependent.SetPropertyAccessMode(PropertyAccessMode.Field); // <--

关于c# - EFCore 删除引用的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55938310/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com