Inserción o actualización masiva dentro de la misma función con Dapper

dapper sql sql-server sql-server-2008

Pregunta

Quiero crear una función en mi Capa de acceso a datos que recorra una lista de contactos y que INSERTAR o ACTUALIZAR según el contacto sea nuevo o existente.

Sé con Dapper que puede hacer una inserción masiva simplemente creando una instrucción INSERT y pasándole una lista de objetos. ¿Es posible hacer lo mismo con una actualización BULK? O mejor aún un BULK InsertOrUpdate.

Aquí está mi solución, ¿hay una mejor manera? Realmente no quería tener que llamar a la función de ejecución una vez para cada contacto en la lista.

StringBuilder insertSql = new StringBuilder();
insertSql.AppendLine("INSERT INTO Contact (FirstName, LastName, Email ");
insertSql.AppendLine("VALUES(@FirstName, @LastName, @Email);");

StringBuilder updateSql = new StringBuilder();
updateSql.AppendLine("UPDATE Contact ");
updateSql.AppendLine("SET FirstName = @FirstName, ");
updateSql.AppendLine("    LastName = @LastName, ");
updateSql.AppendLine("    Email = @Email ");
updateSql.AppendLine("WHERE Id = @Id");

foreach (Contact contact in contacts)
{
    if (contact.Id == 0)
    {
        context.Database.Connection.Execute(insertSql.ToString(), contact);
    }
    else
    {
        context.Database.Connection.Execute(updateSql.ToString(), contact);
    }
}

Respuesta popular

No puedo hablar con Dapper, lo eché un vistazo rápido y parece que Dapper necesitaría primero admitir la funcionalidad MERGE, que puede que no. Pero, dado lo que dijo anteriormente, esto es lo que haría.

Primero, use Dapper para insertar de forma masiva los contactos en una tabla temporal, luego construya su declaración MERGE y ejecútela.

Llamemos a la tabla temp1. En temp1, la fila con id = 2 reemplazará la fila con id = 2 en los contactos, y la fila con id = 3 se insertará en los contactos.

create table contacts (id int, alias varchar(10))
create table temp1 (id int, alias varchar(10))
go

insert into temp1 values (2, 'nameX'), (3, 'name3')
insert into contacts values (1, 'name1'), (2, 'name2')
go

MERGE contacts c
USING temp1 t
ON (c.id = t.id) 
WHEN NOT MATCHED BY TARGET
    THEN INSERT(id, alias) VALUES(t.id, t.alias)
WHEN MATCHED 
    THEN UPDATE SET c.alias = t.alias
;
go

select * from contacts
go


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué