How can I use use Entity Framework to do a MERGE when I don't know if the record exists?

.net entity-framework entity-framework-6 upsert

Question

In this SO answer about Entity Framework and MERGE, the example for how to code it is this:

public void SaveOrUpdate(MyEntity entity)
{
  if (entity.Id == 0)
  {
    context.MyEntities.AddObject(entity);
  }
  else
  {
    context.MyEntities.Attach(entity);
    context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
  }
}

This assumes that you already know if the entity that you want to upsert exists or not; in this case you check entity.Id. But what if you don't know if the item exists or not? For instance, in my case, I'm importing records from a vendor into my database, and a given record may or may not have already been imported. I want to update the record if it exists, otherwise add it. But the vendor's id is already set in both cases.

I can't see any way to do this unless I simply ask the database if the record is there already, which defeats the whole purpose of MERGE.

2
37
5/23/2017 12:26:23 PM

Accepted Answer

If you want an atomic database UPSERT command without a stored procedure and you're not worried about the context being updated, it might worth mentioning that you can also wrap an embedded MERGE statement in an ExecuteSqlCommand call:

public void SaveOrUpdate(MyEntity entity)
{
    var sql =  @"MERGE INTO MyEntity
                USING 
                (
                   SELECT   @id as Id
                            @myField AS MyField
                ) AS entity
                ON  MyEntity.Id = entity.Id
                WHEN MATCHED THEN
                    UPDATE 
                    SET     Id = @id
                            MyField = @myField
                WHEN NOT MATCHED THEN
                    INSERT (Id, MyField)
                    VALUES (@Id, @myField);"

    object[] parameters = {
        new SqlParameter("@id", entity.Id),
        new SqlParameter("@myField", entity.myField)
    };
    context.Database.ExecuteSqlCommand(sql, parameters);
}

This isn't pretty because it works outside EF's abstraction over entities but it will allow you to leverage the MERGE command.

12
1/6/2017 10:05:07 PM

Expert Answer

AddOrUpdate is a good solution however it's not scalable. One database round-trip is required to check if the entity already exists and one round-trip to insert or update the entity. So, if you save 1000 entities, 2000 database round-trip will be performed.

Disclaimer: I'm the owner of the project Entity Framework Extensions

This library allows you to perform a merge operation within Entity Framework at the same time it dramatically improves the performance. Only 1 database round-trip will be required to save 1000 entities.

// Easy to use
context.BulkMerge(customers)

// Easy to customize
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});
10
8/22/2018 10:07:21 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow