c# - using UnitOfWork and Repository Pattern with Entity Framework -
i'm gonna use repository , unitofwork in data access layer take @ 1 contact aggregateroot
public interface iaggregateroot { } this generic repository interface :
public interface irepository<t> { ienumerable<t> getall(); t findby(params object[] keyvalues); void add(t entity); void update(t entity); void delete(t entity); } and poco contact class in model
public class contact :iaggregateroot { public guid id { get; set; } public string name { get; set; } public string email { get; set; } public string title { get; set; } public string body { get; set; } public datetime creationtime { get; set; } } and icontactrepository inherit irepository , maybe has own method
public interface icontactrepository : irepository<contact> { } now have done in iuitofwork , unitofwork
public interface iunitofwork { irepository<contact> contactrepository { get; } } public class unitofwork : iunitofwork { private readonly statoscontext _statoscontext = new statoscontext(); private irepository<contact> _contactusrepository; public irepository<contact> contactrepository { { return _contactusrepository ?? (_contactusrepository = new repository<contact>(_statoscontext)); } } } also repository
public class repository<t> : irepository<t> t : class, iaggregateroot { //implementing methods } i can crud operation accessing repositories unitofwork in service , example :
_unitofwork.contactrepository.add(contact); _unitofwork.savechanges(); but want
_
contactrepository.add(contact); _unitofwork.savechanges(); (get crud , generic method via _contactrepository no _unitofwork.contactrepository) because want contactrepository method specific queries , please ??
it's not direct answer question, might simplify things little bit , reduce duplication.
when use e.g. entityframework power tools reverse-engineer code first (or use code first in general), end dbcontext class serves uow , repository in one, e.g.:
public partial class yourdbcontext : dbcontext { public dbset<contact> contacts {get; set;} } now, if want things testable, there's easy way: introduce thin interface:
public interface idbcontext { idbset<t> entityset<t>() t : class; int savechanges(); //you can reveal more methods original dbcontext, `getvalidationerrors` method or whatever need. } then make file second part of partial class:
public partial class yourdbcontext : idbcontext { public idbset<t> entityset<t>() t : class { return set<t>(); } } ta-da! can inject idbcontext yourdbcontext backing up:
//context injected idbcontext: var contact = context.entityset<contact>().single(x => x.id == 2); contact.name = "updated name"; context.entityset<contact>().add(new contact { name = "brand new" }); context.savechanges(); now if want have control on disposal of context, you'd have write own (gasp) idbcontextfactory (generic or not, depending need) , inject factory instead.
no need write own find, add or update methods now, dbcontext handle appropriately, it's easier introduce explicit transactions , nicely hidden behind interfaces (idbcontext, idbset).
by way, idbcontextfactory equivalent nhibernate's isessionfactory , idbcontext - isession. wish ef had out of box, too.
Comments
Post a Comment