This load and detach trick in your UPDATE is not necessary. You can just only ask the database if the entity already exists or not without loading it (using Any()
instead of FirstOrDefault()
):
public void InsertOrUpdate(T entity, Expression<Func<T, bool>> Findpredicate)
{
bool exists = this.FindBy(Findpredicate).Any();
if (exists)
{
context.CreateObjectSet<T>().Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
else
{
context.CreateObjectSet<T>().AddObject(entity);
}
context.SaveChanges();
}
Alternatively you can load the original entity from the database and update its properties with the modified detached entity (with ApplyCurrentValues
). It has the benefit that only the properties that have really changed are sent with the UPDATE statement to the database (but at the cost that the original entity must be loaded) while setting the whole entity state to Modified
will also send the unchanged properties with the UPDATE to the DB (but with the benefit that the orginal doesn't need to be loaded):
public void InsertOrUpdate(T entity, Expression<Func<T, bool>> Findpredicate)
{
T _dbRecord = this.FindBy(Findpredicate).FirstOrDefault();
if (_dbRecord != null)
{
context.CreateObjectSet<T>().ApplyCurrentValues(entity);
}
else
{
context.CreateObjectSet<T>().AddObject(entity);
}
context.SaveChanges();
}
Note that both solutions only work to update scalar properties of an entity. It doesn't work with changed relationships and navigation properties. There is no simple generic solution for this more general Update scenario with arbitrary object graphs.