【发布时间】:2018-09-24 07:21:23
【问题描述】:
我们决定将所有枚举合并到一个 RefValue 表中,我至少在构思上没有问题,但我似乎无法让 Entity 一起玩。
我认为一旦您查看架构就应该有意义,但它的要点是,当涉及到枚举时,Person 对象将具有 2 个字段(例如,性别、关系状态、名称后缀等)。一个字段将存储值(例如“女性”),而另一个字段将存储该 RefValue 的 id(例如,某个 guid 将是存储/定义值的 RefValue 表的外键)。这样我们就不必在 RefValue 表上进行多次连接来查找这些属性值。
这是架构:
[Table("Person")]
public class Person : Base
{
public Guid Id {get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public RefValue GenderRef { get; set; }
public string RelationshipStatus { get; set; }
public RefValue RelationshipStatusRef { get; set; }
public string NameSuffix { get; set; }
public RefValue NameSuffixRef { get; set; }
}
[Table("RefValue")]
public class RefValue : Base
{
public Guid Id {get; set; }
public string Type { get; set; }
public string Value { get; set; }
}
在 Person 对象中,我真的希望 RefValue 属性只是作为 RefValue 表的外键的 Guid。我开始转向只为它们制作 RefValue 属性,因为如果我按照导航属性的概念来做,EFC 似乎会让事情变得更容易。但问题是,它非常坚持在 RefValue 表上有一列作为这些一对多关系的另一端。
我可以在 RefValue 表上添加额外的列,这样看起来更像这样:
[Table("RefValue")]
public class RefValue : Base
{
public string Type { get; set; }
public string Value { get; set; }
public ICollection<Person> Genders { get; set; }
public ICollection<Person> RelationshipStatus { get; set; }
public ICollection<Person> NameSuffix { get; set; }
}
但无论我如何旋转上下文类的 OnModelCreating() 方法,我似乎都无法让它们一起玩。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<RefValue>()
.HasMany(p => p.Genders)
.WithOne(p => p.GenderRef)
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<RefValue>()
.HasMany(p => p.RelationshipStatus)
.WithOne(p => p.RelationshipStatusRef)
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<RefValue>()
.HasMany(p => p.NameSuffix)
.WithOne(p => p.NameSuffixRef)
.OnDelete(DeleteBehavior.SetNull);
}
我也尝试过相反的方式,但我通常会收到Introducing FOREIGN KEY constraint ... on table ... may cause cycles or multiple cascade paths
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.HasOne(p => p.PersonTypeRef)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<Person>()
.HasOne(p => p.RelationshipStatusRef)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<Person>()
.HasOne(p => p.NameSuffixRef)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
}
有没有什么方法可以创建这种一对多(或真正的多对一)关系,而不会出现级联问题或(尤其是)实体在非依赖表上创建影子属性?
【问题讨论】:
-
我处理它们的方式是创建一个查找表,因为这些值不会经常更改。
LuGender(Code, Desc)。我将用FEM, Female和MAL, Male等填充它。然后我将亲自拥有一个名为Gender的属性(与表名相同,除了Lu)。我发现Guids 的描述性不是很好。 -
我不确定真正的问题是什么。集合导航属性不会向表中添加列。 FK 列位于另一侧(具有参考导航属性的列)。在您的情况下,您只是在
Person和RefValue之间有多个 多对一关系。这种关系设计的唯一问题是多个级联路径(无法告诉数据库 FK 使用不同的值),因此您不能使用级联选项,例如您应该配置与OnDelete(DeleteBehavior.Restrict)的关系。 -
CodingYoshi,是的,我喜欢为查找代码使用一种缩写而不是 Guid 的想法,但是为了统一起见,所有模型都继承自一个基类,其中包括一个 Guid Id 和 4标准 createdDate/by/updatedDate/by,所以我只想在所有表中继续使用该系统。
-
Ivan Stoev,也许这是标准 EF 和 EF Core 之间的区别?这是一个link,他们讨论 EFC 如何创建阴影属性,特别是在一对多关系中。我认为你是对的,尽管这可能是级联的死胡同。我认为可能值得放弃级联删除来代替手动管理 FK 关系,因为我不喜欢 EF 强加其意见并随后创建紧密耦合的依赖关系(“紧密耦合”可能太强了)
-
EF Core 关系没有任何问题。事实上,多级联路径问题/限制源于 SqlServer 数据库。集合导航属性不是强制性的,但流畅的 API 必须准确反映它们的存在 (
WithMany(p => p.Collection)) 或不存在 (WithMany())。那么你只需要使用.OnDelete(DeleteBehavior.Restrict)
标签: c# asp.net sql-server entity-framework-core