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

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

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

所以我在寻找:

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

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


当前回答

单个数据库可以有多个上下文。例如,如果您的数据库包含多个数据库模式,并且您希望将每个模式作为独立的自包含区域来处理,那么它就很有用。

问题是,当您想首先使用代码来创建数据库时,只有应用程序中的单个上下文可以做到这一点。这样做的技巧通常是一个额外的上下文,其中包含仅用于数据库创建的所有实体。仅包含实体子集的实际应用程序上下文必须将数据库初始化式设置为null。

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

其他回答

单个数据库可以有多个上下文。例如,如果您的数据库包含多个数据库模式,并且您希望将每个模式作为独立的自包含区域来处理,那么它就很有用。

问题是,当您想首先使用代码来创建数据库时,只有应用程序中的单个上下文可以做到这一点。这样做的技巧通常是一个额外的上下文,其中包含仅用于数据库创建的所有实体。仅包含实体子集的实际应用程序上下文必须将数据库初始化式设置为null。

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

My gut told me the same thing when I came across this design. I am working on a code base where there are three dbContexts to one database. 2 out of the 3 dbcontexts are dependent on information from 1 dbcontext because it serves up the administrative data. This design has placed constraints on how you can query your data. I ran into this problem where you cannot join across dbcontexts. Instead what you are required to do is query the two separate dbcontexts then do a join in memory or iterate through both to get the combination of the two as a result set. The problem with that is instead of querying for a specific result set you are now loading all your records into memory and then doing a join against the two result sets in memory. It can really slow things down. I would ask the question "just because you can, should you?" See this article for the problem I came across related to this design. The specified LINQ expression contains references to queries that are associated with different contexts

首先,在代码中,可以有多个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中将所有实体标记为受保护的,然后根据需要为每个模式分离创建额外的上下文。

它们都使用相同的连接字符串,但是它们使用不同的连接,因此不要交叉事务并注意锁定问题。一般来说,你的设计是分离的,所以这种情况不应该发生。

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