Code First和DBContext的多态性

时间:2015-01-23 15:46:25

标签: c# .net ef-code-first entity-framework-6

我们有一个项目,我们有多个解决方案,共享一个共同的核心库。我们的核心库包含所有与此上下文一起使用的默认实体,数据上下文和实用程序。我希望让web项目扩展核心上下文,但我似乎总是得到无迁移或多个数据库。基本上,我希望能够拥有

namespace Core
{
    public class BaseContext : DbContext
    {
        DBSet<SomeCoreEntity> CoreEntities {get;set;}
    }
}

然后有

namespace Web
{
    public class DerivedContext : Core.BaseContext
    {
        DBSet<SomeNewEntity> NewEntities {get;set;}
    }
}

从这里开始,我希望核心能够拥有

baseContextInstance.CoreEntities

derivedContextInstance.CoreEntites

引用同一个表,但派生的上下文也可以访问NewEntites。这样做的正确方法是什么?它是否需要web.config中的特殊内容,可能是DatabaseInitializerForType?我环顾四周,无法找到有关如何做到这一点的好文档。

1 个答案:

答案 0 :(得分:1)

因此,如果您确保Derived和基本上下文基本上使用相同的ConnectionString键,那么它看起来是可能的。您可以让他们使用不同的密钥,但这只会导致您需要维护的重复。

NB:我正在使用程序包管理器中的update-databaseEnable-Migrations命令。其他部署过程的一般原则应该是相同的,但我还没有对其进行测试。

首先,创建基本上下文(以及相关的DbSet类):

namespace Core
{
    public partial class BaseContext : DbContext
    {
        public BaseContext()
        {

        }

        public BaseContext(string connectionString)
            : base(connectionString)
        {

        }

        public DbSet<SystemUser> SystemUser { get; set; }
    }

    public partial class SystemUser
    {
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public string Forename { get; set; }
        public string Surname { get; set; }
    }
}

接下来,创建您的派生上下文(使用新类):

namespace Web
{
    public class DerivedContext : Core.BaseContext
    {
        public DerivedContext()
            : base("BaseContext")
        {

        }

        public DbSet<Order> Order { get; set; }
    }

    public class Order
    {
        public int Id { get; set; }
        public double Quantity { get; set; }
        public string Item { get; set; }
    }
}

到目前为止,这几乎是你所做的事情但是,请注意两件事:

  1. BaseContext公开一个带连接字符串(或连接字符串键名)的构造函数 - 它传递给DbContext
  2. 中的相同构造函数
  3. 派生上下文传递密钥名称&#34; BaseContext&#34;下至BaseContext
  4. 现在,在Web项目中的.config文件中添加一个连接字符串条目,其密钥名称为BaseContext,以及相应的连接字符串。

    <connectionStrings>
        <add name="BaseContext" connectionString="Data Source=.;Initial Catalog=TestDb;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
    </connectionStrings>
    

    通过在Package Manager控制台中输入以下内容,将迁移添加到Web项目(确保从下拉列表中选择了Web项目):

    Enable-Migrations
    

    输入创建的迁移文件,并在构造函数

    中将AutomaticMigrations更改为true
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }
    

    现在,当您从Web项目发布时,在PM控制台中使用以下内容:

    Update-Database
    

    它会将SystemUserOrder发布到新的数据库(在我的示例中称为TestDb)。


    <强>用法:

    如果您检查数据库,您会注意到它已成功创建了SystemUsers和Orders表。

    如果您从应用程序运行以下代码:

    using (var ctxt = new Core.BaseContext())
    {
        var user1 = new Core.SystemUser()
        {
            Forename = "Obsidian",
            Surname = "Phoenix"
        };
    
        ctxt.SystemUser.Add(user1);
    
        ctxt.SaveChanges();
    }
    
    using (var ctxt = new DerivedContext())
    {
        var user2 = new Core.SystemUser()
        {
            Forename = "John",
            Surname = "Doe"
        };
    
        ctxt.SystemUser.Add(user2);
    
        ctxt.SaveChanges();
    
    
        var users = ctxt.SystemUser.ToList();
    
        users.ForEach(u => Debug.WriteLine(string.Format("{0} {1}", u.Forename, u.Surname)));
    
        var order = new Order()
        {
            Id = 1,
            Item = "Test Item",
            Quantity = 1
        };
    
        ctxt.Orders.Add(order);
    
        ctxt.SaveChanges();
    }
    

    您可以看到我可以使用BaseContext DerivedContext来读取/写入Systemuser,我可以使用{{1读/写DerivedContext