2017-06-05 38 views
1

关注现在,我使用实体框架具有以下的DbContext类:分离了的DbContext

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

有一些类需要的DbContext用两种Item11sItem2s的依赖关系。所以我的目的是用DbSet类型为DbContext创建一个抽象层(逻辑上独立的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)只要devide当前ItemDbContext上DbContext_Item1和DbContext_Item2 具体类

是的,这是决定。但它是唯一的方式吗?如果我的具体工厂在发动机罩下返回ItemDbContext的实例,那将是非常好的。我能实现它吗?

+0

这有什么错在同一个的DbContext有一个以上的实体?除非这两个实体完全无关,否则没有任何伤害。如果两个实体与关系联系在一起,情况尤其如此。如果你最终在同一个DbContext中有20个实体的大熔炉,那么做一些类似的事情,但否则,呃! – Tipx

+0

@Tipx对于很多场景都是如此,但我的想法是SoC。某些类通过抽象工厂获取具有DbSet特定类型的DbContext实例。如果应用程序具有多种类型的实体,并且有时需要将DbContext分为两种,或反之亦然,那就太好了。然后,我不必重写抽象工厂API(返回类型)和依赖关系类 – Mergasov

+0

在我看来,您正在重新创建UnitOfWork + Repository模式。确保你先知道这一点。 –

回答

0

我认为你需要创建一些基本接口(可以称之为IDatabaseContext):

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

然后你嵌套接口:

IDbContext_Item1 : IDatabaseContext 
IDbContext_Item2 : IDatabaseContext 

而且你ItemDbContext实现了这两个接口。

我同意写所有DbContext方法IDatabaseContext接口并不优雅,但你需要做的只是一个时间

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. 
    } 
}