业务逻辑中的实体框架最佳实践?

lee*_*n3o 31 c# linq asp.net entity-framework

我是第一次使用实体框架,并想知道我是否在最佳实践中使用.

我在业务逻辑中创建了一个单独的类来处理实体上下文.我遇到的问题是,在我看到的所有视频中,他们通常将上下文包装在using语句中以确保其关闭,但显然我不能在我的业务逻辑中执行此操作,因为上下文将在我实际关闭之前关闭用它?

所以我正在做什么呢?几个例子:

    public IEnumerable<Article> GetLatestArticles(bool Authorised) 
    {
        var ctx = new ArticleNetEntities();
        return ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
    }

    public IEnumerable<Article> GetArticlesByMember(int MemberId, bool Authorised)
    {
        var ctx = new ArticleNetEntities();
        return ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
    }
Run Code Online (Sandbox Code Playgroud)

我只是想确保当很多人使用它时,我不会构建一些会死的东西?

RPM*_*984 64

这实际上取决于如何公开您的存储库/数据存储.

不确定你的意思是"上下文将被关闭,因此我不能做业务逻辑".做你的业务逻辑使用using语句.或者,如果您的业务逻辑属于不同的类,那么让我们继续.:)

有些人从他们的Repository返回具体集合,在这种情况下,您可以将上下文包装在using语句中:

public class ArticleRepository
{
   public List<Article> GetArticles()
   {
      List<Article> articles = null;

      using (var db = new ArticleNetEntities())
      {
         articles = db.Articles.Where(something).Take(some).ToList();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是满足了连接的良好实践 - 尽可能晚地打开,并尽早关闭.

您可以将所有业务逻辑封装在using语句中.

缺点 - 您的存储库会发现我个人不喜欢的业务逻辑,并且您最终会针对每个特定方案使用不同的方法.

第二个选项 -新出现一个上下文作为存储库的一部分,并使其实现IDisposable.

public class ArticleRepository : IDisposable
{
   ArticleNetEntities db;

   public ArticleRepository()
   {
      db = new ArticleNetEntities();
   }

   public List<Article> GetArticles()
   {
      List<Article> articles = null;
      db.Articles.Where(something).Take(some).ToList();
   }

   public void Dispose()
   {
      db.Dispose();
   }

}
Run Code Online (Sandbox Code Playgroud)

然后:

using (var repository = new ArticleRepository())
{
   var articles = repository.GetArticles();
}
Run Code Online (Sandbox Code Playgroud)

或者第三个选项(我最喜欢的),使用依赖注入.将所有上下文工作与存储库分离,并让DI容器处理资源:

public class ArticleRepository
{
   private IObjectContext _ctx;

   public ArticleRepository(IObjectContext ctx)
   {
      _ctx = ctx;
   }

   public IQueryable<Article> Find()
   {
      return _ctx.Articles;
   }
}
Run Code Online (Sandbox Code Playgroud)

您选择的DI容器会将具体的ObjectContext注入到Repository的实例化中,并使用已配置的生命周期(Singleton,HttpContext,ThreadLocal等),并根据该配置对其进行处理.

我设置它,以便为每个HTTP请求提供一个新的Context.请求完成后,我的DI容器将自动处理上下文.

我还在这里使用工作单元模式,允许多个存储库使用一个对象上下文.

您可能还注意到我更喜欢从我的存储库返回IQueryable(而不是具体的List).更强大(但风险很大,如果你不理解其含义).我的服务层在IQueryable上执行业务逻辑,然后将具体集合返回给UI.

这是我最强大的选择,因为它允许简单的存储库,工作单元管理上下文,服务层管理业务逻辑,DI容器处理资源/对象的生命周期/处置.

如果您想了解更多信息,请告诉我 - 因为它有很多内容,甚至超过这个令人惊讶的长答案.:)

  • 我想知道的是这个最终版本增加了什么?它似乎是实体框架之上的额外抽象,它已经是一个抽象,因为实体框架本身已经实现了工作单元和存储库.为什么使用此存储库类而不是实体datacontext本身? (5认同)
  • 您能否详细解释一下您如何使用工作单元模式?我认为EF ObjectContext实际上是一个UoW. (2认同)