I am trying to create a Repository & UnitOfWork for Data Access Layer. In my current implementation I have to modify my UnitOfWork everytime I create a new repository. I would like to avoid that and also keep the functionality to extend my repository abstract class.
Following is my generic Repository & UnitOfWork interface & classes
public interface IRepositoryBase<T> where T : class
{
IList<T> FindAll();
T FindByCondition(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
}
public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
protected DBContext _dbContext { get; set; }
public RepositoryBase(DBContext dbContext)
{
_dbContext = dbContext;
}
//other methods removed
public void Create(T entity)
{
_dbContext.Set<T>().Add(entity);
}
}
public interface IUnitOfWork
{
IReminderRepository Reminder { get; }
void Save();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
protected DBContext _dbContext { get; set; }
private IReminderRepository _reminderRepository;
public UnitOfWork(DBContext dbContext)
{
_dbContext = dbContext;
}
public IReminderRepository Reminder
{
get
{
return _reminderRepository = _reminderRepository ?? new ReminderRepository(_dbContext);
}
}
public void Save()
{
_dbContext.SaveChanges();
}
public void Dispose()
{
_dbContext.Dispose();
}
}
Here I can extend my Repository as per my specific needs by implementing the specific Repository as
public interface IReminderRepository : IRepositoryBase<Reminder>
{
IList<Reminder> GetAllReminders();
Reminder GetReminderById(Guid id);
Reminder GetReminderByName(string name);
void CreateReminder(Reminder reminder);
void UpdateReminder(Reminder reminder);
void DeleteReminder(Reminder reminder);
}
public class ReminderRepository : RepositoryBase<Reminder>, IReminderRepository
{
public ReminderRepository(DBContext dbContext)
: base(dbContext)
{
_dbContext = dbContext;
}
//other methods removed
public Reminder GetReminderByName(string name)
{
return FindAll()
.OrderByDescending(r => r.Name)
.FirstOrDefault(r => r.Name == name);
//return FindByCondition(r => r.Name == name);
}
}
This is ok but when ever I will create a new Specific Repository I will have to modify the UnitOfWork class as well by adding a new property for the new Repository.
While searching online I found following but it does not work in my case as my RepositoryBase is an abstract class.
public interface IUnitOfWork
{
void Save();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DBContext _dbContext { get; set; }
private readonly Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
public Dictionary<Type, object> Repositories
{
get { return _repositories; }
set { Repositories = value; }
}
public UnitOfWork(DBContext dbContext)
{
_dbContext = dbContext;
}
public IRepositoryBase<T> Repository<T>() where T : class
{
if (Repositories.Keys.Contains(typeof(T)))
{
return Repositories[typeof(T)] as IRepositoryBase<T>;
}
IRepositoryBase<T> repo = new RepositoryBase<T>(_dbContext);//This does not work
Repositories.Add(typeof(T), repo);
return repo;
}
public void Save()
{
_dbContext.SaveChanges();
}
}
You obviously need to get a reference to a IReminderRepository somewhere in your code to be able to use the remainder specific APIs.
If you don't want to extend your UnitOfWork class to return an IReminderRepository, you may create one yourself in the method that actually uses the specific repository, e.g.:
using (var context = new DBContext())
{
IUnitOfWork uow = new UnitOfWork(context);
ReminderRepository repository = new ReminderRepository(context);
Reminder remainder = repository.GetReminderByName("...");
remainder.SomeProperty = "updated value..";
uow.Save();
}
The only purpose of using the unit of work is to be able to share the same context between several different repositories anyway. Exposing a Dictionary<Type, object> in your UnitOfWork won't solve anything as the purpose of using generics is to provide compile-time type safety.
Related
I am trying to implement UOW with repository pattern in my application.
While the independent repository is in place, but while multiple repositories in one transaction (UOW) is driving me crazy.
EF Relation One Customer - Many CustomerContacts
IUnitOfWork
public interface IUnitOfWork
: IDisposable
{
void InitTransaction();
void Rollback();
void CommitTransaction();
}
BaseUOW
public class UnitOfWork :
IUnitOfWork
{
protected DbContextTransaction _transaction;
#region IUnitOfWork
public void CommitTransaction()
{
_transaction.UnderlyingTransaction.Commit();
}
public void Rollback()
{
_transaction.UnderlyingTransaction.Rollback();
}
#endregion IUnitOfWork
}
CustomerUOW
public class CustomerUOW
: UnitOfWork
{
private IRepository<CustomerRepository> _customerRepository;
private IRepository<CustomerContactRepository> _customerContactRepository;
public BranchUOW(IRepository<CustomerRepository> customerRepository,
IRepository<CustomerContactRepository> customerContactRepository)
{
_customerRepository= customerRepository;
_customerContactRepository= customerContactRepository;
}
public override void InitTransaction()
{
_transaction.Commit();
}
}
How do I implement my CustomerUOW so that Customer &
CustomerContact repository share the same DbContext & goes in one
transaction??
Note: Each repository has an implementation of CRUD in their separate class. like
public class EntityRepository<C, T>
: BaseRepository<FoodieTenantContext, T>
where T : class
where C : CustomerContext
{
private DbSet<T> _dataSet
{
get
{
return _ctx.Set<T>();
}
}
public EntityRepository(FoodieTenantContext ctx)
: base(ctx)
{
}
public override void Add(T entity)
{
_dataSet.Add(entity);
}
public override void Delete(T entity)
{
throw new NotImplementedException();
}
public override IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dataSet.Where(predicate).ToList<T>();
}
public override IEnumerable<T> GetAll()
{
return _dataSet.ToList<T>();
}
public override IQueryable<T> GetQuery()
{
return _dataSet;
}
public override int Save()
{
return _ctx.SaveChanges();
}
public override T Single(Expression<Func<T, bool>> predicate)
{
return _dataSet.Where(predicate).SingleOrDefault();
}
public override void Update(T entity)
{
_dataSet.Attach(entity);
_ctx.Entry<T>(entity).State = EntityState.Modified;
}
}
Thanks
On way would be to provide a Func<FoodieTenantContext, IRepository<CustomerContactRepository>> in your CustomerUow
public abstract class UnitOfWork : IUnitOfWork
{
public UnitOfWork(FoodieTenantContext context)
{
this.Context = context;
}
// ... rest of the class
}
// usage could be like the following
public class CustomerUOW : UnitOfWork
{
public CustomerService(Func<FoodieTenantContext, IRepository<CustomerRepository>> customerRepo
, Func<FoodieTenantContext, IRepository<CustomerContactRepository>> contactRepo
, FoodieTenantContext context)
: (context)
{
_customerRepo = customerRepo(context);
_contactRepo = contactRepo(context);
}
}
Another option would be to create a RepositoryFactory, but this would mean you would have to expose a Context property from IRepository<T>
public class RepositoryFactory
{
IServiceProvider _ioc; // This would be your IoC/DI Container
public RepositoryFactory(IServiceProvider ioc)
{
_ioc = ioc;
}
// Resolve T passing in the provided `FoodieTenantContext` into the constructor
public IRepository<T> CreateRepository<T>(FoodieTenantContext context) =>
_ioc.Resolve<T>(context);
}
Another solution could be (my least favourite) would be to expose methods in a RepositoryFactory for each type of IRepository<T>
public class RepositoryFactory
{
public IRepository CreateCustomerContactRepository(FoodieTenantContext context) =>
return new CustomerContactRepository(context);
}
Registering Func in Castle.Windsor
As per comment, to register Func<T> in Castle.Windsor you can try something like the following which is a modified version of Anton's answer to Func injecting with Windsor container question.. (I am not able to test this right now)
Container.Register(
Component.For<Func<FoodieTenantContext, IRepository<CustomerRepository>>>()
.Instance((FoodieTenantContext context) => Container.Resolve<IRepository<CustomerRepository>>(new {context = context}))
)
Otherwise you could try playing around with AsFactory(). For more info read Windsor documentation
And as a last resort, you can always fallback to manually creating a factory or switching IoC/DI containers that support Func<[TIn1, TIn2, ...], T> out of the box, or at least natively.
It's a week I have been dealing with Repository pattern, somehow I have implemented something, a generic repository:
private CentralEntities db = null;
private DbSet<T> table = null;
public RepositoryTest()
{
this.db = new CentralEntities();
table = db.Set<T>();
}
public RepositoryTest(CentralEntities db)
{
this.db = db;
table = db.Set<T>();
}
public IEnumerable<T> SelectAll()
{
return table.Take(10).ToList();
}
Here is my IRepository:
public interface IRepositoryTest<T> where T:class
{
IEnumerable<T> SelectAll();
}
Here in my Controller I implemented like the following and it works:
public class DashbrdController : Controller
{
IRepositoryTest<Event> _repository = null;
public DashbrdController(IRepositoryTest<Event> _repository)
{
this._repository = _repository;
}
public DashbrdController()
{
this._repository = new RepositoryTest<Event>();
}
public ActionResult DashBrd()
{
var rslt= _repository.SelectAll().Take(10);
return View(rslt);
}
}
First I do not how to implement Iunitofwork and UnitOfWork, and second apart from creating a single gate for update or insert, whats the usage of UnitOfWork? what kind of problem can it solve in the above example?
Please refer to the section below for detail understanding of UOW and Repository:
1) You create Generic Repository (The base of all the data source):
public class GenericRepository : IGenericRepository where T :
class
{
protected DbContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable();
}
public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IEnumerable<T> query = _dbset.Where(predicate).AsEnumerable();
return query;
}
public virtual T GetSingle(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
T query = _dbset.Where(predicate).FirstOrDefault();
return query;
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = EntityState.Modified;
}
public virtual void Attach(T entity)
{
_dbset.Attach(entity);
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
2) Then you create a Unit Of Work (Generic that adds the instance of Repository)
public sealed class GenericUnitOfWork : IGenericUnitOfWork, IDisposable
{
private ApplicationDbContext entities = null;
private ApplicationUserManager _userManager;
public GenericUnitOfWork()
{
entities = new ApplicationDbContext();
}
public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public IGenericRepository<T> Repository<T>() where T : class
{
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as IGenericRepository<T>;
}
IGenericRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
return repo;
}
public int Commit()
{
return entities.SaveChanges();
}
private bool disposed = false;
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
3) Then you call UnitOfWork from your controller, that creates instance of Repository in Generic Form
public class DashbrdController : Controller
{
private GenericUnitOfWork uow = null;
public DashbrdController()
{
uow = new GenericUnitOfWork();
}
public ActionResult DashBrd()
{
var rslt = uow.Repository<Event>().GetAll().ToList();
return View(rslt);
}
}
The unit of work class coordinates the work of multiple repositories by creating a single database context class shared by all of them.
For a specific user action (say adding a event), all the transactions like insert/update/delete and so on are done in one single transaction, rather then doing multiple database transactions. This means, one unit of work here involves insert/update/delete operations, all in one single transaction.
Please make the interfaces with the implementation classes provided above. Let me know if problem occurs in that.
Hope if helps.
I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.
Here is my Repository Base Interface:
public interface IRepositoryBase<T> where T : class
{
void Add(T entity, string userGuid = "");
void Delete(T entity);
// ... removed other method signatures for brevity
}
My Repository base implementation:
public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
private Guid? currUserGuid = null;
private D dataContext;
protected D DataContext
{
get
{
if (dataContext == null)
dataContext = new D();
return dataContext;
}
set { dataContext = value; }
}
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return DataContext.Set<T>().Where(predicate);
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = DataContext.Set<T>();
return query;
}
public virtual void Delete(T entity)
{
OperationStatus stat = TryDelete(entity);
}
// .... removed rest for brevity
}
Interface and implementation for concrete class:
public interface ICustomerRepository : IRepositoryBase<Customer>
{
Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
public Customer GetCustomerAndStatus( Guid custGuid )
{
return DataContext.Customers.Include( x => x.CustStatusType )
.SingleOrDefault( x => x.PKGuid == custGuid );
}
}
My Ninject dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public IKernel Kernel { get { return kernel; } }
private void AddBindings()
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
// ... other bindings are omitted for brevity
}
}
and finally, here is my Entity Framework generated DBContext:
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base("name=PCDataEFContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
}
All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.
Babu.
Could you do it like this?
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base(Util.GetTheConnectionString())
{ }
}
public class MyDerivedContext : PCDataEFContext
{
public MyDerivedContext()
: base()
{ }
}
class Util
{
public static string GetTheConnectionString()
{
// return the correct name based on some logic...
return "name=PCDataEFContext";
}
}
Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:
protected D DataContext
{
get
{
if (dataContext == null)
{
dataContext = new D();
dataContext.Database.Connection.ConnectionString = "the new connectionstring";
}
return dataContext;
}
set { dataContext = value; }
}
In my backend service I use unit of work pattern. I was wondering if I'm missing something related to disposing objects.
First, this is the code I have so far, which works. The service just calls a request handler:
[GlobalExceptionHandlerBehaviour(typeof(GlobalExceptionHandler))]
public class CustomerService : ICustomerService
{
public void AddCustomer(AddCustomerRequest request)
{
ObjectFactory.GetInstance<AddCustomerRequestHandler>().Execute(request);
}
}
The request handler looks like:
public class AddCustomerRequestHandler
{
private readonly IUnitOfWork _unitOfWork;
private readonly ICustomerRepository _customerRepository;
public AddCustomerRequestHandler(IUnitOfWork unitOfWork, ICustomerRepository customerRepository)
{
_unitOfWork = unitOfWork;
_customerRepository = customerRepository;
}
public void Execute(AddCustomerRequest request)
{
var customer = new Customer(request.Id, request.CompanyName);
_customerRepository.Add(customer);
_unitOfWork.Commit();
}
}
The unit of work is defined as follows:
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory<EfTrackerDbContext> _databaseFactory;
private EfTrackerDbContext _dataContext;
public UnitOfWork(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
{
_databaseFactory = databaseFactory;
}
public EfTrackerDbContext DataContext
{
get { return _dataContext ?? (_dataContext = _databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
The EfTrackerDbContext is the actual EF context:
public class EfTrackerDbContext : DbContext, IUnitOfWork
{
public DbSet<Customer> Customers { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().ToTable("Customer");
}
}
And the DatabaseFactory is like:
public class DatabaseFactory<TContext> : DisposableObject, IDatabaseFactory<TContext> where TContext : DbContext, new()
{
private TContext _dataContext;
public TContext Get()
{
return _dataContext ?? (_dataContext = new TContext());
}
protected override void DisposeManagedResources()
{
if (_dataContext != null)
{
_dataContext.Dispose();
_dataContext = null;
}
}
}
The CustomerRepository:
public interface ICustomerRepository : IRepository<Customer>
{
IQueryable<Customer> Customers { get; }
}
public class CustomerRepository : RepositoryBase<EfTrackerDbContext, Customer>, ICustomerRepository
{
public CustomerRepository(IDatabaseFactory<EfTrackerDbContext> databaseFactory)
: base(databaseFactory)
{
}
public IQueryable<Customer> Customers
{
get { return DataContext.Customers; }
}
}
As you see, everything is injected. Registration looks like:
For<IDatabaseFactory<EfTrackerDbContext>>().HybridHttpOrThreadLocalScoped().Use<DatabaseFactory<EfTrackerDbContext>>();
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ICustomerRepository>().HybridHttpOrThreadLocalScoped().Use<CustomerRepository>();
Now, the question is about disposing the objects. The only place where IDisposable is implemented is DatabaseFactory, where _datacontext is disposed. I guess that is not enough, so I have following questions:
AddCustomerRequestHandler is injected, so it gets disposed if AddCustomer() service operation ends and garbage collection starts. Is this ok, or should I explicitely call Dispose on the AddCustomerRequestHandler at the end of the AddCustomer() operation and so have it implement IDisposable?
Should UnitOfWork also implement IDisposable, and do I have to call it explicitely?
How to dispose the EfTrackerDbContext ?
Other remarks?
In short, I'm looking for the right way to have everything disposed as soon as the service operation ends.
Thanks for the advice,
L
Whenever you use something that implements IDisposable you should Dispose it as soon as you don't need it any more.
If you use it as a field in a class, implement IDisposable in that class and iterate this process.
PS:
If you turn on Code Analysis like this:
you will get some warnings pointing you to this for free :D
Hi I am using Unity to manage my service layers, which in turn speak to UnitOfWork which manages all the repositories.
Some of my services call other services, my question is how can i pass the same UnitOfWork between service layers?
In my case all controller actions are initiated from a GUI on each button action or event on a timer, this is why I have a factory to create UnitOfWork on demand, but it is causing issues as i dont know how to pass this UnitOfWork between services.
Especially difficult is knowing how to get this specific UnitOfWork instance injected into the service constructor. Please note that some of the services may be long running (10 minutes or so on a background thread), i don't know if that has any impact on the design or not.
Currently the service that is called from the other service is then creating its own UnitOfWork which is causing issues for both transactional design, and Entity framework entity tracking.
Suggestions very welcome!
class OtherService : IOtherService
{
public OtherService(IUnitOfWorkFactory unitOfworkFactory,
ISettingsService settingsService)
{
UnitOfWorkFactory = unitOfworkFactory;
SettingsService = settingsService;
}
IUnitOfWorkFactory UnitOfWorkFactory;
ISettingsService SettingsService;
function SomeSeviceCall()
{
// Perhaps one way is to use a factory to instantiate a
// SettingService, and pass in the UnitOfWork here?
// Ideally it would be nice for Unity to handle all of
// the details regardless of a service being called from
// another service or called directly from a controller
// ISettingsService settingsService =
// UnityContainer.Resolve<ISettingService>();
using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
{
var companies = uow.CompaniesRepository.GetAll();
foreach(Company company in companies)
{
settingsService.SaveSettings(company, "value");
company.Processed = DateTime.UtcNow();
}
uow.Save();
}
}
}
class SettingsService : ISettingsService
{
public SettingsService(IUnitOfWorkFactory unitOfworkFactory)
{
UnitOfWorkFactory = unitOfworkFactory;
}
IUnitOfWorkFactory UnitOfWorkFactory;
// ISettingsService.SaveSettings code in another module...
function void ISettingsService.SaveSettings(Company company,
string value)
{
// this is causing an issue as it essentially creates a
// sub-transaction with the new UnitOfWork creating a new
// Entiy Framework context
using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
{
Setting setting = new Setting();
setting.CompanyID = company.CompanyID;
setting.SettingValue = value;
uow.Insert(setting);
uow.Save();
}
}
}
Hi I've been battling with this problem this is what I've come up with...
public class UnitOfWorkFactory
{
private static readonly Hashtable _threads = new Hashtable();
private const string HTTPCONTEXTKEY =
"AboutDbContext.UnitOfWorkFactory";
public static IUnitOfWork Create()
{
IUnitOfWork unitOfWork = GetUnitOfWork();
if (unitOfWork == null || unitOfWork.IsDisposed)
{
unitOfWork = new UnitOfWork();
SaveUnitOfWork(unitOfWork);
}
return unitOfWork;
}
public static IUnitOfWork GetUnitOfWork()
{
if (HttpContext.Current != null)
{
if (HttpContext.Current.Items.Contains(HTTPCONTEXTKEY))
{
return (IUnitOfWork)HttpContext
.Current.Items[HTTPCONTEXTKEY];
}
return null;
}
var thread = Thread.CurrentThread;
if (string.IsNullOrEmpty(thread.Name))
{
thread.Name = Guid.NewGuid().ToString();
return null;
}
lock (_threads.SyncRoot)
{
return (IUnitOfWork)_threads[Thread.CurrentThread.Name];
}
}
private static void SaveUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[HTTPCONTEXTKEY] = unitOfWork;
}
else
{
lock (_threads.SyncRoot)
{
_threads[Thread.CurrentThread.Name] = unitOfWork;
}
}
}
public static void DisposeUnitOfWork(IUnitOfWork unitOfWork)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items.Remove(HTTPCONTEXTKEY);
}
else
{
lock (_threads.SyncRoot)
{
_threads.Remove(Thread.CurrentThread.Name);
}
}
}
}
public interface IUnitOfWork : IDisposable
{
void Commit();
bool IsDisposed { get; }
}
public class UnitOfWork : MyContext
{
}
public abstract class Repository<T>
: IRepository<T>, IDisposable where T : class
{
private UnitOfWork _context;
private UnitOfWork Context
{
get
{
if (_context == null || _context.IsDisposed)
return _context = GetCurrentUnitOfWork<UnitOfWork>();
return _context;
}
}
public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>()
where TUnitOfWork : IUnitOfWork
{
return (TUnitOfWork)UnitOfWorkFactory.GetUnitOfWork();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Where(predicate).ToList();
}
public bool Exists(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Any(predicate);
}
public T First(Expression<Func<T, bool>> predicate)
{
return Context.Set<T>().Where(predicate).FirstOrDefault();
}
public IEnumerable<T> GetAll()
{
return Context.Set<T>().ToList();
}
public IEnumerable<T> GetAllOrderBy(Func<T, object> keySelector)
{
return Context.Set<T>().OrderBy(keySelector).ToList();
}
public IEnumerable<T> GetAllOrderByDescending(Func<T, object> keySelector)
{
return Context.Set<T>().OrderByDescending(keySelector).ToList();
}
public void Commit()
{
Context.SaveChanges();
}
public void Add(T entity)
{
Context.Set<T>().Add(entity);
}
public void Update(T entity)
{
Context.Entry(entity).State = EntityState.Modified;
}
public void Delete(T entity)
{
Context.Set<T>().Remove(entity);
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
GC.SuppressFinalize(this);
}
}
public class MyContext : DbContext, IUnitOfWork
{
public DbSet<Car> Cars { get; set; }
public void Commit()
{
SaveChanges();
}
protected override void Dispose(bool disposing)
{
IsDisposed = true;
UnitOfWorkFactory.DisposeUnitOfWork(this);
base.Dispose(disposing);
}
public bool IsDisposed { get; private set; }
}
Then I can do:
using (var unitOfWork = UnitOfWorkFactory.Create())
{
_carRepository.Add(new Car
{
Make = "Porshe", Name = "Boxter"
});
_carRepository.Commit();
}
You could use some kind of "current" unit of work which is tied to current thread and explicitly resolved in service code. You need class to hold thread static instance of UoW to achieve this. However, this is not very good solution.
You be the judge...
I think you are double doing it.
Point 1:
http://www.britannica.com/topic/Occams-razor
Point 2:
From the F2 object browser description of EF main object, the DBContext...
public class DbContext
Member of System.Data.Entity
Summary:
A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit.