I want to update a row in EF:
Case newCase = new Case(...);
dbContext.Entry(newCase).State = EntityState.Modified;
dbContext.SaveChanges();
When updating I have this message:
Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded
There is no concurrency, since I am using the db on my machine.
If I go to SQL profiler to see the query that is executed, the condition is:
WHERE [Id] = @p0 AND [RowVersion] = @p14;
in this condition, @p0 is 1 and @p14 is NULL, exactly like the record that I want to modify. however, if I manually launch this query in SQL Server after removing the RowVersion part of the query, it succeeds, updating 1 row.
What can be the problem and how can I solve it?
EDIT:
I tried to select the record just before updating it, but the error is the same:
IEnumerable<Case> cases = from c in dbContext.Cases where c.Id.ToString() == "1" select c;
Case cs = cases.SingleOrDefault();
dbContext.Entry(cs).State = EntityState.Modified;
dbContext.SaveChanges();
Here is the complete error:
An exception of type 'Microsoft.Data.Entity.DbUpdateConcurrencyException' occurred in EntityFramework.Core.dll but was not handled in user code
Additional information: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
And here is the query from Sql Profiler:
exec sp_executesql N'SET NOCOUNT OFF;
UPDATE [Case]
SET
[Closed] = @p1
, [Comment] = @p2
, [ContactComment] = @p3
, [ContactId] = @p4
, [CreatedBy] = @p5
, [CreatedDateTime] = @p6
, [Description] = @p7
, [Email] = @p8
, [LastModifiedBy] = @p9
, [LastModifiedDateTime] = @p10
, [OpenedDateTime] = @p11
, [Phone] = @p12
, [RowVersion] = @p13
, [SlaConsumedTime] = @p15
, [SlaSuspended] = @p16
, [SlaTotalTime] = @p17
, [Status] = @p18
, [Title] = @p19
WHERE
[Id] = @p0
AND [RowVersion] = @p14;
SELECT @@ROWCOUNT;',
N'@p0 int,@p1 bit,@p2 nvarchar(max) ,@p3 nvarchar(max) ,@p4 int,@p5 int,@p6 datetime2(7),
@p7 nvarchar(4000),@p8 nvarchar(4000),@p9 int,@p10 datetime2(7),@p11 datetime2(7),
@p12 nvarchar(max) ,@p13 varbinary(max) ,@p14 varbinary(max) ,@p15 time(7),@p16 bit,
@p17 time(7),@p18 int,@p19 nvarchar(4000)',
@p0=1,@p1=0,@p2=NULL,@p3=NULL,@p4=0,@p5=1,@p6='2015-09-23 09:07:55.7041023',@p7=N'y',
@p8=N'[email protected]',@p9=1,@p10='2015-09-23 09:50:02.9934006',@p11='2015-09-23 09:07:55.6796028',
@p12=NULL,@p13=NULL,@p14=NULL,@p15='00:00:00',@p16=0,@p17='00:00:00',
@p18=0,@p19=N'y'
Caseentity surely has aRowVersionproperty, this is used for concurrency check. But when you create aCasewithnew, that property does not have the original value currently stored in database. So the WHERE condition failed, you have to manually set the original values forRowVersionwith some value fetched from database before callingSaveChanges(). - HopelessdbContext.Cases.Add(newCase)(it a new object, not an existing one) - user3559349RowVersion = NULLwill never be true, it should beRowVersion is NULL). But the query is auto-generated so we cannot easily make it be translated toIs NULLinstead of= NULL. However I think you configure the model wrong, theRowVersionshould not be nullable. Also somehow you should ensure it to be auto-generated whenever a new record is added/modified. I would useIsRowVersion()method to configure it. - Hopeless