c# - Entity Framework 代码首先多对多关系不起作用

标签 c# entity-framework

我们使用 Entity Framework 6,代码优先,来存储一个复杂的对象树,如下所示:

public abstract class DataCode
{
    public long Id { get; set; }
    public string Code { get; set; }
    public string Description { get; set; }
    public bool IsActive { get; set; }
}

public class InternCode : DataCode
{
    public string PrimaryRelationalOperator { get; set; }
    public string PrimaryValue { get; set; }
    public string SecondaryRelationalOperator { get; set; }
    public string SecondaryValue { get; set; }
}

public class Model : DataCode
{
    public ICollection<string> Aliases { get; set; }
    public bool ExportOnly { get; set; }
    public void GetOptions()
    {
        throw new NotImplementedException();
    }
}

public class Version
{
    public long Id { get; set; }
    public string Description { get; set; }
    public string Status { get; set; }
    public float VersionNumber { get; set; }
    public virtual PriceLevel PriceLevel { get; set; }
    public DateTime EffectiveDate { get; set; }
    public virtual ICollection<Model> Models { get; set; }
    public virtual ICollection<InternCode> DataReleaseLevels { get; set; }
}

因此,一个Version可以引用多个Model,每个Model都是一个DataCode。但是另一个 Version 可以引用同一组 Model(因此 virtual 关键字,我认为是你这样做的方式)。 PriceLevel 也是一个 DataCode。一个Version也可以有很多个InternCode,每个都是一个DataCode,但那是另外一回事了。无论如何,EF 生成的 DataCode 表中发生了很多事情。

我们有以下DataInitializer代码:

var ModelList = new List<Model>
{
    new Model { Code = "001-230", Description = "Model 230" },
    new Model { Code = "001-231", Description = "Model 231" },
    new Model { Code = "001-232", Description = "Model 232" },
    new Model { Code = "001-233", Description = "Model 233" },
    // and many more
}

var versions = new List<Entities.Version>
{
    new Entities.Version {
        VersionNumber=2.1F,
        Description = "Version 2.1 for Model Group A",
        EffectiveDate = DateTime.Parse("1/15/1995"),
        Models=new List<Model> { 
            ModelList.Find( m => m.Code == "001-230"),
            ModelList.Find( m => m.Code == "001-231"),
            ModelList.Find( m => m.Code == "001-232"),
            ModelList.Find( m => m.Code == "001-233"),
        },
        Status = "Draft"
   },
   new Entities.Version {
       VersionNumber=2.2F,
       Description = "Version 2.2 for Model Group A",
       EffectiveDate = DateTime.Parse("7/15/1995"),
       Models=new List<Model> { 
           ModelList.Find( m => m.Code == "001-230"),
           ModelList.Find( m => m.Code == "001-231"),
           ModelList.Find( m => m.Code == "001-232"),
           ModelList.Find( m => m.Code == "001-233"),
       },
       Status = "Draft"
   },
   new Entities.Version {
       VersionNumber=2.3F,
       Description = "Version 2.3 for Model Group A",
       EffectiveDate = DateTime.Parse("1/15/1996"),
       Models=new List<Model> { 
           ModelList.Find( m => m.Code == "001-230"),
           ModelList.Find( m => m.Code == "001-231"),
           ModelList.Find( m => m.Code == "001-232"),
           ModelList.Find( m => m.Code == "001-233"),
       },
       Status = "Draft"
   }                            
};

保存更改、牺牲一只鸡和所有其他东西后,我们发现数据库中的 DataCode 表正在创建两个名为 Version_VersionIdVersion_VersionId1。第一个具有空值,第二个具有创建的最后一个 Version 记录的 Id。至少,我希望它会为 Model 所属的每个 Version 创建一个新的 Version_VersionId 列。这对我来说似乎非常低效,但至少它会起作用。相反,数据似乎踩在了以前的 Version 引用上。

我希望我们可以使用 FluentAPI 解决这个问题,但我不知道如何解决。有人有什么建议吗?

最佳答案

开始前,解决问题后,还要注意public ICollection<string> Aliases { get; set; }因为不能以这种方式映射。

上下文非常重要。对我来说,您有一个 DataCode 表很奇怪(DataCode 类是抽象的,因此您和 EF 无法创建它)。 无论如何,使用这个上下文

public class TestContext : DbContext
{
    public TestContext(DbConnection connection) : base(connection, true) { }

    public DbSet<InternCode> InternCodes { get; set; }
    public DbSet<Model> Models { get; set; }
    public DbSet<Version> Versions { get; set; }


}

三个表按预期创建。 InternCode 有一个 Version_Id,Model 有一个 Version_Id,因为您没有在 Model 和 InternCode 上指定任何关于版本的信息,所以 EF 假定一个 InternCode(和一个模型)只有一个 Version

要实现单个模型(和单个 InternCode)可以与多个版本相关,您可以执行以下操作:

public class TestContext : DbContext
{
    public TestContext(DbConnection connection) : base(connection, true) { }

    public DbSet<InternCode> InternCodes { get; set; }
    public DbSet<Model> Models { get; set; }
    public DbSet<Version> Versions { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new VersionMap());
    }
}

public class InternCode : DataCode
{
    public string PrimaryRelationalOperator { get; set; }
    public string PrimaryValue { get; set; }
    public string SecondaryRelationalOperator { get; set; }
    public string SecondaryValue { get; set; }

    public virtual ICollection<Version> Versions { get; set; }
}

public class Model : DataCode
{
    public ICollection<string> Aliases { get; set; }
    public bool ExportOnly { get; set; }
    public virtual ICollection<Version> Versions { get; set; }
    public void GetOptions()
    {
        throw new NotImplementedException();
    }
}


public class VersionMap : EntityTypeConfiguration<Version>
{
    public VersionMap()
    {
        // Relationships
        HasMany(t => t.Models)
            .WithMany(t => t.Versions);

        HasMany(t => t.DataReleaseLevels)
            .WithMany(t => t.Versions);
    }
}

在这种情况下,您会看到创建了几个表(表示 n 到 m 关系的表)

关于c# - Entity Framework 代码首先多对多关系不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31976964/

相关文章:

c# - 调用无参数构造函数后具有引用类型成员的 c# 结构的相等性和 gethashcode 覆盖

c# - SonarLint 意图说明

c# - 在 WPF 中动态生成一组具有不同内容的单选按钮

c# - TextTransform 无效转换错误

entity-framework - Entity Framework 6.1 将我的数据库放在哪里?

c# - EF 迁移代码优先。如果列不存在,则将列添加到数据库

c# - 给 Entity Framework 生成的类添加数据注解

c# - Entity Framework /LINQ : Left join defaultifempty fails

java - 如何从 String[] 数组填充 Point[] 数组?

c# - 在 EntityFramework 中使用Where()会导致System.ArgumentException