我看过很多有关实现存储库和工作单元的文章。我也看到了一些文章,谈到这样做只是增加了额外的复杂性,因为DbContext已经在使用存储库和工作单元模式。
我将重构一个应用程序,它几乎为每个实体都有一个存储库,并希望尽可能地减少复杂性。
有人能解释/提供文章/博客等,讲解如何使用DbContext而不是我自己的存储库吗?
我看过很多有关实现存储库和工作单元的文章。我也看到了一些文章,谈到这样做只是增加了额外的复杂性,因为DbContext已经在使用存储库和工作单元模式。
我将重构一个应用程序,它几乎为每个实体都有一个存储库,并希望尽可能地减少复杂性。
有人能解释/提供文章/博客等,讲解如何使用DbContext而不是我自己的存储库吗?
private readonly AppContext context = new AppContext();
的步骤。也许你可以将两者结合起来,但这样你仍然需要修改每一个查询类,如果你的数据层发生变化的话。public class Repository : IRepository
{
protected readonly DbContext context;
public Repository(DbContext context)
{
this.context = context;
}
public IEnumerable<TEntity> GetAll<TEntity>()
{
var dbSet = context.Set<TEntity>;
return dbSet.ToList();
}
...
}
我的实际类比那个复杂得多,但这足以说明主要观点。首先,注入上下文。这是我强烈不同意Rob的一个领域。也许如果您在处理上下文时玩得快而松散,您可能不知道“它来自哪里”,但我使用依赖注入容器为每个请求创建一个上下文实例。换句话说,我确切地知道它来自哪里。
其次,因为这是一个带有通用方法的标准老类,我不需要在控制器操作中新建一堆它们。我也不必为每个实体定义单独的存储库类。我只需将此依赖项注入到我的控制器中并执行即可:
public class FooController : Controller
{
private readonly IRepository repo;
public FooController(IRepository repo)
{
this.repo = repo;
}
...
}
Foo
,我只需要执行以下操作:repo.GetAll<Foo>();
如果我想要一些Bar
:
repo.GetAll<Bar>()
。
然后,你可以通过泛型约束开始做一些真正有趣的事情。比如说,我想只提取“已发布”的项目。我所需要的就是一个像这样的接口:
public interface IPublishable
{
PublishStatus Status { get; }
DateTime? PublishDate { get; }
DateTime? ExpireDate { get; }
}
然后,我只需让我想要“可发布”的实体实现此接口或继承实现它的抽象类。一旦所有设置完成,我就可以在我的存储库中执行以下操作:
public IEnumerable<TEntity> GetAllPublished<TEntity>()
where TEntity : IPublishable
{
var dbSet = context.Set<TEntity>();
return dbSet.Where(m =>
m.Status == PublishStatus.Published &&
m.PublishDate.HasValue && m.PublishDate.Value <= DateTime.Now &&
(!m.ExpireDate.HasValue || m.ExpireDate.Value > DateTime.Now)
).ToList();
}
现在,我有一个方法在一个存储库中,可以仅提取实现了IPublishable
接口的任何实体的已发布项。代码重复最少,并且更重要的是,如果我需要将数据访问层切换到其他东西,比如不同的ORM甚至Web API,我只需要更改这个存储库类。所有其余的代码都可以愉快地运行,就好像什么也没有发生。