DbContext

时间:2017-06-05 23:12:04

标签: c# entity-framework inheritance

现在我将Entity Framework与以下DbContext类一起使用:

public class ItemDbContext : DbContext {
    ...
    public DbSet<Item1> Item1s { get; set; }
    public DbSet<Item2> Item2s { get; set; }
}

有些类需要使用Item11sItem2s作为依赖关系的DbContext。所以我的目的是为DbContext创建一个抽象层,使用DbSet类型(逻辑上将DbContext_Item1和DbContext_Item2分开)。它也可用于实现抽象工厂模式(创建DbContext_Item1或DbContext_Item2实例)。

我的想法:

1)接口

public interface IDbContext_Item1 { 
    DbSet<Item1> Item1s { get; set; }
}
public interface IDbContext_Item2 { 
    DbSet<Item3> Item2s { get; set; }
}

所以我的抽象工厂能够拥有这样的API:

public abstract ItemFactory { 
    public abstract IDbContext_Item1 GetItem1Context;
    public abstract IDbContext_Item2 GetItem2Context;
}

对我来说没问题。但是获取IDbContext_ItemX实例的类并不将其视为DbContext实例(即不能调用类似SaveChanges()等的方法)。不幸的是,任何接口都不能从像DbContext这样的类继承。

2)使用DbContext

方法的扩展接口
public interface IDbContext_Item1 { 
    DbSet<Item1> Item1s { get; set; }
    void SaveChanges;
    // etc
}

在我看来,它非常不优雅。

3) IDbContext_ItemX

的抽象类

但我当前的DbContext实现ItemDbContext不能从多个类继承。

4)在DbContext_Item1和DbContext_Item2 具体类上只需 devide 当前ItemDbContext

是的,这是决定。但这只是方法吗?如果我的具体工厂在引擎盖下返回ItemDbContext的实例,那就太好了。我能实现吗?

2 个答案:

答案 0 :(得分:1)

正如我评论的那样,我首先挑战想要在给定上下文中使用单个实体的原因,但如果您决定继续使用该实体,我会使用通用接口,或者甚至是一般的背景:

interface IDbContext<T> where T : class
{
    IDbSet<T> Set { get; }
}

// Context implement generic Interface
class DbContextItem1 : IDbContext<Item1>
{
    IDbSet<Item1> Set { get; private set; }

    override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Logic to get relevant mappings,
    }
}

// Technically you could also do that.
class DbContextItem1 : IDbContext<Item1>, IDbContext<Item2>
{
    IDbSet<Item1> IDbContext<Item1>.Set { get; }
    IDbSet<Item2> IDbContext<Item2>.Set { get; }

    override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Logic to get relevant mappings,
    }
}

// Generic context.
class DbContextGeneric<T> : IDbContext<T>
{
    IDbSet<T> Set { get; private set; }

    override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Logic to get relevant mappings based on T.
    }
}

答案 1 :(得分:0)

我认为您需要创建一些基本界面(让我们称之为IDatabaseContext):

public interface IDatabaseContext : IDisposable
{
  //base DbContext stuff like SaveChanges here
}

然后你有嵌套的接口:

IDbContext_Item1 : IDatabaseContext
IDbContext_Item2 : IDatabaseContext

您的ItemDbContext实现了两个接口。

我同意在DbContext界面中编写所有IDatabaseContext方法并不优雅,但您只需要执行一次