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

后端 未结 4 1054
滥情空心
滥情空心 2020-12-05 04:27

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)         


        
相关标签:
4条回答
  • 2020-12-05 04:48

    The only way you can change INSERT or UPDATE sql that Entity Framework generates is when you configure your model to use stored procedures.

    You can then modify the sql generated in the Up migration for creating the insert and update procedures to use your MERGE sql rather than INSERT and UPDATE

     CREATE PROCEDURE [dbo].[Blog_Insert]  
      @Name nvarchar(max),  
      @Url nvarchar(max)  
    AS  
    BEGIN 
      -- Your Merge Sql goes here
    
      --And you need to use MERGE OUTPUT to get the primary key 
      --instead of SCOPE_IDENTITY()
      --SELECT SCOPE_IDENTITY() AS BlogId 
    END
    
    0 讨论(0)
  • 2020-12-05 04:51

    I use AddOrUpdate in this situation. However, I believe it does query the database first in order to decide to issue an insert or update.

    context.MyEntities.AddOrUpdate(e => e.Id, entity);
    

    Update:

    I ran through my debug log files. First it runs:

    SELECT TOP (2) ... WHERE 1 = [Extent1].[Id]
    

    Then it runs either:

    INSERT [dbo].[TestTable](...) VALUES (...)
    SELECT [Id]
    FROM [dbo].[TestTable]
    WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
    

    OR:

    UPDATE [dbo].[TestTable]
    SET ...
    WHERE ([Id] = @2)
    

    Update 2: Here's an interesting extension method the uses MERGE: https://gist.github.com/ondravondra/4001192

    0 讨论(0)
  • 2020-12-05 04:53

    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;
    });
    
    0 讨论(0)
  • 2020-12-05 05:13

    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.

    0 讨论(0)
提交回复
热议问题