asp.net mvc 4 - Generic Repository EF 5 - Update Entity And It's Complex/Scalar/Navigation Properties -
i'm trying find easy solution updating entity + included properties in solution. i've created generic repository dbcontext (database). update parent entity, not handling changes on child properties. there way handle or track changes?
example code updating child propery: (look @ comment - example code)
[httpput] public httpresponsemessage putbrand(brand brand) { if (!modelstate.isvalid) { return request.createerrorresponse(httpstatuscode.badrequest, modelstate); } try { // example code brand.brandsizes.firstordefault().name = "i'm test"; // add values brand.state = state.changed; brand.datechanged = datetime.now; // update brand = _brandservice.updatebrand(brand); // save _brandservice.savebrandchanges(); // signalr hub.clients.all.updatebrand(brand); return request.createresponse<brand>(httpstatuscode.ok, brand); } catch (exception ex) { return request.createresponse(httpstatuscode.internalservererror, ex.message); } }
context:
public class erpcontext : dbcontext { #region catalog public dbset<brand> brands { get; set; } public dbset<brandsize> brandsizes { get; set; } public dbset<brandsizeoption> brandsizeoptions { get; set; } public dbset<brandtierprice> brandtierprices { get; set; } #endregion catalog public erpcontext() : base("db-erp") { configuration.lazyloadingenabled = false; configuration.proxycreationenabled = false; } protected override void onmodelcreating(dbmodelbuilder modelbuilder) { modelbuilder.conventions.remove<pluralizingtablenameconvention>(); } }
generic repository:
public class erprepository<t> : irepository<t> t : class { #region fields private dbset<t> _dbset; private dbcontext _datacontext; #endregion fields #region ctor public erprepository(dbcontext datacontext) { if (datacontext == null) { throw new argumentnullexception("datacontext", "datacontext cannot null"); } _datacontext = datacontext; _dbset = _datacontext.set<t>(); } #endregion ctor #region methods public t add(t item) { return _dbset.add(item); } public t delete(t item) { return _dbset.remove(item); } public t update(t item) { var updated = _dbset.attach(item); _datacontext.entry(item).state = entitystate.modified; return updated; } public iqueryable<t> query(params expression<func<t, object>>[] includes) { var query = _dbset; if (includes != null) { includes.tolist().foreach(x => query.include(x).load()); } return query; } public void savechanges() { _datacontext.savechanges(); } #endregion methods }
model:
public class brand { #region ctr public brand() { brandsizes = new list<brandsize>(); brandtierprices = new list<brandtierprice>(); } #endregion ctr #region properties public int id { get; set; } public string name { get; set; } public string description { get; set; } public int? logoid { get; set; } public int displayorder { get; set; } public bool deleted { get; set; } public bool locked { get; set; } public state state { get; set; } public datetime datechanged { get; set; } public datetime datecreated { get; set; } #endregion properties #region mapping public virtual picture logo { get; set; } public virtual list<brandsize> brandsizes { get; set; } public virtual list<brandtierprice> brandtierprices { get; set; } #endregion mapping }
brandservice:
public partial class brandservice : ibrandservice { #region fields private readonly irepository<brand> _brandrepository; private readonly irepository<brandsize> _brandsizerepository; private readonly irepository<brandsizeoption> _brandsizeoptionrepository; #endregion fields #region ctor public brandservice(irepository<brand> brandrepository, irepository<brandsize> brandsizerepository, irepository<brandsizeoption> brandsizeoptionrepository) { _brandrepository = brandrepository; _brandsizerepository = brandsizerepository; _brandsizeoptionrepository = brandsizeoptionrepository; } #endregion ctor #region methods public virtual ienumerable<brand> getallbrands() { return _brandrepository.query(x => x.brandsizes); //return _brandrepository.query(); } public virtual brand getbrandbyid(int id) { return _brandrepository.query().where(x => x.id == id).firstordefault(); } public virtual brand insertbrand(brand brand) { return _brandrepository.add(brand); } public virtual brand updatebrand(brand brand) { return _brandrepository.update(brand); } public virtual brand deletebrand(brand brand) { return _brandrepository.delete(brand); } public virtual void savebrandchanges() { _brandrepository.savechanges(); } #endregion methods }
create iobjectwithstate interface , state enum track changes manually:
public interface iobjectwithstate { state state { get; set; } } public enum state { added, unchanged, modified, deleted }
and implement interface in every mapped entity
public class brand:iobjectwithstate { .... [notmapped] public state state { get; set; }}
and add these 2 helper methods convert state , apply changes in entire graph:
public static entitystate convertstate(state state) { switch (state) { case state.added : return entitystate.added; case state.deleted: return entitystate.deleted; case state.modified: return entitystate.modified; case state.unchanged: return entitystate.unchanged; default: return entitystate.unchanged; } } public static void applystatechanges(this dbcontext context) { foreach (var entry in context.changetracker.entries<iobjectwithstate>()) { iobjectwithstate stateinfo = entry.entity; entry.state = statehelpers.convertstate(stateinfo.state); } }
and when update or insert object edit state of object.state = state.modified;
, modify insert or update method this:
public void insertorupdate(t entity, bool isgraph) { if (((iobjectwithstate)entity).state == state.added) { datacontext.entry(entity).state = system.data.entity.entitystate.added; } else { dbset.add(entity); datacontext.entry(entity).state = system.data.entity.entitystate.modified; } //this method change state of every changed object if (isgraph) applystatechanges(datacontext); datacontext.commit(); }
Comments
Post a Comment