【问题标题】:Polymorphism with Code First and DBContextCode First 和 DBContext 的多态性
【发布时间】:2015-01-23 15:46:24
【问题描述】:

我们有一个项目,我们有多个共享一个共同核心库的解决方案。我们的核心库拥有我们所有的默认实体、数据上下文和使用此上下文的实用程序。我想让 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?我环顾四周,找不到任何关于如何执行此操作的好的文档。

【问题讨论】:

  • 您是否尝试过使用 Partial 类?将 Core 类设置为 public partial class,在网站中也是如此。您可能需要将该类周围的网站命名空间更改为 Core 而不是 web。另外,我怀疑您需要从网站内部而不是核心库内部进行数据库迁移。否则核心只能看到自身内部的类。
  • 你不能跨程序集有一个分部类。一旦我们构建了我们的核心库,元数据就会被写入,并且类不再是部分的。
  • 啊,你是对的。我认为你可以,但显然我从未真正尝试过。

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


【解决方案1】:

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

注意:我正在使用来自包管理器的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. 派生上下文将键名“BaseContext”向下传递给BaseContext

现在,在 Web 项目中的 .config 文件中添加一个连接字符串条目,键名为 BaseContext 和适当的连接字符串。

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

通过在包管理器控制台中输入以下内容来向 Web 项目添加迁移(确保从下拉列表中选择了 Web 项目):

Enable-Migrations

输入创建的Migration文件,在构造函数中将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();
}

你可以看到我可以同时使用BaseContextDerivedContext来读/写Systemuser,我可以使用DerivedContext读/写@ 987654342@.

【讨论】:

  • 这 95% 把我带到了我需要去的地方。唯一的问题似乎是数据播种。首先引用哪个上下文的初始化程序将运行,因此我必须添加一个快速调用以从 Application_Start 中的派生上下文中获取一些对象,以确保数据加载。有点hacky,但它似乎工作得很好。
  • 其实我可以直接调用derivedContext.Database.Initialize(false);对我来说闻起来少了很多。
  • 是的,这听起来确实不那么老套了。很高兴它有帮助。
猜你喜欢
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
相关资源
最近更新 更多