c# - LinqToSQL generic lookup of foreign key entity to string -
i working linq sql , trying keep history of changes , store these database.
i know there frameworks out there such doddleaudit feels buggy , bloaty me i'm trying create own.
this have far. looking way make repetitive code more reuseable:
protected void insertauditrecordtodatabase(modifiedmemberinfo[] changes, object entity) { type type = entity.gettype(); propertyinfo key; key = type.getproperties() .where(o => o.getcustomattributes(typeof(columnattribute), true) .any(a=>((columnattribute)a).isprimarykey)).singleordefault(); auditrecord audit = new auditrecord(); audit.action = (byte)auditaction.update; audit.auditdate = datetime.now; audit.associationtable = null; audit.associationtablekey = null; audit.entitytable = type.name; audit.entitytablekey = int.parse(key.getvalue(entity, null).tostring()); audit.username = httpcontext.current.user.identity.name; if (string.isnullorempty(audit.username)) audit.username = "anonymous"; foreach (modifiedmemberinfo mmi in changes) { auditrecordfield field = new auditrecordfield(); if (!excludedfieldnamesfromaudit.any(x => x.equals(mmi.member.name, stringcomparison.ordinalignorecase))) { field.membername = mmi.member.name; field.oldvalue = (mmi.originalvalue != null ? mmi.originalvalue.tostring() : string.empty); field.newvalue = (mmi.currentvalue != null ? mmi.currentvalue.tostring() : string.empty); if ((field.oldvalue != null && !field.oldvalue.equals(field.newvalue)) || (field.oldvalue == null && field.newvalue != null)) { // special handling if (field.membername.equals("euamembertypeid")) { int oldint; organisationsubtype oldvalue = null; if(int.tryparse(field.oldvalue, out oldint)) oldvalue = this.organisationsubtypes.singleordefault(m => m.id == oldint); field.oldvalue = oldvalue != null ? oldvalue.name : string.empty; int newint; organisationsubtype newvalue = null; if(int.tryparse(field.newvalue, out newint)) newvalue = this.organisationsubtypes.singleordefault(m => m.id == newint); field.newvalue = newvalue != null ? newvalue.name : string.empty; } if (field.membername.equals("contactpersonstaffid")) { int oldint; organisationstaff oldvalue = null; if (int.tryparse(field.oldvalue, out oldint)) oldvalue = this.organisationstaffs.singleordefault(m => m.id == oldint); field.oldvalue = oldvalue != null ? oldvalue.contact.fullname : string.empty; int newint; organisationstaff newvalue = null; if (int.tryparse(field.newvalue, out newint)) newvalue = this.organisationstaffs.singleordefault(m => m.id == newint); field.newvalue = newvalue != null ? newvalue.contact.fullname : string.empty; } if (field.membername.equals("countryid")) { int oldint; country oldvalue = null; if (int.tryparse(field.oldvalue, out oldint)) oldvalue = this.countries.singleordefault(m => m.id == oldint); field.oldvalue = oldvalue != null ? oldvalue.name : string.empty; int newint; country newvalue = null; if (int.tryparse(field.newvalue, out newint)) newvalue = this.countries.singleordefault(m => m.id == newint); field.newvalue = newvalue != null ? newvalue.name : string.empty; } // save db audit.auditrecordfields.add(field); } } } if (audit.auditrecordfields.count > 0) this.auditrecords.insertonsubmit(audit); }
as can see, block of code being repeated:
if (field.membername.equals("countryid")) { int oldint; country oldvalue = null; if (int.tryparse(field.oldvalue, out oldint)) oldvalue = this.countries.singleordefault(m => m.id == oldint); field.oldvalue = oldvalue != null ? oldvalue.name : string.empty; int newint; country newvalue = null; if (int.tryparse(field.newvalue, out newint)) newvalue = this.countries.singleordefault(m => m.id == newint); field.newvalue = newvalue != null ? newvalue.name : string.empty; }
the repeated pattern is:
- a lookup on table:
countries
- looking entity:
country
- using expression:
m => m.id == oldint
- and expression convert entity string:
oldvalue.name
i hoping done generic expression magic can't seem figure out.
this should work intend.
one of challenges face expect have expression int parameter before variable created parse string. if had variable created @ time created expression, reference variable , process simpler.
i got around dynamically building expression after string parsed int variable.
protected void insertauditrecordtodatabase(modifiedmemberinfo[] changes, object entity) { type type = entity.gettype(); propertyinfo key; key = type.getproperties() .where(o => o.getcustomattributes(typeof(columnattribute), true) .any(a => ((columnattribute)a).isprimarykey)).singleordefault(); auditrecord audit = new auditrecord(); audit.action = (byte)auditaction.update; audit.auditdate = datetime.now; audit.associationtable = null; audit.associationtablekey = null; audit.entitytable = type.name; audit.entitytablekey = int.parse(key.getvalue(entity, null).tostring()); audit.username = httpcontext.current.user.identity.name; if (string.isnullorempty(audit.username)) audit.username = "anonymous"; foreach (modifiedmemberinfo mmi in changes) { auditrecordfield field = new auditrecordfield(); if (!excludedfieldnamesfromaudit.any(x => x.equals(mmi.member.name, stringcomparison.ordinalignorecase))) { field.membername = mmi.member.name; field.oldvalue = (mmi.originalvalue != null ? mmi.originalvalue.tostring() : string.empty); field.newvalue = (mmi.currentvalue != null ? mmi.currentvalue.tostring() : string.empty); if ((field.oldvalue != null && !field.oldvalue.equals(field.newvalue)) || (field.oldvalue == null && field.newvalue != null)) { // special handling if (field.membername.equals("euamembertypeid")) { field.oldvalue = getdescription(this.organisationsubtypes, field.oldvalue, m => m.id, m => m != null ? m.name : string.empty); field.newvalue = getdescription(this.organisationsubtypes, field.newvalue, m => m.id, m => m != null ? m.name : string.empty); } if (field.membername.equals("contactpersonstaffid")) { field.oldvalue = getdescription(this.organisationstaffs, field.oldvalue, m => m.id, m => m != null ? m.contact.fullname : string.empty); field.newvalue = getdescription(this.organisationstaffs, field.newvalue, m => m.id, m => m != null ? m.contact.fullname : string.empty); } if (field.membername.equals("countryid")) { field.oldvalue = getdescription(this.countries, field.oldvalue, m => m.id, m => m != null ? m.name : string.empty); field.newvalue = getdescription(this.countries, field.newvalue, m => m.id, m => m != null ? m.name : string.empty); } // save db audit.auditrecordfields.add(field); } } } if (audit.auditrecordfields.count > 0) this.auditrecords.insertonsubmit(audit); } public static string getdescription<t, tprop>(table<t> thistable, string searchparam, expression<func<t, tprop>> searchexpression, expression<func<t, string>> descriptionexpression) t : class { if (!(searchexpression.body memberexpression)) { throw new argumentexception("search expression must memberexpression (i.e v => v.id)", "searchexpression"); } else { int searchvalue; if (int.tryparse(searchparam, out searchvalue)) { var equalityexpression = expression.equal(searchexpression.body, expression.constant(searchvalue)); var lambdaexpression = expression.lambda<func<t, bool>>(equalityexpression, searchexpression.parameters); // passed-in expression must resemble v => v.id // generated expression resemble v => v.id == 5 var value = thistable.singleordefault(lambdaexpression); return descriptionexpression.compile()(value); } return string.empty; } }
Comments
Post a Comment