到目前为止,我的印象是DbContext是用来表示数据库的,因此,如果您的应用程序使用一个数据库,那么您只需要一个DbContext。

然而,一些同事希望将功能区域分解为单独的DbContext类。

我相信这是出于一个好的原因——希望保持代码更干净——但它似乎不稳定。我的直觉告诉我这是个坏主意,但不幸的是,我的直觉并不是设计决策的充分条件。

所以我在寻找:

A)为什么这可能是一个坏主意的具体例子;

B)保证这一切都会顺利解决。


当前回答

首先,在代码中,可以有多个DBContext和一个数据库。您只需在构造函数中指定连接字符串。

public class MovieDBContext : DbContext
{
    public MovieDBContext()
        : base("DefaultConnection")
    {

    }
    public DbSet<Movie> Movies { get; set; }
}

其他回答

实现以下简单示例:

    ApplicationDbContext forumDB = new ApplicationDbContext();
    MonitorDbContext monitor = new MonitorDbContext();

只在main上下文中设置属性范围:(用于创建和维护DB) 注意:只使用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。

在使用多种上下文类型时,还会遇到其他问题——例如共享实体类型及其从一个上下文传递到另一个上下文等等。一般来说,这是可能的,它可以使你的设计更干净,并分离不同的功能区域,但它的代价是额外的复杂性。

首先,在代码中,可以有多个DBContext和一个数据库。您只需在构造函数中指定连接字符串。

public class MovieDBContext : DbContext
{
    public MovieDBContext()
        : base("DefaultConnection")
    {

    }
    public DbSet<Movie> Movies { get; set; }
}

另一点“智慧”。我有一个面向互联网和内部应用程序的数据库。每一个面向都有一个上下文。这有助于我保持纪律严明的隔离。

灵感来自@JulieLerman的DDD MSDN Mag文章2013

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。莱托