JB0*_*B06 3 asp.net-mvc entity-framework unit-of-work repository-pattern
我看过很多关于实现存储库和工作单元的文章.我还看过有关如何添加额外复杂性的文章,因为DbContext已经在使用存储库和工作单元模式.
我将重构一个几乎每个实体都有一个存储库的应用程序,并希望尽可能多地删除复杂性.
任何人都可以解释/提供文章/博客/等链接,解释如何使用DbContext而不是我自己的存储库?
Rob Conery是个聪明人,但我不得不在这个问题上与他不同意.他建议的命令/查询方法只是从动作中删除查询逻辑(这是一些东西,但不多).仍然没有真正的抽象.并且,基本控制器方法也不是很好.虽然数据访问方法(这里是一个ORM)被抽象到代码中的一个位置,以便在将来稍微更改一些,但它无法抽象API来处理该数据层,因此它几乎变得毫无意义.它真正拯救你的唯一一件事就是必须放在private readonly AppContext context = new AppContext();每个控制器的顶部.您也许可以将两者结合起来,但是如果数据层发生变化,您仍然需要修改每个查询类.
我认为这里的主要问题是每个人都在努力实现不同的目标.Rob的建议方法是为了保持DRY.就个人而言,我抽象数据层的目的是为了能够在以后轻松切换数据访问方法.也许那是因为我过去已经被烧掉了,选择了一些获取数据的方法,从长远来看,这些方法最终无法理解.但我们至少都同意,传统的存储库实现方式是一个坏主意.
事实上,这是一个没有真正答案的问题.在某种程度上,您必须做最适合您和您的应用的事情.我已经解决的方法有点类似于存储库模式,我使用泛型方法而不是泛型类.类似于以下内容:
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();
}
...
}
Run Code Online (Sandbox Code Playgroud)
我的实际课程比这复杂得多,但这足以说明要点.首先,注入上下文.这是我强烈不同意Rob的一个领域.也许如果你在你的上下文中快速和松散地玩,你可能不知道"它来自哪里",但我使用依赖注入容器,它根据我的上下文请求创建一个实例.换句话说,我确切地知道它来自哪里.
其次,因为这是一个带有泛型方法的标准旧类,所以我不需要在我的控制器操作中新建它们.我也不必为每个实体定义单独的存储库类.我可以简单地将这一个依赖项注入我的控制器并滚动:
public class FooController : Controller
{
private readonly IRepository repo;
public FooController(IRepository repo)
{
this.repo = repo;
}
...
}
Run Code Online (Sandbox Code Playgroud)
然后,如果我想获取一些Foos,我只是这样做:
repo.GetAll<Foo>();
Run Code Online (Sandbox Code Playgroud)
或者,如果我想要一些Bars : repo.GetAll<Bar>().
然后,您可以通过通用约束开始做有趣的事情.假设我希望能够只提取"已发布"的项目.我需要的只是一个界面:
public interface IPublishable
{
PublishStatus Status { get; }
DateTime? PublishDate { get; }
DateTime? ExpireDate { get; }
}
Run Code Online (Sandbox Code Playgroud)
然后,我只是将我希望成为"可发布"的任何实体实现此接口,或者从实现它的抽象类继承.一旦完成设置,我现在可以在我的存储库中执行以下操作:
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();
}
Run Code Online (Sandbox Code Playgroud)
现在,我在一个存储库中有一个方法可以为任何实现的实体提取已发布的项目IPublishable.代码重复是最基本的,更重要的是,如果我需要用不同的ORM甚至Web API切换数据访问层,我只需要更改这个存储库类.我所有其余的代码都快乐地笑着,好像什么都没发生一样.
| 归档时间: |
|
| 查看次数: |
3362 次 |
| 最近记录: |