353

I am using Entity Framework to populate a grid control. Sometimes when I make updates I get the following error:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

I can't figure out how to reproduce this. But it might have something to do with how close together I make the updates. Has anyone seen this or does anyone know what the error message refers to?

Edit: Unfortunately I am no longer at liberty to reproduce the problem I was having here, because I stepped away from this project and don't remember if I eventually found a solution, if another developer fixed it, or if I worked around it. Therefore I cannot accept any answers.

Alex Butenko
  • 3,664
  • 3
  • 35
  • 54
strongopinions
  • 3,917
  • 3
  • 25
  • 28
  • I got this error with the introduction of a [SQL Server Row Level Security policy that allowed updates to a row into a state that could not be read back (an exclusive FILTER predicate with a permissive BLOCK predicate)](https://stackoverflow.com/q/50009638/263832). EntityFramework requires the updated row to be read back after the update otherwise it assumes it was a concurrency error (at least when using optimistic concurrency). – xr280xr Apr 24 '18 at 21:02
  • The problem could be incorrect scoping for your DBContext https://stackoverflow.com/questions/49154250/asp-net-identitys-usermanager-caches-users (this example is for ASPNET Identity but applies for any context) – Simon_Weaver Dec 17 '18 at 23:33
  • Regardless of the context of this error it's a good idea to put a breakpoint wherever it is that the context is being instantiated. Were you expecting it to be instantiated once when you loaded a webpage but it's hitting that breakpoint 5 times? Then you probably have a race condition. Look at `Request.Uri` to see the actual request URL. In my case I had some tracking logic that was hitting my site and unnecessarily loading the context from the DB (and occasionally updating it too). So then the actual page I was debugging had had its data stomped upon by a stupid tracking code logic. – Simon_Weaver Dec 17 '18 at 23:44
  • add @Html.AntiForgeryToken() in view – Vikas Sharma Feb 14 '19 at 10:10
  • I can not give answer to the question now but I am getting this error when I am using the reverse poco generator(https://marketplace.visualstudio.com/items?itemName=SimonHughes.EntityFrameworkReversePOCOGenerator) and the issue was I don't have primary key set on the table. Adding primary key to table and updating model solves my problem. – Saurabh Solanki Mar 31 '21 at 10:06

45 Answers45

419

I ran into this and it was caused by the entity's ID (key) field not being set. Thus when the context went to save the data, it could not find an ID = 0. Be sure to place a break point in your update statement and verify that the entity's ID has been set.

From Paul Bellora's comment

I had this exact issue, caused by forgetting to include the hidden ID input in the .cshtml edit page

Jens Kloster
  • 11,099
  • 5
  • 40
  • 54
webtrifusion
  • 4,536
  • 2
  • 14
  • 9
  • 3
    +1 I was having same problem and this helped find the solution. Turns out I had [Bind(Exclude = "OrderID")] in my Order model which was causing the value of the entity's ID to be zero on HttpPost. – Dhaust Jan 23 '12 at 02:07
  • 3
    That's exactly what I was missing. My object's ID was 0. – Azhar Khorasany Aug 16 '12 at 21:18
  • 5
    @Html.HiddenFor(model => model.productID) -- worked perfect. I was missing the productID on the EDIT PAGE (MVC RAZOR) – Ravi Ram Aug 28 '12 at 05:02
  • 2
    I had a similar issue but with a twist. For me the issue was I didn't have the sql table setup correctly. My primary key field was not set to auto increment. So EF would send the record I was trying to insert w/o a key which is fine if you remember to tell sql that field is an auto increment Identity field, which I forgot : – Agile Noob Jan 06 '13 at 19:36
  • had a similar issue. usually i am adding my newly created entity(`id =0`) to my conext. though if it already exists i get it from the context (`id != 0`) and didnt check if `id == 0` before i am adding it. so i added an already attached entity to my conext and tried to save it. – JuHwon Feb 26 '13 at 11:04
  • Also happens if the record with the relevant Id does not exist! – user373455 Aug 01 '13 at 14:38
  • I had forgotten to copy the Id from the database record into the view model. – David Ching Aug 05 '13 at 23:31
  • Thank you for this solution. I am using the unit of work pattern with viewmodels and automapper. I got this error and noticed the id was not being passed properly. I added: @Html.HiddenFor(model => model.ID) and now I can save my data. – VoltaicShock Jan 15 '14 at 02:36
  • Had the same issue, for some reason one of the columns wasn't created in the Table. I went in and manually added it with SLQ Management Studio and all worked flawlessly after that! – Spets May 16 '14 at 20:41
  • 1
    Same issue but using a composite key. One of the key values was not set. – obaylis Feb 05 '15 at 16:17
  • Created a CreateOrEdit view that basically does both create and edit and I kept forgetting to put in the Id in the edit, as its not needed in the create! You sir are a genius! – Louie Bacaj Jun 01 '16 at 20:06
  • This will also happen if you have a column of type `rowversion` on the entity/table you're updating and you don't set the value for it. – jtate Nov 01 '16 at 20:38
  • I ran into this issue with ASP.NET Identity when looking to update an existing user. I had neglected to pass the `Id` of the user into the `ApplicationUser` instance I was passing to `UpdateAsync` – webworm Dec 09 '16 at 14:40
  • Indeed, It was Key Identity issue and once I have update it (CustomerId int IDENTITY(1,1)) the issue was resolved. Thanks – Yaduraj Jan 25 '19 at 11:54
  • This has bitten me several times due to paste errors in my MVC views. Watch out for this! You have to put that hidden record key into the view on Edit pages. This was an important answer for me! – Greg Barth Apr 19 '22 at 22:13
219

That's a side-effect of a feature called optimistic concurrency.

Not 100% sure how to turn it on/off in Entity Framework but basically what it's telling you is that between when you grabbed the data out of the database and when you saved your changes someone else has changed the data (Which meant when you went to save it 0 rows actually got updated). In SQL terms, their update query's where clause contains the original value of every field in the row, and if 0 rows are affected it knows something's gone wrong.

The idea behind it is that you won't end up overwriting a change that your application didn't know has happened - it's basically a little safety measure thrown in by .NET on all your updates.

If it's consistent, odds are it's happening within your own logic (EG: You're actually updating the data yourself in another method in-between the select and the update), but it could be simply a race condition between two applications.

Daniel
  • 10,864
  • 22
  • 84
  • 115
fyjham
  • 7,004
  • 2
  • 32
  • 40
  • 40
    This is happening in a single-user environment (on my dev machine) so I don't think it could be a race condition. I am binding to a custom grid control with an EntityDataSource so I'm not sure exactly what's happening behind the scenes, but I don't have any extra code of my own that is modifying the tables. Is there a way to change this concurrency setting? – strongopinions Dec 04 '09 at 00:16
  • 3
    I think you can on a per-column basis in your entity model (It's in the properties window), but the thing is that'll just prevent you seeing the error and it'll still not update anything. Are you able to view the SQL commands going to your database (EG: SQL Server Profiler for MSSQL)? This way you could see what update it's generated and should be able to see why that update doesn't affect any rows. – fyjham Dec 04 '09 at 04:58
  • 9
    If the entity has a timestamp property, then make sure you have it stored in your view and make sure the entity populate the timestamp properly. – anIBMer Aug 29 '13 at 23:54
  • I had a timestamp column and once I addressed the it, EF6.1 worked as expected, thanks for the tip @anelBMer – JQII Sep 17 '14 at 21:53
  • 3
    If you use timestamps, tje object you want to delete needs the PK set and the RowVersion Property in order to update it successfully! I was setting the rowVersion (timestamp) property, after I have attached the object to the respective DbSet, that's why it didn't work. Good job! – Legends Mar 29 '15 at 17:10
  • In my case I added "-Select-" in my @Html.DropDownList in my Edit view and that was causing the problem. After removing it the issue resolved. – dawncode May 23 '16 at 18:02
  • I encountered this issue and discovered that every update statement will be followed by a select statement with where clause @@ROWCOUNT > 0. If you have a timestamp, you need to include the timestamp in the update statement otherwise @@ROWCOUNT will be zero – code4j Jun 23 '17 at 02:00
  • i got this issue and i was trying update method instead of insert using EF. – Rejwanul Reja Nov 05 '18 at 09:38
121

Wow, lots of answers, but I got this error when I did something slightly different that no on else has mentioned.

Long story short, if you create a new object and tell EF that its modified using the EntityState.Modified then it will throw this error as it doesn't yet exist in the database. Here is my code:

MyObject foo = new MyObject()
{
    someAttribute = someValue
};

context.Entry(foo).State = EntityState.Modified;
context.SaveChanges();

Yes, this seems daft, but it arose because the method in question used to have foo passed to it having been created earlier on, now it only has someValue passed to it and creates foo itself.

Easy fix, just change EntityState.Modified to EntityState.Added or change that whole line to:

context.MyObject.Add(foo);
Ben
  • 5,525
  • 8
  • 42
  • 66
  • Thanks for posting this. That was my problem too, I had copy-pasted some code that was setting the State to EntityState.Modified. – clayRay May 22 '18 at 04:42
24

I was facing this same scaring error... :) Then I realized that I was forgetting to set a

@Html.HiddenFor(model => model.UserProfile.UserId)

for the primary key of the object being updated! I tend to forget this simple, but very important thingy!

By the way: HiddenFor is for ASP.NET MVC.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 3
    That seems like a security flaw, to store the `UserId` in the form, very prone to hackers...this should be populated afterwards from `HttpContext.Current.User.Identity.Name` – Serj Sagan Nov 22 '13 at 21:19
  • @SerjSagan you're right... but as long you do some checks on the server side to confirm the UserId and current UserName you're good to go. – Leniel Maccaferri Nov 22 '13 at 22:49
  • 2
    My point is why even store that in the `HiddenFor` you'll need to get it from the `HttpContext` anyways... I would not put this property in the form at all, which would force me to always populate it server side... – Serj Sagan Nov 25 '13 at 05:08
  • Thats not true: "Wow, lots of answers, but I got this error when I did something slightly different that no on else has mentioned." user webtrifusion mentioned your case! – HelloWorld Jun 29 '20 at 12:43
16

Check whether you forgot the "DataKeyNames" attribute in the GridView. it's a must when modifying data within the GridView

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeynames.aspx

dotNetE
  • 616
  • 1
  • 6
  • 27
Solly
  • 161
  • 1
  • 2
  • +1. Perfect and simple solution for me. I am binding GridView to EntityDataSource and did not set this to my primary key on the object. – Andez Aug 21 '12 at 20:22
  • We know that Kendo UI does not support composite key, but in case I added new column that concat-ed my keys to one, what's happening then? – Branislav Nov 11 '13 at 21:39
16

The issue is caused by either one of two things :-

  1. You tried to update a row with one or more properties are Concurrency Mode: Fixed .. and the Optimistic Concurrency prevented the data from being saved. Ie. some changed the row data between the time you received the server data and when you saved your server data.
  2. You tried to update or delete a row but the row doesn't exist. Another example of someone changing the data (in this case, removing) in between a retrieve then save OR you're flat our trying to update a field which is not an Identity (ie. StoreGeneratedPattern = Computed) and that row doesn't exist.
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 1
    This could also be caused if all of the object properties that were assigned to, they were assigned with the same values as they had before. – Serj Sagan Nov 29 '13 at 19:46
  • +1 for 2nd one. I had StoreGeneratedPattern = None, changing to StoreGeneratedPattern = Identity resolved the issue. Thanks – tkt986 May 27 '17 at 16:46
12

I got this same error because part of the PK was a datetime column, and the record being inserted used DateTime.Now as the value for that column. Entity framework would insert the value with millisecond precision, and then look for the value it just inserted also with millisecond precision. However SqlServer had rounded the value to second precision, and thus entity framework was unable to find the millisecond precision value.

The solution was to truncate the milliseconds from DateTime.Now before inserting.

innominate227
  • 11,109
  • 1
  • 17
  • 20
  • 2
    We had the same problem except we were inserting into a `Date` column with a `DateTime` value – adam0101 Jan 25 '16 at 16:29
  • 1
    Same here. We had a data warehouse record and were using the timestamp as part of the key. The timestamp in the data warehouse was a SQL DateTime, but the timestamp in C# was not matching. I changed the SQL data type to DateTime2(7), updated the EF model, and all was fixed. – mmcfly Aug 30 '18 at 21:04
  • Changing the column to Datetime2(7) worked for me too. Thanks @mmcfly – Dzejms Sep 18 '18 at 16:24
10

I had the same problem, I figure out that was caused by the RowVersion which was null. Check that your Id and your RowVersion are not null.

for more information refer to this tutorial

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application

Bilel Chaouadi
  • 903
  • 1
  • 10
  • 28
10

I was having same problem and @webtrifusion's answer helped find the solution.

My model was using the Bind(Exclude) attribute on the entity's ID which was causing the value of the entity's ID to be zero on HttpPost.

namespace OrderUp.Models
{
[Bind(Exclude = "OrderID")]
public class Order
{
    [ScaffoldColumn(false)]
    public int OrderID { get; set; }

    [ScaffoldColumn(false)]
    public System.DateTime OrderDate { get; set; }

    [Required(ErrorMessage = "Name is required")]
    public string Username { get; set; }
    }
}   
Community
  • 1
  • 1
Dhaust
  • 5,470
  • 9
  • 54
  • 80
  • Similar problem, for security reasons, I have Bind(include = some fields). ID was not in the list. Also I added it as a hidden input. Must have erased something generated by MVC or the ID was not there at all. Thanks for the help. – MusicAndCode Apr 12 '17 at 19:33
9

I also came across this error. The problem it turned out was caused by a Trigger on the table I was trying to save to. The Trigger used 'INSTEAD OF INSERT' which means 0 rows ever got inserted to that table, hence the error. Luckily in may case the trigger functionality was incorrect, but I guess it could be a valid operation that should somehow be handled in code. Hope this helps somebody one day.

Si-N
  • 1,495
  • 1
  • 13
  • 27
  • 2
    Entity can be tricked into believing that rows were added by returning a SELECT statement (with the primary key column) from the trigger. – jahu Feb 09 '16 at 15:39
  • 2
    To expand on the comment by @jahu, I had to get an actual id of the newly inserted item to be returned from my trigger and the column name has to match the trigger table's identity column (in my case, actually a view so it didn't have an identity of its own but I had tricked the edmx into believing it did). My trigger was doing an insert into a separate table, so I just added this last line to my trigger: `SELECT SCOPE_IDENTITY() as MyViewId` – DannyMeister Jun 28 '16 at 23:10
  • Also see this question: http://stackoverflow.com/questions/5820992/error-when-inserting-into-table-having-instead-of-trigger-from-entity-data-frame – J. Polfer Aug 24 '16 at 15:50
  • In my case I was doing a delete operation on entities in a child collection but there was a trigger on delete for one of the child entities that caused another of the child entities to be deleted. This caused the error since N - 1 rows were affected due to the trigger deleting one of the child entities itself before entity framework tried to delete it. – skeletank Oct 12 '17 at 17:39
8

While editing include the id or primary key of the entity as a hidden field in the view

ie

      @Html.HiddenFor(m => m.Id)

that solves the problem.

Also if your model includes non-used item include that too and post that to the controller

Arun Aravind
  • 101
  • 1
  • 4
8

I started getting this error after changing from model-first to code-first. I have multiple threads updating a database where some might update the same row. I don't know why I didn't have a problem using model-first, assume that it uses a different concurrency default.

To handle it in one place knowing the conditions under which it might occur, I added the following overload to my DbContext class:

using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;

public class MyDbContext: DbContext {
...
        public int SaveChanges(bool refreshOnConcurrencyException, RefreshMode refreshMode = RefreshMode.ClientWins) {
            try {
                return SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex) {
                foreach (DbEntityEntry entry in ex.Entries) {
                    if (refreshMode == RefreshMode.ClientWins)
                        entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                    else
                        entry.Reload();
                }
                return SaveChanges();
            }
        }
}

Then called SaveChanges(true) wherever applicable.

avenmore
  • 2,809
  • 3
  • 33
  • 34
  • 1
    OK, everyone else is complaing about the issue, showing how they can trigger it etc, but this answer has a cool answer. I use a continue update model (no save button here baby) and was getting this on grid updates when the EF thread was falling behind, and solved it. Brilliant work my good name.. you made me look like a hero - standing on the shoulder of giants!! – Tony Trembath-Drake May 23 '17 at 07:28
  • Helped me too, look at this for more options- https://stackoverflow.com/a/13891724/4836581 – Zvi Redler Sep 11 '19 at 10:10
8

The line [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)] did the trick in my case:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;


[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int? SomeNumber { get; set; }
Tomo
  • 429
  • 1
  • 10
  • 24
  • [DatabaseGenerated(DatabaseGeneratedOption.None)] This saved my life as the field which I had decorated as KEY was actually not a Primary key in database table and had put only as a work around for entity framework to not throw an exception for model without key. And also this field was nullable. So whenever I was trying to add new record to this table it was giving this error probably because it was expecting this field to be generated from the database table which obviously was not happening due to that field was not key in the table. – Mantra Dec 21 '21 at 14:11
7

You need to explicitly include a BoundField of the primary key. If you don't want the user to see the primary key, you have to hide it via css:

    <asp:BoundField DataField="Id_primary_key" ItemStyle-CssClass="hidden" 
HeaderStyle-CssClass="hidden" />

Where 'hidden' is a class in css that has it's display set to 'none'.

Paulo
  • 172
  • 1
  • 5
7

I came across this issue on a table that was missing a primary key and had a DATETIME(2, 3) column (so the entity's "primary key" was a combination of all the columns)... When performing the insert the timestamp had a more precise time (2018-03-20 08:29:51.8319154) that was truncated to (2018-03-20 08:29:51.832) so the lookup on key fields fails.

combatc2
  • 1,215
  • 10
  • 10
5

Just make sure table and form both have primary key and edmx updated.

i found that any errors during update were usually because of: - No primary key in Table - No primary key in Edit view/form (e.g. @Html.HiddenFor(m=>m.Id)

Moji
  • 5,720
  • 2
  • 38
  • 39
5

I also had this error. There are some situations where the Entity may not be aware of the actual Database Context you are using or the Model may be different. For this, set: EntityState.Modified; to EntityState.Added;

To do this:

if (ModelState.IsValid)
{
context.Entry(yourModelReference).State = EntityState.Added;
context.SaveChanges();
}

This will ensure the Entity knows youre using or adding the State youre working with. At this point all the correct Model Values need to be set. Careful not to loose any changes that may have been made in the background.

Hope this helps.

Rusty Nail
  • 2,692
  • 3
  • 34
  • 55
5
  @Html.HiddenFor(model => model.RowVersion)

My rowversion was null, so had to add this to the view which solved my issue

wickjon
  • 900
  • 5
  • 14
  • 40
  • Wasn't passing the RowVersion from the View to the edit Action, plus I forgot to do the model binding for RowVersion. At the time you are saving the object to db, you need the previous value of the RowVersion submit to the db along with the object for the concurrency check. You make silly mistakes when you need things faster! – Dhanuka777 Jan 25 '16 at 03:02
4
    public void Save(object entity)
    {
        using (var transaction = Connection.BeginTransaction())
        {
        try
                {
                    SaveChanges();
                    transaction.Commit();
                }
                catch (OptimisticConcurrencyException)
                {
                    if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Deleted || ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Modified)
                        this.Refresh(RefreshMode.StoreWins, entity);
                    else if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Added)
                        Detach(entity);
                    AcceptAllChanges(); 
                    transaction.Commit();
                }
        }
    }
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Prem Prakash
  • 203
  • 2
  • 12
  • Can you please clarify what 'this' is referring to here and what is ObjectStateManager? I'm trying this in our base repository class but getting errors – Naomi Apr 30 '18 at 22:23
4

I had the same problem. In my case I was trying to update the primary key, which is not allowed.

ajaysinghdav10d
  • 1,771
  • 3
  • 23
  • 33
4

I got this error sporadically when using an async method. Has not happened since I switched to a synchronous method.

Errors sporadically:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public async Task<IHttpActionResult> Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    await db.SaveChangesAsync();

    return Ok();
}

Works all the time:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public IHttpActionResult Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    db.SaveChanges();

    return Ok();
}
Ogglas
  • 62,132
  • 37
  • 328
  • 418
  • Although this resolved my issue, it served to point to the underlying issue mentioned earlier in this post about PKs & Row versions. I had neglected to add a schema map for a new table that was further complicated by the fact the PK did not follow the naming convention rule. ID.
    – midohioboarder May 12 '18 at 23:40
3

I got that error when I was deleting some rows in the DB (in the loop), and the adding the new ones in the same table.

The solutions for me was, to dynamicaly create a new context in each loop iteration

Tony
  • 12,405
  • 36
  • 126
  • 226
  • I had to do the same thing, still not sure why the problem occurred in the first place, but this works. – Jed Grant Sep 20 '14 at 02:17
3

This will also happen if you are trying to insert into a unique constraint situation, ie if you can only have one type of address per employer and you try to insert a second of that same type with the same employer, you will get the same problem.

OR

This could also happen if all of the object properties that were assigned to, they were assigned with the same values as they had before.

        using(var db = new MyContext())
        {
            var address = db.Addresses.FirstOrDefault(x => x.Id == Id);

            address.StreetAddress = StreetAddress; // if you are assigning   
            address.City = City;                   // all of the same values
            address.State = State;                 // as they are
            address.ZipCode = ZipCode;             // in the database    

            db.SaveChanges();           // Then this will throw that exception
        }
Serj Sagan
  • 28,927
  • 17
  • 154
  • 183
2

I got this exception when attaching an object that didn't exist in the database. I had assumed the object was loaded from a separate context, but if it was the user's first time visiting the site, the object was created from scratch. We have auto-incrementing primary keys, so I could replace

context.Users.Attach(orderer);

with

if (orderer.Id > 0) {
    context.Users.Attach(orderer);
}
Andrew
  • 4,145
  • 2
  • 37
  • 42
2

One way to debug this problem in an Sql Server environment is to use the Sql Profiler included with your copy of SqlServer, or if using the Express version get a copy of Express Profiler for free off from CodePlex by the following the link below:

Express Profiler

By using Sql Profiler you can get access to whatever is being sent by EF to the DB. In my case this amounted to:

exec sp_executesql N'UPDATE [dbo].[Category]
SET [ParentID] = @0, [1048] = NULL, [1033] = @1, [MemberID] = @2, [AddedOn] = @3
WHERE ([CategoryID] = @4)
',N'@0 uniqueidentifier,@1 nvarchar(50),@2 uniqueidentifier,@3 datetime2(7),@4 uniqueidentifier',
@0='E060F2CA-433A-46A7-86BD-80CD165F5023',@1=N'I-Like-Noodles-Do-You',@2='EEDF2C83-2123-4B1C-BF8D-BE2D2FA26D09',
@3='2014-01-29 15:30:27.0435565',@4='3410FD1E-1C76-4D71-B08E-73849838F778'
go

I copy pasted this into a query window in Sql Server and executed it. Sure enough, although it ran, 0 records were affected by this query hence the error being returned by EF.

In my case the problem was caused by the CategoryID.

There was no CategoryID identified by the ID EF sent to the database hence 0 records being affected.

This was not EF's fault though but rather a buggy null coalescing "??" statement up in a View Controller that was sending nonsense down to data tier.

rism
  • 11,932
  • 16
  • 76
  • 116
2

Well i have this same issue. But this was due to my own mistake. Actually i was saving an object instead of adding it. So this was the conflict.

Ali
  • 468
  • 7
  • 18
2

None of the above answers quite covered my situation and the solution to it.

Code where the error was thrown in MVC5 controller:

        if (ModelState.IsValid)
        {
            db.Entry(object).State = EntityState.Modified; 
            db.SaveChanges(); // line that threw exception
            return RedirectToAction("Index");
        }

I received this exception when I was saving an object off an Edit view. The reason it threw it was because when I went back to save it, I had modified the properties that formed the primary key on the object. Thus, setting its state to Modified didn't make any sense to EF - it was a new entry, not a previously saved one.

You can solve this by either A) modifying the save call to Add the object, or B) just don't change the primary key on edit. I did B).

J. Polfer
  • 12,251
  • 10
  • 54
  • 83
2

When the accepted answer said "it won't end up overwriting a change that your application didn't know has happened", I was skeptic because my object was newly created. But then it turns out, there was an INSTEAD OF UPDATE, INSERT- TRIGGER attached to the table which was updating a calculated column of the same table.

