An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext

zach picture zach · Aug 31, 2013 · Viewed 10.6k times · Source

I've got a problem with NotSupportedException, I'm getting: "An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext."

partial class SupplyOfert : Model
{
    public SupplyOfert(int id = 0)
    {
        if (id > 0)
            this.get(id);
    }

    public Supplier supplier
    {
        get
        {
            return this.Supplier;
        }
        set
        {
            this.Supplier = db.Suppliers.SingleOrDefault(s => s.id == value.id);
        }
    }

    public override bool get(int id)
    {
        SupplyOfert so = (SupplyOfert)db.SupplyOferts.SingleOrDefault(s => s.id == id).Copy(this, "Supplies");
        this._Supplies = so._Supplies;
        so._Supplies.Clear();
        if (this.id > 0)
        {
            db.Dispose();
            db = new Database();
            db.SupplyOferts.Attach(this);  // here I'm getting the exception
            return true;
        }
        else
            return false;
    }

    public override void save()
    {
        if (this.id <= 0)
            db.SupplyOferts.InsertOnSubmit(this);
        db.SubmitChanges();
    }

    public override void remove()
    {
        if (this.id > 0)
        {
            db.SupplyOferts.DeleteOnSubmit(this);
            db.SubmitChanges();
        }
    }
}

When I add new record with:

SupplyOfert ofert = new SupplyOfert();
ofert.price = 100;
ofert.publisher = "some publisher";
ofert.supplier = new Supplier(1);
ofert.title = "some title";
ofert.year = DateTime.Today;
ofert.save();

It's ok, but when I want to update record, using:

SupplyOfert ofert = new SupplyOfert(2);
ofert.price = 220;
ofert.publisher = "new publisher";
ofert.save();

I'm getting "NotSupportedExceptionw was unhandled".

Here's the Model class:

public abstract class Model
{
    protected Database db = new Database();

    public Model(){}

    ~Model()
    {
        db.Dispose();
    }

    abstract public bool get(int id);
    abstract public void save();
    abstract public void remove();

}

And here's the copy method:

public static class ObjectProperties
{
    public static object Copy(this object source, object destination, string skip = "")
    {
        if (source != null)
        {
            foreach (var sourceProperty in source.GetType().GetProperties())
            {
                foreach (var destinationProperty in destination.GetType().GetProperties())
                {
                    if (destinationProperty.Name == sourceProperty.Name && destinationProperty.Name != skip)
                        destinationProperty.GetSetMethod().Invoke(destination, new object[] { sourceProperty.GetGetMethod().Invoke(source, null) });
                }
            }
        }
        else
            destination = null;
        return source;
    }
}

Database class it's only:

public class Database : DataClasses1DataContext

I've found out, that this problem is connected with assignment:

this.supplier = so.supplier;

But I don't know why...

Answer

Matthew picture Matthew · Aug 31, 2013

The issue here looks like you are creating a separate context with each entity (Model has a new copy of db instantiated). So what happens is:

  1. You create the object and it has a context object in the entity to which it is attached
  2. You create a new object with it's own context class and set the properties you want to update
  3. It tries to save and throws an exception that the entity is already loaded in another context - the one in which it was created.

The first step to correcting this is to not create a new context inside the entity.