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