提问人:aardvark 提问时间:9/19/2023 更新时间:9/19/2023 访问量:27
使用带有桥接表的 EF Core 7 约定实现查询和级联删除时遇到问题
Having trouble achieving queries and cascading deletes using EF Core 7 conventions with a bridge table
问:
在我的 SQL 数据库中,我有一个表。我还有一张桌子。单元可以具有 Containers,并且该关系是与表建立的,该表包含 ContainerId - Containers 表的 ContainerId 列的外键;以及 UnitId,它是返回到 Units 表上的 UnitId 的外键。UnitId 不直接位于 Containers 表上的原因是,容器也可以属于其他类型的实体,因此决定为每个类型设置一个桥接表,而不是每次想要将新类型与容器关联时都更改表定义。Units
Containers
UnitContainers
在 OnModelCreating() 中,目前我有以下内容:
modelBuilder.Entity<UnitContainer>().HasKey(uc => new { uc.UnitId, uc.ContainerId });
modelBuilder.Entity<Unit>()
.HasMany(u => u.UnitContainers)
.WithOne()
.HasForeignKey(uc => uc.UnitId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Container>()
.HasMany(c => c.UnitContainers)
.WithOne()
.HasForeignKey(uc => uc.ContainerId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<UnitContainer>()
.HasKey(uc => new { uc.UnitId, uc.ContainerId });
modelBuilder.Entity<UnitContainer>()
.HasOne(uc => uc.Unit)
.WithMany(u => u.UnitContainers)
.HasForeignKey(uc => uc.UnitId);
modelBuilder.Entity<UnitContainer>()
.HasOne(uc => uc.Container)
.WithMany(c => c.UnitContainers)
.HasForeignKey(uc => uc.ContainerId);
我已经尝试了配置的其他几种排列,但它们几乎都会导致相同的结果,也就是说,当我去执行这个 linq 查询时:
var query = ctx.Set<Unit>()
.Include(unit => unit.Containers);
我收到一个 SqlException:
Microsoft.Data.SqlClient.SqlException (0x80131904):列无效 名称“UnitId”。列名“UnitId”无效。
这是因为生成的 SQL 尝试直接将容器 LEFT JOIN 到 Units,而不是使用 UnitContainers 桥接表。
将这部分视为我的问题之一。第二部分是我不仅需要它才能工作,我还需要级联删除才能工作,以便当我删除一个单元时,在 UnitContainers 中引用该单元的任何条目也会被删除。
谁能告诉我我的配置有什么问题?
下面是 Unit 实体:
public class Unit
{
[Key]
UnitId { get; set; }
public ICollection<UnitContainer> UnitContainers { get; set; }
public ICollection<Container> Containers { get; set; }
}
下面是容器实体:
public class Container
{
[Key]
public int ContainerId { get; set; }
public int UnitId { get; set; }
public Unit Unit { get; set; }
public ICollection<UnitContainer> UnitContainers { get; set; }
}
提前致谢。
答:
我相信您已经多次配置了属性关系。
在这个...UnitConfigurations
modelBuilder.Entity<Unit>()
.HasMany(u => u.UnitContainers)
.WithOne()
.HasForeignKey(uc => uc.UnitId)
.OnDelete(DeleteBehavior.Cascade);
您声明了单方面的关系,有一个集合,但不知道从...Unit
UnitContainers
UnitConfiguration
Unit
.WithOne()
然后你又宣布了财产关系......UnitContainers
modelBuilder.Entity<UnitContainer>()
.HasOne(uc => uc.Unit)
.WithMany(u => u.UnitContainers)
.HasForeignKey(uc => uc.UnitId);
这一次,存在互惠关系 两者都在配置相同的关系,并且都配置了属性。但是,同一实体之间的两个不同关系不能共享同一个密钥。.HasOne(uc=>uc.Unit)
UnitContainers
要么将两个子句都留空,...With
modelBuilder.Entity<Unit>()
.HasMany(u => u.UnitContainers)
.WithOne()
.HasForeignKey(uc => uc.UnitId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<UnitContainer>()
.HasOne(uc => uc.Unit)
.WithMany()
.HasForeignKey(uc => uc.UnitId);
或者摆脱这种关系并使用已经定义的。Unit
UnitConfiguration
作为奖励...
如果要跳过中间导航,例如直接导航到 from,或者相反,可以尝试以下配置:UnitConfiguration
List<Configuration> Configurations
Unit
modelbuilder.Entity<Unit>
.HasMany(x=>x.Configurations)
.WithMany()
.UsingEntity<UnitConfiguration>();
评论