I'm having a issue with Entity Framework and Code First. I have an entity with a Timestamp property, and I add an new record to the database, call SaveChanges, and it's all ok. When I try to delete the record I've just added, I get the following message:
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.
It seems to me that EF has no knowledge that this new record exists in database, despite the fact that it is there. Sometimes, even when I try to update an different record I get the same message, but if I try to delete an different one it works.
Does anyone knows why this is happening?
Thanks in advance, Diego
EDIT I've assembled some code to make it easier to understand my problem:
I have two simple entities:
public class Entidade1
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Descricao { get; set; }
[Timestamp]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte[] RecTS { get; set; }
}
public class Entidade2
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Descricao { get; set; }
[Timestamp]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte[] RecTS { get; set; }
public virtual Entidade1 Entidade1 { get; set; }
}
The Context:
public class DB : DbContext
{
public DB() : base("DB")
{
this.Configuration.AutoDetectChangesEnabled = true;
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = true;
}
public DbSet<Entidade1> Entidade1 { get; set; }
public DbSet<Entidade2> Entidade2 { get; set; }
}
And the code:
var item = new Entidade1();
item.Descricao = "teste";
var db = new DB();
db.Set(typeof(Entidade1)).Add(item);
db.SaveChanges();
var item2 = new Entidade2();
item2.Descricao = "teste 2";
item2.Entidade1 = item;
db.Set(typeof (Entidade2)).Add(item2);
db.SaveChanges();
var q = (from c in db.Entidade1
where c.Descricao == "teste"
select c).FirstOrDefault();
db.Set(typeof(Entidade1)).Remove(q);
db.SaveChanges();
var q2 = (from c in db.Entidade2
where c.Descricao == "teste 2"
select c).FirstOrDefault();
db.Set(typeof (Entidade2)).Remove(q2);
db.SaveChanges(); // Here I got the error
Custom resolution of optimistic concurrency exceptions SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Get the current entity values and the values in the database var entry = ex. Entries. Single(); var currentValues = entry. CurrentValues; var databaseValues = entry.
Concurrency problems can be solved by implementing a proper "Locking strategy". Locks prevent action on a resource to be performed when some other resource is already performing some action on it.
How can we do pessimistic locking? We can do pessimistic locking by specifying “IsolationLevel” in SQL Server stored procedures, ADO.NET level or by using transaction scope object.
I've found out that the problem is a known bug in Entity Framework 4.0, and that it's presente since 2010 and will be resolved in the next version (hope in 4.5). When I update an object that has related objects, EF tries to update all the relations, and as nothing has changed in the parentes, it will give me the '0 rows' message.
Hope it helps someone.
I suggest, using local scope for Context:
Using(var x = new MyObjectContext){ // //.... x.SaveChanges(); }
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