我们已经决定将所有枚举合并到一个RefValue表中,我至少对此没有任何疑问,但是我似乎无法让Entity发挥作用。
我认为,一旦您查看了架构,这应该很有意义,但是要点是,当涉及枚举时,Person对象将具有2个字段(例如,gender,relationshipStatus,nameSuffix等)。一个字段将存储值(例如“ female”),而另一个字段将存储该RefValue的ID(例如,一些guid,该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属性当作Guid作为RefValue表的外键。我开始转向仅使它们成为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);
}
有没有什么方法可以创建这种一对多(或实际上是多对一)的关系,而又无需级联问题或(尤其是)实体在非依赖表上创建阴影属性?
最佳答案
让我们采用原始的实体模型:
[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; }
}
使用Fluent API配置FK关系绝对没有问题(即仅在一侧具有导航属性)。您需要考虑的唯一一件事是,由于该模型引入了多个级联路径,因此您不能使用删除级联选项,即应指定
DeleteBehavior.Restrict
。话虽如此,这是上述模型的流畅配置:
modelBuilder.Entity<Person>()
.HasOne(p => p.GenderRef)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Person>()
.HasOne(p => p.RelationshipStatusRef)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Person>()
.HasOne(p => p.NameSuffixRef)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
而且,如果您添加了集合导航属性,请不要忘记在相应的
WithMany
调用中指定它们,否则EF Core将创建其他关系。