Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied! <p>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? </p> <p>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.</p> <p>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. </p> <p>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. </p> <p>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 <a href="http://msdn.microsoft.com/en-us/magazine/ee819139.aspx" rel="noreferrer">article</a> describing this approach with NHibernate session (same as EF ObjectContext) in MSDN magazine. </p> <p>Some starting implementation of UnitOfWork and Repository patterns:</p> <p>Context holder and abstract factory for repositories</p> <pre class="lang-cs prettyprint-override"><code>public interface IUnitOfWork { IRepository&lt;MyEntity&gt; MyEntityRepository { get; } // Repositories for other entities SaveChanges(); } </code></pre> <p>Repository for detached entities</p> <pre class="lang-cs prettyprint-override"><code>public interface IRepository&lt;T&gt; where T : class { IQueryable&lt;T&gt; 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); } </code></pre> <p>Disposable implementation of UnitOfWork wrapping Enitity framework</p> <pre class="lang-cs prettyprint-override"><code>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&lt;MyEntity&gt; _myEntityRepository; public IRepository&lt;MyEntity&gt; MyEntityRepository { get { return _myEntityRepository ?? (_myEntityRepository = new GeneralRepository&lt;MyEntity&gt;(_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; } } } } </code></pre> <p>Base repository implementation</p> <pre class="lang-cs prettyprint-override"><code>public class GeneralRepository&lt;T&gt; : IRepository&lt;T&gt; where T : class { private ObjectSet&lt;T&gt; _set; private ObjectContext _context; public GeneralRepository(ObjectContext context) { if (context == null) throw new ArgumentNullException("context"); _context = context; _set = context.CreateObjectSet&lt;T&gt;(); } // Override this method for example if you need Includes public virtual IQueryable&lt;T&gt; 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); } } </code></pre> <p>Usage when selecting data</p> <pre class="lang-cs prettyprint-override"><code>using (var uow = new UnitOfWork(connectionString)) { var entity = uow.MyEntitiesRepository.GetQuery().Single(e =&gt; e.Id == 1); // Do something with entity } </code></pre> <p>Usage when modifing data</p> <pre class="lang-cs prettyprint-override"><code>using (var uow = new UnitOfWork(connectionString)) { uow.MyEntitiesRepository.Update(entity); uow.SaveChanges(); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload