在EF数据库上下文中使用相同的c#模型两次

时间:2015-10-21 09:18:10

标签: c# entity-framework orm datamapper

我们有一个应用程序,其中复杂数据模型的集合保存在数据存储中 - 我们称之为单独的数据集DataFiles。可以将这些DataFiles调用到编辑器中进行更改,然后在完成后将其保存回存储。该过程与从硬盘驱动器加载Excel文件,编辑然后选择保存或另存为一样。

我们当前的App设计将DataFile存储和DataFile编辑器分成两个数据库和两个数据库上下文。通过这种方式,我们可以为商店和编辑器使用相同的C#模型,并可以将编辑后的DataFile非常简单地映射回商店,反之亦然。在最简单的情况下:

  • 得到A
  • A = B
  • 保存B

这消除了对属性的1:1映射的需要。它还使A向B的注入相对容易,适用于更复杂的数据结构

我们需要移动到商店和编辑器的单个数据库上下文。

问题是 - 在单个数据库上下文中,我们可以将一个C#数据模型绑定到数据库的两个独立数据表吗?

这是我们正在尝试做的一个非常简单的例子。这不起作用,因为EF尝试将两个DbSet定义映射到一个表(称为DataFile)

// C# model
namespace MyApp.Models
{
    public partial class DataFile
    {
        public int Id { get; set; }

        public int MyDataField { get; set; }
        public string MyOtherDataField { get; set; }

    }
}

// Database binding
public class AppDbContext : DbContext
{
    public AppDbContext() : base("name=AppDbContext"){}

    // Store Data File Access
    public virtual DbSet<DataFile> StoreDataFiles { get; set; }

    // Active Data File Access
    public virtual DbSet<DataFile> EditorDataFiles { get; set; }


    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

}

1 个答案:

答案 0 :(得分:0)

这是我认为可以满足您需求的解决方案,唯一需要注意的是ID字段在两个表中都必须是唯一的,并且您需要自己处理。除此之外,这种技术源于here被称为“每种混凝土类型的表格”。

我们要做的是创建一个抽象类,其中包含您的类型具有的属性,并从中继承。这应该使两个类保持同步,并且可以通过来回转换来获得一个或另一个。这里重要的是DatabaseGeneratedAttribute设置为&#39;无&#39 ;;使用这种技术,因为两个表都具有相同的PK,EF不能告诉它需要跨表共享它们。

父类必须是抽象的;至少,这是我能够将它识别为DbSet而不是为它创建表的唯一方法。

public abstract class DataFileParent
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }

        public int MyDataField { get; set; }
        public string MyOtherDataField { get; set; }
    }

public class DataFileEditor : DataFileParent
    {
    }

public class DataFileStore : DataFileParent
    {
    }

现在我们可以创建我们的Context类,只有一个DbSet将在表中共享。我们还要告诉上下文我们要根据实体的具体类型将实体映射到不同的表,这在OnModelCreating方法中完成。

public class Context : DbContext
    {
        public DbSet<DataFileParent> DataFileParents { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<DataFileEditor>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("DataFileEditor");
            });

            modelBuilder.Entity<DataFileStore>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("DataFileStore");
            });
        }
    }

这就是它!现在,当您想要创建DataFileStoreDataFileEditor时,可以这样做,并将其添加为:(假设StoreDataFileStore类型的变量)

using (var db = new Context())
{
    db.DataFileParents.Add(Store);
    db.SaveChanges();
}

我为此设置了一个小控制台应用程序并将其放在GitHub上。