Strange entity updating in Entity Framework Code-First

10,689

Solution 1

When you get

"Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." From the inner exception: "OriginalValues cannot be used for entities in the Added state."

It means there was errors such as NOT NULL collumns that were blank or other constraints , check the entity validation errors by debugging or like

try{
...
catch ( DbEntityValidationException ex )
   {
foreach ( var validationErrors in ex.EntityValidationErrors )
    {
     foreach ( var validationError in validationErrors.ValidationErrors )
     {
      System.Diagnostics.Trace.TraceInformation( "Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage );
     }
    }
}

Solution 2

OriginalValues cannot be used for entities in the Added state.

Can be corrected by ensuring that non identity primary key fields are specified as not generated in the model.

modelBuilder
    .Entity<T>()
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    // this can also be achieved using attributes on the entity.

The error is actually self explanatory when you have context, but baffling otherwise. The database generates two statements for the insert, the second of which is:

SELECT [PrimaryKeyId]
FROM [dbo].[Entity]
WHERE @@ROWCOUNT > 0 AND [PrimaryKeyId] = scope_identity()
/* SP:StmtCompleted... */

This statement will not return any rows for non identity columns. Hence the OriginalValues will remain unaltered in the added state. This also explains why this exception is wrapped in an OptimisticConcurrencyException as the number of rows affected is used to detect existing altered data.

Share:
10,689
kyrylomyr
Author by

kyrylomyr

Updated on June 04, 2022

Comments

  • kyrylomyr
    kyrylomyr almost 2 years

    I'm solving the problem with updating entity before saving to database and got strange behavior.

    I'm using Entity Framework 4.1 Code-First in ASP.NET MVC 3 web application. Here is model:

    public class Order
    {
        public int OrderId { get; set; }
        public int CarId { get; set; }
        public DateTime BeginRentDate { get; set; }
        public DateTime EndRentDate { get; set; }
        public decimal RentPrice { get; set; }
        public virtual Car Car { get; set; }
    }
    
    public class Car
    {
        public int CarId { get; set; }
        public string Brand { get; set; }
        public string Model { get; set; }
        public string NumberPlate { get; set; }
        public decimal RentPrice { get; set; }
    }
    

    Each Car has a RentPrice. This price should be copied to Order's RentPrice when creating one. The car is selecting by user so initially Order.RentPrice is 0.

    Here I want to copy price value:

    [HttpPost]
    public ActionResult Create(Order order)
    {
        order.RentPrice = _context.Cars.Find(order.CarId).RentPrice;
    
        if (ModelState.IsValid)
        {
            _context.Orders.Add(order);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
    
        return View(order);
    }
    

    It's not working because of an error on the SaveChanges that entity has validation errors. OK. I found that need first to call UpdateModel(order); and then change values.

    So what I have. Working code:

    _context.Orders.Add(order);
    UpdateModel(order);
    order.RentPrice = 777;
    _context.SaveChanges();
    

    Not working code:

    _context.Orders.Add(order);
    UpdateModel(order);
    order.RentPrice = _context.Cars.Find(order.CarId).RentPrice;
    _context.SaveChanges();
    

    Working code (!):

    _context.Orders.Add(order);
    UpdateModel(order);
    var t = (double)_context.Cars.Find(order.CarId).RentPrice;
    order.RentPrice = (decimal)t;
    _context.SaveChanges();
    

    Can someone explain, please, what is going on here? Especially magic on the 3nd and 4th lines in the last block of code.

    Update

    I'm getting DbEntityValidationException: "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." From the inner exception: "OriginalValues cannot be used for entities in the Added state."

  • kyrylomyr
    kyrylomyr over 12 years
    EF uses convention over configuration (it takes <name>Id property for this). So, yeah, my database has primary keys. I checked. And how its explain last block of code?..
  • John
    John over 11 years
    Hey sorry I don't have an explanation for your original question only a tip how to get what the error really is from that DbEntityValidationException
  • Dreamcasting
    Dreamcasting over 8 years
    In my case found a mismatched data annotation between my register view model and identity model.