简单的例子来实现以下目的:
ApplicationDbContext forumDB = new ApplicationDbContext(); MonitorDbContext monitor = new MonitorDbContext();
只需在主上下文中定义属性:(用于创建和维护数据库) 注意:只需使用protected :(实体不在此处公开)
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("QAForum", throwIfV1Schema: false) { } protected DbSet<Diagnostic> Diagnostics { get; set; } public DbSet<Forum> Forums { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<Thread> Threads { get; set; } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } }
MonitorContext: 在这里公开单独的实体
public class MonitorDbContext: DbContext { public MonitorDbContext() : base("QAForum") { } public DbSet<Diagnostic> Diagnostics { get; set; } // add more here }
诊断模型:
public class Diagnostic { [Key] public Guid DiagnosticID { get; set; } public string ApplicationName { get; set; } public DateTime DiagnosticTime { get; set; } public string Data { get; set; } }
如果您愿意,可以将所有实体标记为主ApplicationDbContext中的受保护,然后根据需要为每个模式分隔创建其他上下文。
它们都使用相同的连接字符串,但它们使用单独的连接,因此不要交叉事务并注意锁定问题。通常你的设计分离,所以这不应该发生。
另一点“智慧”。我有一个面向互联网和内部应用程序的数据库。每张脸都有一个背景。这有助于我保持纪律严明,安全的隔离。
您可以为单个数据库设置多个上下文。例如,如果您的数据库包含多个数据库模式,并且您希望将它们作为单独的自包含区域进行处理,那么它可能很有用。
问题是当您想首先使用代码创建数据库时 - 应用程序中只有单个上下文可以做到这一点。这方面的技巧通常是一个附加的上下文,其中包含仅用于创建数据库的所有实体。只包含实体子集的真实应用程序上下文必须将数据库初始化程序设置为null。
在使用多种上下文类型时,您会看到其他问题 - 例如共享实体类型及其从一个上下文传递到另一个上下文等。一般情况下,它可以使您的设计更清晰,并将不同的功能区域分开,但它有它的另外复杂的成本。
这个帖子刚刚在StackOverflow上冒出来,所以我想提供另一个“B)保证这一切都很好”:)
我通过DDD Bounded Context模式正是这样做的。我在我的书“编程实体框架:DbContext”中写过这篇文章,它是我在Pluralsight课程中的一个50分钟模块的焦点 - &gt; http://pluralsight.com/training/Courses/TableOfContents/efarchitecture
灵感来自[@JulieLerman的DDD MSDN Mag Article 2013] [1]
public class ShippingContext : BaseContext<ShippingContext> { 聽 public DbSet<Shipment> Shipments { get; set; } 聽 public DbSet<Shipper> Shippers { get; set; } 聽 public DbSet<OrderShippingDetail> Order { get; set; } //Orders table 聽 public DbSet<ItemToBeShipped> ItemsToBeShipped { get; set; } 聽 protected override void OnModelCreating(DbModelBuilder modelBuilder) 聽 { 聽聽聽 modelBuilder.Ignore<LineItem>(); 聽聽聽 modelBuilder.Ignore<Order>(); 聽聽聽 modelBuilder.Configurations.Add(new ShippingAddressMap()); 聽 } }
public class BaseContext<TContext> DbContext where TContext : DbContext { static BaseContext() { Database.SetInitializer<TContext>(null); } protected BaseContext() : base("DPSalesDatabase") {} }
“如果你正在进行新的开发,并且你想让Code First根据你的类创建或迁移你的数据库,你需要使用包含所有类的DbContext创建一个”模型“。和构建表示数据库的完整模型所需的关系。但是,这个上下文不能继承BaseContext。“ JL
在代码中,您可以拥有多个DBContext和一个数据库。您只需在构造函数中指定连接字符串即可。
public class MovieDBContext : DbContext { public MovieDBContext() : base("DefaultConnection") { } public DbSet<Movie> Movies { get; set; } }
我会反对这个想法,用现实世界的经验来支持我的投票。
我被带到一个大型应用程序,该应用程序有五个上下文用于单个数据库。最后,我们最终删除了除了一个之外的所有上下文 - 恢复到单个上下文。
起初,多个上下文的想法似乎是一个好主意。我们可以将数据访问分离到域中,并提供几个干净的轻量级上下文。听起来像DDD,对吧?这将简化我们的数据访问。另一个论点是性能,因为我们只访问我们需要的上下文。
但实际上,随着我们的应用程序的发展,我们的许多表在各种环境中共享了关系。例如,在上下文1中对表A的查询也需要在上下文2中连接表B.
这给我们留下了几个糟糕的选择。我们可以在各种上下文中复制表。我们试过这个。这创建了几个映射问题,包括要求每个实体具有唯一名称的EF约束。所以我们在不同的上下文中得到了名为Person1和Person2的实体。有人可能会说这是我们糟糕的设计,但尽管我们付出了最大的努力,但这就是我们的应用程序在现实世界中实际增长的方式。
我们还尝试查询两个上下文以获取我们需要的数据。例如,我们的业务逻辑将从上下文1查询其所需内容的一半,而从上下文2查询另一半。这有一些重大问题。我们不得不针对单个上下文执行一个查询,而是必须跨不同的上下文执行多个查询。这有一个真正的性能损失。
最后,好消息是很容易剥离多个上下文。上下文旨在成为轻量级对象。所以我认为性能不是多个上下文的好参数。在几乎所有情况下,我认为单个上下文更简单,更简单,并且可能性能更好,并且您不必实施一系列解决方案来使其工作。
我想到了一种情况,其中多个上下文可能有用。可以使用单独的上下文来修复实际包含多个域的数据库的物理问题。理想情况下,上下文与域一对一,与数据库一对一。换句话说,如果一组表与给定数据库中的其他表没有任何关系,那么它们应该被拉出到一个单独的数据库中。我意识到这并不总是实用的。但是如果一组表格如此不同以至于您可以将它们分成单独的数据库(但您选择不这样做),那么我可以看到使用单独的上下文的情况,但仅仅因为实际上有两个独立的域。
我对你的想法很感兴趣。
我想分享一个案例,我认为在同一个数据库中拥有多个DBContexts的可能性很有意义。
我有两个数据库的解决方案。一个是除了用户信息之外的域数据。另一个仅用于用户信息。该部门主要由欧盟推动 通用数据保护条例 。通过拥有两个数据库,只要用户数据保留在一个安全的位置,我就可以自由地移动域数据(例如从Azure到我的开发环境)。
现在对于用户数据库,我已经通过EF实现了两个模式。一个是AspNet Identity框架提供的默认值。另一个是我们自己实现用户相关的任何其他内容。我更喜欢这个解决方案而不是扩展ApsNet模式,因为我可以轻松处理对AspNet Identity的未来更改,同时分离使程序员清楚地知道“我们自己的用户信息”在我们定义的特定用户模式中。
提醒:如果您组合了多个上下文,请确保切断n粘贴各种功能 RealContexts.OnModelCreating() 进入你的单身 CombinedContext.OnModelCreating() 。
RealContexts.OnModelCreating()
CombinedContext.OnModelCreating()
我只是浪费时间寻找为什么我的级联删除关系没有被保留只是为了发现我没有移植它 modelBuilder.Entity<T>()....WillCascadeOnDelete(); 从我的真实语境到我的组合语境中的代码。
modelBuilder.Entity<T>()....WillCascadeOnDelete();
当我遇到这个设计时,我的直觉告诉了我同样的事情。 我正在开发一个代码库,其中有三个dbContexts到一个数据库。 3个dbcontex中的2个依赖于来自1个dbcontext的信息,因为它提供了管理数据。此设计限制了您如何查询数据。我遇到了这个问题,你无法加入dbcontexts。相反,您需要做的是查询两个单独的dbcontexts然后在内存中进行连接或迭代两者以获得两者的组合作为结果集。问题在于,不是查询特定的结果集,而是将所有记录加载到内存中,然后对内存中的两个结果集进行连接。它可以真的减慢速度。 我会问这个问题“ 的 只因为你可以,你呢? 强> “ 有关我遇到的与此设计相关的问题,请参阅此文章。 指定的LINQ表达式包含对与不同上下文关联的查询的引用