在了解特定的DbContext类之前,如何在EntityRepository中为EF编写通用API时处理DbContext?

时间:2016-09-26 17:55:49

标签: c# entity-framework generics n-tier-architecture

我正在尝试编写一个通用的NTier API库,我可以在我的所有"模块中使用#34; (如UserModule,AccountingModule等),目前使用EF,但数据访问层不应与EF硬连接。问题是,我似乎无法找到一种良好的方式来合并DbContext。

我计划的结构是将通用NTier库作为独立项目,然后在我的Module项目中引用它,其中只是类库和为特定主题区域编写的NTier API。

举个例子,这是我的通用EntityRepository的片段:

public class EntityRepository<TClass> : IEntityRepository<TClass> where TClass : Entity, new()
{
    private DbContext Context => //Not sure what to do here.

    public void Delete<TTableClass>(Guid id) where TTableClass : Entity, new ()
    {
        TTableClass record = Context.Set<TTableClass>().Find(id);
        Context.Set<TTableClass>().Remove(record);
        Context.SaveChanges();
    }

注意,TClass与TTableClass不同。现在在我之前的这个API迭代中,在我决定将内容分成模块之前,它看起来像这样:

public class EntityRepository<TClass, TTableClass> : IEntityRepository<TClass> where TClass : Entity, new()
    where TTableClass : Entity, new ()
{
    private DbContext Context => EntityDbContextFactory<MyDbContext>.GetInstance();

    protected DbSet<TTableClass> DbSet => Context.Set<TTableClass>();

    public void Delete(Guid id)
    {
        TTableClass record = DbSet.Find(id);
        DbSet.Remove(record);
        Context.SaveChanges();
    }

但这只是因为它只是一个上下文所以我知道上下文类将是什么,现在我不知道。显而易见的答案是将上下文类作为通用参数包含在内,但这是一个糟糕的设计,因为这意味着我的服务类必须知道我的存储库层查询数据的方式,漏洞抽象不好。事实上,我之前已经完成了我的通用API之前的2个版本,它看起来像这样:

public abstract class EntityRepository<TClass, TDbContext>
    where TClass : Entity, new ()
    where TDbContext : DbContext, new()
{
    private DbContext Context
    {
        get { return EntityContextFactory<TDbContext>.Current(); }
    }

但这使得我的EntityService和具体的实现定义如下所示:

public abstract class EntityService<TRepositoryClass, TClass, TDbContext>
    where TClass : Entity, new()
    where TDbContext : DbContext, new()
    where TRepositoryClass : EntityRepository<TClass, TDbContext>

public class UserService : EntityService<UserRepository, User, MyDbContext>

哎呀,抽象漏洞太多了。另一个问题是我不能将DbContext类存储为类的成员/属性(因此上面是静态工厂引用),因为我无法保证使用我的库的其他程序员正在使用DI容器< / p>

简而言之,如果符合以下条件,如何使通用API工作:

  1. 我事先并不知道DbContext类型。
  2. 我无法将DbContext类型作为类定义的通用参数传递。
  3. 我无法将DbContext存储为EntityRepository的成员。

0 个答案:

没有答案