实体框架核心一对多在主表上没有外键

时间:2018-04-13 21:27:24

标签: c# asp.net sql-server entity-framework-core

我们决定将所有枚举合并到一个RefValue表中,至少我没有遇到任何问题,但我似乎无法让Entity一起玩。

我认为一旦你看到模式就应该有意义,但它的要点是Person对象在枚举时会有2个字段(例如gender,relationshipStatus,nameSuffix等)。一个字段将存储该值(例如" female"),另一个字段将存储该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属性作为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);
    }

有没有办法在没有级联问题的情况下创建这种一对多(或真正多对一)的关系,或者(特别是)实体在非依赖表上创建阴影属性?< / p>

2 个答案:

答案 0 :(得分:2)

让我们采用您的原始实体模型:

[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; }
}

使用流畅的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将创建其他关系。

答案 1 :(得分:1)

  

我们决定将所有枚举合并到RefValue表中

这让我感到难过。你如何阻止人们成为单身性别或女性的关系状态?如何使用特定外键的所有有效值填充下拉列表?您如何帮助报告作者正确加入表格?

  

我似乎无法让他们一起玩。

那是因为你所尝试的是对关系设计的根本违反。这只是许多困难中的第一个,应该让你重新思考这个设计。