c# - EF7(核心)中同一个表的多个关系

标签 c# .net entity-framework orm

我有这样的模型

public class Question
{
    public string Id { get; set; } = Guid.NewGuid().ToString();

    public Answer Answer { get; set; }
    public List<Variant> Variants { get; set; }

    public string CorrectVariantId { get; set; }
    public Variant CorrectVariant { get; set; }
}

public class Variant
{
    public string Id { get; set; } = Guid.NewGuid().ToString();

    public string QuestionId { get; set; }
    public Question Question { get; set; }
}

// mapping

modelBuilder.Entity<Question>()
    .HasOne(q => q.CorrectVariant)
    .WithOne(v => v.Question)
    .HasForeignKey<Question>(q => q.CorrectVariantId);

modelBuilder.Entity<Variant>()
    .HasOne(v => v.Question)
    .WithMany(a => a.Variants)
    .OnDelete(DeleteBehavior.Cascade);

在我从 EF RC1 升级到 RTM 之前,它工作得很好。但现在它抛出: System.InvalidOperationException:无法在“Question.Variants”和“Variant.Question”之间创建关系,因为“Question.CorrectVariant”和“Variant.Question”之间已经存在关系。导航属性只能参与单个关系。

如果不从 Question 模型中删除 Variants 属性,是否有任何解决此问题的方法?

最佳答案

给出的两个例子已经让我完成了一部分,但我想要一个集合和一个相同对象类型的单个项目,因此我的模型上有同一个表,就像在原始问题中一样。我试图在下面提供一个适用于 .NET Core 2.2 的简单示例:

public class ParentModel
{
    public int Id { get; set; }

    // Id for single instance navigation property
    public int? ChildModelId { get; set; }

    // Single instance navigation property to ChildTable, identified by ChildModelId property as foreign key
    public virtual ChildModel ChildModel { get; set; }

    // Collection navigation property to ChildTable with identified by ParentId property
    public virtual ICollection<ChildModel> ChildModels { get; set; }
}

public class ChildModel
{
    public int Id { get; set; }

    // Id for ParentModel property back to ParentTable
    public int ParentId { get; set; }

    // Single instance navigation property to ParentTable, identified by ParentId property as foreign key
    public virtual ParentModel ParentModel { get; set; }
}

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {   
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<ParentModel>()
            .ToTable("ParentTable");

        // Configure collection of ChildModels (ParentTable to ChildTable/one-to-many relationship)
        builder.Entity<ParentModel>()
            .HasMany(t => t.ChildModels)
            .WithOne(t => t.ParentModel)
            .HasForeignKey(t => t.ParentId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);

        builder.Entity<ChildModel>()
            .ToTable("ChildTable");

        // Configure single ChildModel navigation property on ParentModel (one-to-one relationship)
        builder.Entity<ParentModel>()
            .HasOne(t => t.ChildModel)
            .WithOne()
            .HasForeignKey(typeof(ParentModel), nameof(ParentModel.ChildModelId))
            .IsRequired(false)
            .OnDelete(DeleteBehavior.Restrict);
    }
}

避免Navigation properties can only participate in a single relationship.错误的关键是将导航属性配置回父表只一次。我们使用 .WithOne(t => t.ParentModel) 为 ParentTable 上的 ChildModels 集合配置它。然后,我们不必通过调用空的 .WithOne() 来为后续关系配置关系的另一端,因为如果我们再次配置它(例如 .WithOne(t => t.ParentModel)) 会报错。

导航属性上的 virtual 修饰符也允许 lazy loading .

关于c# - EF7(核心)中同一个表的多个关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38520695/

相关文章:

entity-framework - Web 应用程序的 EF Code First DBContext 生命周期

c# - 使用平面样式更改 ToolStripComboBox 的边框

C# volatile double

.net - 暴力破解验证码?

c# - ExecuteSqlCommand并行执行

c# - Winforms Entity Framework

c# - 如何实现非泛型的泛型参数

C# Nullable<T> 查询理解 - "expression is always true"警告

C# 对象引用未设置为对象的实例

C# .NET 生成一次字符串数组,其索引是表中的字符串值