实体框架中的仓库模式4何时应该处理? [英] Repository Pattern in Entity framework 4 when should we dispose?

查看:85
本文介绍了实体框架中的仓库模式4何时应该处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新增到EF,我注意到使用存储库模式可以真正简化事情,并允许我做一些嘲笑也是如此。

New to EF and I have noticed that using a repository pattern can really simplify things and will allow me to do some mocking too.So far so good.

我的问题

objectContext的一个典型用法是尽快销毁,见下文

A typical usage of the objectContext is to destroy as soon as possible see below

using (var context = new SchoolEntities())
{    
    context.AddToDepartments(department);    
    context.SaveChanges();
}

使用Repository模式,我注意到没有人实际使用使用模式例如

Using the Repository pattern I have noticed that nobody actually uses the "Using Pattern" eg

using (var repository= new Repository<Student>(new MyContext))
{    
    repository.Add(myStudentEntity)  
    repository.SaveChanges();
}

这个想法应该是尽快处理上下文记忆可能泄漏或变得非常大?

Should the idea be that we should dispose of the context as soon as possible otherwise the memory might leak or get very big?

任何人都可以澄清吗?非常感谢。

Can anyone clarify? Thanks a lot.

推荐答案

是的,即使您正在使用存储库,也应该处理上下文。不清楚您的Repository实现给您什么优势,因为您仍然提供ObjectContext作为构造函数的参数,不是吗?

Yes you should dispose context even if you are using repository. It is not clear what advantage does your Repository implementation give you because you are still providing ObjectContext as constructor's parameter, aren't you?

IMO使用Repository和自定义UnitOfWork的主要原因是持久性无知=高层应用程序层的EF代码,因为ObjectContext + ObjectSet本身是库和工作模式的实现

IMO the main reason for using Repository and custom UnitOfWork is persistance ignorance = hidding EF code from upper application layers because ObjectContext + ObjectSet themselves are implementation of repository and unit of work patterns.

如果我正在使用存储库,我总是包装整个EF代码,所以我的存储库的公共接口不提供有关EF相关基础设施的任何信息。在这种情况下,这取决于我如何处理ObjectContext。

If I'm using repository, I'm always wrapping whole EF code, so the public interface of my repository doesn't provide any information about EF related infrastructure. In that case it is up to me how I deal with ObjectContext.

为了方便直接的CRUD方案,我可以将上下文创建和处理包装到每个存储库方法中。在更复杂的场景中,我使用了额外的类 - UnitOfWork(UoW),它包含上下文创建和处理,并且触发将更改保存到数据库中。它还作为所有存储库的工厂,并将创建的上下文的实例传递到存储库的构造函数中。

For easy straight forward CRUD scenarios, I can wrap context creation and disposing into each repository method. In more complex scenarios I'm using additional class - UnitOfWork (UoW), which wraps context creation and disposing and it triggers saving changes into database. It also acts as factory for all repositories and passes instance of created context into repositories' constructors.

大部分时间我是编程服务或Web应用程序,所以我正在处理分离的对象。我总是使用单个UoW实例进行请求处理。所以UoW是在请求处理开始时创建的,并在请求处理结束时发布。在WinForms / WPF应用程序和附加对象的情况下,我认为最好的想法是在每个窗体中都有U/ ObjectContext - 文章在MSDN杂志中使用NHibernate会话(与EF ObjectContext相同)描述了这种方法。

Most of the time I'm programming services or web applications so I'm dealing with detached objects. I'm always using single UoW instance for request processing. So the UoW is created at the beginning of request processing and released at the end of request processing. In case of WinForms / WPF applications and attached objects I think the good idea is to have UoW / ObjectContext instance "per form" - there is article describing this approach with NHibernate session (same as EF ObjectContext) in MSDN magazine.

有些开始实现UnitOfWork和Repository模式:

Some starting implementation of UnitOfWork and Repository patterns:

存储库的上下文持有者和抽象工厂

Context holder and abstract factory for repositories

public interface IUnitOfWork
{
  IRepository<MyEntity> MyEntityRepository { get; }
  // Repositories for other entities

  SaveChanges();
}

分离实体的存储库

public interface IRepository<T> where T : class
{
  IQueryable<T> GetQuery();
  void Insert(T entity);
  void Delete(T entity);

  // In very complex scenarios with big object graphs you will probably give up
  // using detached approach and you will always load your entities from DB before
  // deleting or updating them. In such case you will not need Update method at all.

  void Update(T entity);
}

UnitOfWork包装的一次性实现Enitity框架

Disposable implementation of UnitOfWork wrapping Enitity framework

public class UnitOfWork : IUnitOfWork, IDisposable
{
   private ObjectContext _context = null;

   public UnitOfWork(string connectionString)
   {
     if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");
     _context = new ObjectContext(connectionString);
   }

   private IRepository<MyEntity> _myEntityRepository;

   public IRepository<MyEntity> MyEntityRepository
   {
     get
     {
        return _myEntityRepository ?? (_myEntityRepository = new GeneralRepository<MyEntity>(_context));
     }
   }

   public void SaveChanges()
   {
     _context.SaveChanges();
   }

   public void Dispose()
   {
     Dispose(true);
     GC.SuppressFinalize(this);
   }

   protected virtual void Dispose(bool disposing)
   {
     if (disposing)
     {
       if (_context != null)
       {
         _context.Dispose();
         _context = null;
       }
     }
   }
}

Base存储库实现

public class GeneralRepository<T> : IRepository<T> where T : class
{
  private ObjectSet<T> _set;
  private ObjectContext _context;


  public GeneralRepository(ObjectContext context)
  {
    if (context == null) throw new ArgumentNullException("context");
    _context = context;
    _set = context.CreateObjectSet<T>();
  }

  // Override this method for example if you need Includes
  public virtual IQueryable<T> GetQuery()
  {
    return _set;
  }

  // Override following methods if you are working with object graphs.
  // Methods do not execute operations in database. It is responsibility of 
  // UnitOfWork to trigger the execution

  public virtual void Insert(T entity)
  {
    if (entity == null) throw new ArgumentNullException("entity");
    _set.AddObject(entity);
  }

  // These impelementations are for detached scenarios like web application

  public virtual void Delete(T entity)
  {
    if (entity == null) throw new ArgumentNullException("entity");
    _set.Attach(entity);
    _set.DeleteObject(entity);
  }

  public virtual void Update(T entity)
  {
    if (entity == null) throw new ArgumentNullException("entity");
    _set.Attach(entity);
    _context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
  }
}

选择数据时的使用

using (var uow = new UnitOfWork(connectionString))
{
  var entity = uow.MyEntitiesRepository.GetQuery().Single(e => e.Id == 1);
  // Do something with entity
}

修改数据时的用法



Usage when modifing data

using (var uow = new UnitOfWork(connectionString))
{
  uow.MyEntitiesRepository.Update(entity);
  uow.SaveChanges();
}

这篇关于实体框架中的仓库模式4何时应该处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