Once I change this to AFTER INSERT, UPDATE, it was working fine.

Mahesh
  • 3,727
  • 1
  • 39
  • 49
2

This happened to me due to a mismatch between datetime and datetime2. Strangely, it worked fine prior to a tester discovering the issue. My Code First model included a DateTime as part of the primary key:

[Key, Column(Order = 2)]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;

The generated column is a datetime column. When calling SaveChanges, EF generated the following SQL:

-- Region Parameters
DECLARE @0 Int = 2
DECLARE @1 Int = 25
DECLARE @2 Int = 141051
DECLARE @3 DateTime2 = '2017-07-27 15:16:09.2630000' --(will not equal a datetime value)
-- EndRegion
UPDATE [dbo].[OrganizationSurvey]
SET [OrganizationSurveyStatusId] = @0
WHERE ((([SurveyID] = @1) AND ([OrganizationID] = @2)) AND ([PurchasedDate] = @3))

Because it was trying to match a datetime column with a datetime2 value, it returned no results. The only solution I could think of was to change the column to a datetime2:

[Key, Column(Order = 2, TypeName = "DateTime2")]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;
R. Salisbury
  • 1,954
  • 16
  • 17
  • 1
    The strangeness of it working vs. not working has to do with the underlying format/base of `datetime` vs. `datetime2`. Essentially some millisecond values will evaluate to a match, others will not. The same thing happened to me and I also switched to `DateTime2`. – xr280xr Apr 24 '18 at 20:57
  • +1 I wish I could +100 on this one for you. I after perusing around many places I finally found this and realized that, indeed, I had a Datetime as part of my primary key. Yes, this indeed fixed it. I updated the column to Datetime2 and it worked. Now, my beef is with Entity Framework for devising such a crappy query for this which forces me to do this. – Catchops May 22 '19 at 21:32
