usar tutorial porque net framework entre diferencia definicion asp .net entity-framework entity-framework-6 upsert

.net - tutorial - ¿Cómo puedo usar Entity Framework para hacer un MERGE cuando no sé si el registro existe?



entity framework vb net (4)

En esta respuesta SO sobre Entity Framework y MERGE, el ejemplo de cómo codificarlo es este:

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

Esto supone que usted ya sabe si existe o no la entidad que desea restablecer; en este caso, verifica la entity.Id . entity.Id . Pero, ¿qué pasa si no sabes si el artículo existe o no? Por ejemplo, en mi caso, estoy importando registros de un proveedor a mi base de datos, y un registro dado puede o no haberse importado ya. Quiero actualizar el registro si existe, de lo contrario agrégalo. Pero la identificación del proveedor ya está configurada en ambos casos.

No veo ninguna manera de hacerlo a menos que simplemente pregunte a la base de datos si el registro ya está allí, lo que frustra el propósito de MERGE.


AddOrUpdate es una buena solución, pero no es escalable . Se requiere una ida y vuelta a la base de datos para verificar si la entidad ya existe y un viaje de ida y vuelta para insertar o actualizar la entidad. Por lo tanto, si guarda 1000 entidades, se realizará 2000 viajes de ida y vuelta de la base de datos.

Descargo de responsabilidad : soy el propietario del proyecto Entity Framework Extensions

Esta biblioteca le permite realizar una operación de fusión dentro de Entity Framework al mismo tiempo que mejora drásticamente el rendimiento. Solo se requerirá 1 viaje de ida y vuelta de la base de datos para guardar 1000 entidades.

// Easy to use context.BulkMerge(customers) // Easy to customize context.BulkMerge(customers, operation => { operation.ColumnPrimaryKeyExpression = customer => customer.Code; });


La única manera en que puede cambiar INSERT o UPDATE sql que genera Entity Framework es cuando configura su modelo para usar procedimientos almacenados .

A continuación, puede modificar el sql generado en la migración hacia arriba para crear los procedimientos de inserción y actualización para usar su MERGE sql en lugar de INSERTAR y ACTUALIZAR

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


Si desea un comando UPSERT de base de datos atómica sin un procedimiento almacenado y no le preocupa que se actualice el contexto, cabe mencionar que también puede ajustar una instrucción MERGE incorporada en una llamada ExecuteSqlCommand :

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); }

Esto no es bonito porque funciona fuera de la abstracción de EF sobre entidades, pero le permitirá aprovechar el comando MERGE .


Yo uso AddOrUpdate en esta situación. Sin embargo, creo que consulta la base de datos primero para decidir publicar una inserción o actualización.

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

Actualizar:

Corrí a través de mis archivos de registro de depuración. Primero funciona:

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

Luego se ejecuta ya sea:

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

O:

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

Actualización 2: Aquí hay un método de extensión interesante que usa MERGE: https://gist.github.com/ondravondra/4001192