c# - Optimistic Concurrency -
i have entity framework project several linked entities. since utilized multiple users @ once i've set rowversion-field entities edited several users @ once. unfortunately optimisticconecurrencyexception
every time try save new entity, linked existing entity.
store update, insert, or delete statement affected unexpected number of rows (0). entities may have been modified or deleted since entities loaded. see http://go.microsoft.com/fwlink/?linkid=472540 information on understanding , handling optimistic concurrency exceptions.
the problem error doesn't give pointers error lies. either underlying model modified in meantime, there validation error on new model or else.
the code use add new entity follows:
using (ctx = new dbcontext()) { try { ctx.samples.add(model); ctx.savechanges(); } catch (dbupdateconcurrencyexception ex) { logmanager.handleexception(ex.innerexception); } }
model
model want add database
edit: seen above modified code ignore update of underlying model. furthermore have verified through:
ctx.database.log = s => debug.write(s);
that insert statement sent database , not additional update statement.
insert [dbo].[samples]([idsample], [modificationdate], [iduser]) values (@0, @1, @2) select [rowversion] [dbo].[samples] @@rowcount > 0 , [idsample] = @0 , [modificationdate] = @1
i understand exception if update entity , rowversion column wouldn't match, in case it's new entity. there way see if 1 of properties malformed?
edit2:
instead of trimming milliseconds used datetime.today instead of datetime.now works. seemingly there problem datetime2(4) on modificationdate. made sure modificationdate truncated 4 milliseconds there should no parse error.
edit3:
after switching datetime.now , trimming milliseconds stopped working , entities not longer inserted database. caused fact sql server has problems matching entities based on millisecond values. executed ef generated sql seen above fictional values , went through although on occasions query didn't return rowversion-value. in terms of entity framework, client interpret return value of 0 lines , therefore call concurrency-exception. (it should of note modificationdate idsample primary key of entity.)
edit4:
i'm using datetime.today , add needed precision, works me. can flagged solved. (altough have expected ef can take care of datetime-format-conversion :/)
the question have are/were adding datetime? creating many steps hammer out problem. creating datetime, modifying it, etc.
if you're entity inheriting base class mapped properties concurrency add/update in dbcontext override of savechanges().
here's example: (written without optimized syntax)
public abstract class entitybase { public int id {get; set;} public datetime creationdate {get; set;} public datetime? modifydate {get; set;} public string versionhash {get; set;} } public static class entitybaseextensions { public static void mybaseentitymapping<t>(this entitytypeconfiguration<t> configuration) t : entitybase { configuration.haskey(x => x.id); configuration.property(x => x.creationdate) .isrequired(); configuration.property(x => x.modifydate) .isoptional(); configuration.property(x => x.versionhash).isconcurrencytoken(); } } public class myentity : entitybase { public string myproperty {get; set;} } public class myentitymapping : entitytypeconfiguration<myentity> { public myentitymapping() { this.mybaseentitymapping(); property(x=>x.myproperty).isrequired(); } } public class mycontext : dbcontext { .... public override int savechanges() { this.changetracker.detectchanges(); //this forces ef compare changes originals including references , 1 many relationships, i'm in habit of doing this. var context = ((iobjectcontextadapter)this).objectcontext; //grab underlying context var ostateentries = context.objectstatemanager.getobjectstateentries(entitystate.modified | entitystate.added); // grab entity entries (add/remove, queried) in current context var stateentries = ostateentries.where(x => x.isrelationship == false && x.entity entitybase); // don't care relationships, has inherit entitybase var time = datetime.now; //getting date our auditing dates foreach (var entry in stateentries) { var entity = entry.entity entitybase; if (entity != null) //redundant, resharper still yells @ :) { if (entry.state == entitystate.added) //could @ id field > 0, safe enough { entity.creationdate = time; } entity.modifydate = time; entity.versionhash = guid.newguid().tostring().replace("-", "").substring(0, 10); //this example of simple random configuration of letters/numbers.. since query on sql server using primary key index, can use whatever want without worrying query execution.. don't query on version itself! } } return base.savechanges(); } .... }
Comments
Post a Comment