1

I got this issue when I accidently tried to update the object instead of save!

I had

 if (IsNewSchema(model))
            unitOfWork.SchemaRepository.Update(schema);
        else
            unitOfWork.SchemaRepository.Insert(schema);

when I should of had

 if (IsNewSchema(model))
            unitOfWork.SchemaRepository.Insert(schema);
        else
            unitOfWork.SchemaRepository.Update(schema);
jps
  • 1,060
  • 12
  • 19
  • This is the same probably I have; however, in my case I correctly called insert but only 3 of the 4 records came in as added. The 4th got marked as modified. I still haven't figured out a solution just yet... – endyourif Feb 27 '19 at 16:07
1

This may happen if trying to update a record with an Id that does not exist in the database.

Thomas.Benz
  • 8,381
  • 9
  • 38
  • 65
  • This is exactly what is happening in our scenario. My question is - how to handle that scenario properly to avoid (or ignore) this error? In our case one method deletes a row and updates the DB but then tries to update using original state and thus fails. I like avenmore idea which I am going to try. – Naomi Apr 30 '18 at 22:13
1

Just had the same problem.

I'm using EF 6, Code First + Migrations. The problem was that our DBA created a constraint on the table that threw the error.

Jaime Yule
  • 981
  • 1
  • 11
  • 20
1

For those of you using AutoMapper If you are updating an entity that has foreign keys to another entity(or entities), make sure all of the foreign entities have their primary key set to database generated (or auto-incremented for MySQL).

For example:

public class BuyerEntity
{
    [Key]
    public int BuyerId{ get; set; }

    public int Cash { get; set; }

    public List<VehicleEntity> Vehicles { get; set; }

    public List<PropertyEntity> Properties { get; set; }

}

Vehicles and Properties are stored in other tables than Buyers. When you add a new buyer, AutoMapper and EF will automatically update the Vehicles and Properties tables so if you don't have auto-increment set up on either of those tables (like I didn't), then you will see the error from the OP's question.

big_water
  • 3,024
  • 2
  • 26
  • 44
1

I got this exception and i set id column as auto increment in my database's table and then it working fine

Umang Patwa
  • 2,795
  • 3
  • 32
  • 41
1

If you are trying to create mapping in your edmx file to a "function Imports", this can result this error. Just clear the fields for insert, update and delete that is located in Mapping Details for a given entity in your edmx, and it should work. I hope I made it clear.

Mubarak
  • 11
  • 2
1

I ran into this using Telerik's RadGrid. I had the primary key as a gridbound column that was set to read only. It would work fine if the column was display="false" but readonly="true" caused the problem. I solved it by having the gridbound column display=false and adding a separate template column for display

<telerik:GridBoundColumn HeaderText="Shouldnt see" Display="false" 
     UniqueName="Id" DataField="Id">
</telerik:GridBoundColumn>
<telerik:GridTemplateColumn HeaderText="Id" UniqueName="IdDisplay">
    <ItemTemplate>
        <asp:Label ID="IDLabel" runat="server" 
            Text='<%# Eval("Id") %>'></asp:Label>                               
    </ItemTemplate>
</telerik:GridTemplateColumn> 
Talimite
  • 11
  • 1
0

In our case this error was caused by marking entities as modified when none of their properties 'really' changed. For example when you assign same value to a property, context may see that as an update where database doesn't.

Basically we ran a script to repopulate one property with concatenated values from other properties. For a lot of records that meant no change, but it flagged them as modified. DB returned different number of updated objects which presumably triggered that exception.

We solved it by checking the property value and only assigning new one if different.

Patrick
  • 1,019
  • 13
  • 16
0

Got this error when using SaveChanges(false) and then later SaveChanges() on the same context, in a unitofwork where multiple rows were being deleted from two tables (in the context)(SaveChanges(False) was in one of the deletes. Then in the calling function SaveChanges() was being called.... The solution was to remove the unnecessary SaveChanges(false).

Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
0

I'll throw this in just in case someone is running into this issue while working in a parallel loop:

Parallel.ForEach(query, deet =>
{
    MyContext ctx = new MyContext();
    //do some stuff with this to identify something
    if(something)
    {
         //Do stuff
         ctx.MyObjects.Add(myObject);
         ctx.SaveChanges() //this is where my error was being thrown
    }
    else
    {
        //same stuff, just an update rather than add
    }
}

I changed it to the following:

Parallel.ForEach(query, deet =>
{
    MyContext ctxCheck = new MyContext();
    //do some stuff with this to identify something
    if(something)
    {
         MyContext ctxAdd = new MyContext();
         //Do stuff
         ctxAdd .MyObjects.Add(myObject);
         ctxAdd .SaveChanges() //this is where my error was being thrown
    }
    else
    {
        MyContext ctxUpdate = new MyContext();
        //same stuff, just an update rather than add
        ctxUpdate.SaveChanges();
    }
}

Not sure if this is 'Best Practice', but it fixed my issue by having each parallel operation use its own context.

ledgeJumper
  • 3,560
  • 14
  • 45
  • 92
0

I had a similar problem today, I'll document it here, as it's not quite the optimistic concurrency error.

I'm converting an old system to a new database and it has couple of thousand entities that I've had to script over to the new system. However, to aid with sanity I've opted to keep the original unique IDs and so was injecting that into the new object and then trying to save it.

The problem I had is that I'd used MVC Scaffolding to create base repositories and they have a pattern in their UpdateOrInsert method, that basically checks to see if the Key attribute is set before it either adds the new entity or changes its state to modified.

Because the Guid was set, it was trying to modify a row that didn't actually exist in the database.

I hope this helps someone else!

Russ Clarke
  • 17,511
  • 4
  • 41
  • 45
0

Recently, I'm trying upgrade EF5 to EF6 sample project . The table of sample project has decimal(5,2) type columns. Database migration successfully completed. But, initial data seed generated exception.

Model :

    public partial class Weather
    {
    ...
    public decimal TMax {get;set;}
    public decimal TMin {get;set;}
    ...
    }

Wrong Configuration :

public partial class WeatherMap : EntityTypeConfiguration<Weather>
{

    public WeatherMap()
    {
        ...
        this.Property(t => t.TMax).HasColumnName("TMax");
        this.Property(t => t.TMin).HasColumnName("TMin");
        ...
    }
}

Data :

    internal static Weather[] data = new Weather[365]
    {
      new Weather() {...,TMax = 3.30M,TMin = -12.00M,...},
      new Weather() {...,TMax = 5.20M,TMin = -10.00M,...},
      new Weather() {...,TMax = 3.20M,TMin = -8.00M,...},
      new Weather() {...,TMax = 11.00M,TMin = -7.00M,...},
      new Weather() {...,TMax = 9.00M,TMin = 0.00M,...},
    };

I found the problem, Seeding data has precision values, but configuration does not have precision and scale parameters. TMax and TMin fields defined with decimal(10,0) in sample table.

Correct Configuration :

public partial class WeatherMap : EntityTypeConfiguration<Weather>
{

    public WeatherMap()
    {
        ...
        this.Property(t => t.TMax).HasPrecision(5,2).HasColumnName("TMax");
        this.Property(t => t.TMin).HasPrecision(5,2).HasColumnName("TMin");
        ...
    }
}

My sample project run with: MySql 5.6.14, Devart.Data.MySql, MVC4, .Net 4.5.1, EF6.01

Best regards.

gelistirici
  • 419
  • 5
  • 8
0

Got the same problem when removing item from table(ParentTable) that was referenced by another 2 tables foreign keys with ON DELETE CASCADE rule(RefTable1, RefTable2). The problem appears because of "AFTER DELETE" trigger at one of referencing tables(RefTable1). This trigger was removing related record from ParentTable as result RefTable2 record was removed too. It appears that Entity Framework, while in-code was explicitly set to remove ParentTable record, was removing related record from RefTable1 and then record from RefTable2 after latter operation this exception was thrown because trigger already removed record from ParentTable which as results removed RefTable2 record.

Volodymyr
  • 1,209
  • 1
  • 15
  • 26
0

we forgot mention "enctype" posting "multi-part" form data. One of my another scenario that I've just now face...

kyawagwin
  • 96
  • 7
0

I had this issue with Mvc identity when registering new user instead of:

var result = await UserManager.CreateAsync(user);

I was doing:

var result = await UserManager.UpdateAsync(user);
JustLearning
  • 3,164
  • 3
  • 35
  • 52
0

This just happened to me. I was running Aurora (AWS MySQL) and tried to add records to a table. The field marked [Key] in the model was mapped to an auto-incremented field in the table... or so I thought. It was set as Primary Key, but it was not set to auto-increment. So setting it to auto-increment fixed my issue.

CodeOrElse
  • 328
  • 2
  • 16