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."
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 );
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With