Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DbUpdateConcurrencyException in Entity Framework Code First

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
like image 683
Diego Modolo Ribeiro Avatar asked May 31 '12 17:05

Diego Modolo Ribeiro


People also ask

How do I resolve DbUpdateConcurrencyException?

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.

How do I fix concurrency issues in C#?

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 in Entity Framework?

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.


2 Answers

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.

like image 50
Diego Modolo Ribeiro Avatar answered Oct 04 '22 16:10

Diego Modolo Ribeiro


I suggest, using local scope for Context:

Using(var x = new MyObjectContext){
      //
      //....
      x.SaveChanges(); 
     }
like image 39
A.Dara Avatar answered Oct 04 '22 15:10

A.Dara