c# - Unable to get entity framework to generate a DbUpdateConcurrencyException (Database First) -


i'm trying implement optimistic locking model ef. have column timestamp datatype on tables i'm trying with.

i've tried adding timestamp attribute on member modifying t4 script. running test , seeing not working, tried adding concurrencycheck attribute on same member in same way (via t4). however, in neither case generated sql utilize member on updates (shown below). i've set concurrency mode fixed on property in edmx designer.

i can see timestamp column in separate select after update not on update itself. i've tried breaking on savechanges(), changing database record , seeing timestamp value changing after manual update, executing savechanges() line , executes fine without throwing exception. there i'm missing, need roll own timestamp comparison code, or need world of ef interceptors change sql output? thanks.

the generated sql: (logged via dbcontext.database.log)

update [dbo].[foo] set [footitle] = @0 ([fooid] = @1) select [fooversion] [dbo].[foo] @@rowcount > 0 , [fooid] = @1  

the final version of member after t4 generation:

[timestamp] [concurrencycheck] public byte[] fooversion { get; set; } 

what i'm trying ef do:

update [dbo].[foo] set [footitle] = @0 ([fooid] = @1 , [fooversion] = @2) 

i decided roll own checking code. it's pretty efficient, though require 2 trips database.

i wrote interface attaches series of partial classes use attach things entities. defines lookup selector entity base class service can use go fetch particular version. no result? return message. if there result entity updates you'd expect.

the interface:

public interface iversionabledbobject<tentity>     tentity : class, ivalidatableobject {     byte[] version { get; }     expression<func<tentity, bool>> lookupselector { get; } } 

an implementation example:

public partial class foo : iversionabledbobject<foo> {     public byte[] version { { return fooversion; } }      public expression<func<foo, bool>> lookupselector     {         { return foo => foo.fooid == fooid && foo.fooversion == version; }     } } 

the checking code in base service:

iversionabledbobject<tentity> versionablesource = entity iversionabledbobject<tentity>; if (versionablesource != null) {     bool versionexists = innercontext.set<tentity>().where(versionablesource.lookupselector).any();      if (!versionexists)         return new validationresult(string.format(fooresources.entityupdateversionconflicterror,                     bitconverter.toint32(versionablesource.version, 0))); } 

the validation result message formatter accepts version trying looked up. returning of validationresult specific own implementation. if use it, will.

here's generated sql on .any():

select  case when ( exists (select      1 [c1]     [dbo].[foo] [extent1]     ([extent1].[fooid] = @p__linq__0) , ([extent1].[fooversion] = @p__linq__1) )) cast(1 bit) else cast(0 bit) end [c1]  ( select 1 x ) [singlerowtable1] 

interestingly, when update happens, ef still refreshes row version without timestamp or concurrencycheck attributes similar sql posted in op.


Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -