2010-07-06 12 views
6

SQL Server 2008 Ent ASP.NET MVC 2.0 LINQ to SQLse fusionan utilizando LINQ to SQL

Estoy construyendo un sitio de juegos, que realiza un seguimiento cuando un jugador en particular (toon) había caído un monstruo en particular (jefe). Tabla se ve algo como:

int ToonId 
int BossId 
datetime LastKillTime 

que utiliza un servicio 3d partido que me devuelve información más reciente (toon, jefe, tiempo).
Ahora quiero actualizar mi base de datos con esa nueva información.
El enfoque de fuerza bruta consiste en hacer una línea por línea. Pero parece feo (en cuanto al código), y probablemente también lento.

Creo que la mejor solución sería insertar nuevos datos (usando la tabla temporal?) Y luego ejecutar la instrucción MERGE.

¿Es buena idea? Sé que las tablas temporales son "mejores para evitar". ¿Debo crear una tabla permanente "temp" solo para esta operación?
¿O debería simplemente leer todo el conjunto actual (100 filas como máximo), fusionar y volver a colocarlo desde la aplicación?

Cualquier sugerencia es siempre apreciada.

Respuesta

6

Un ORM es la herramienta incorrecta para realizar operaciones por lotes, y Linq-to-SQL no es una excepción. En este caso, creo que ha elegido la solución correcta: almacene todas las entradas en una tabla temporal rápidamente, luego realice la UPSERT usando merge.

La forma más rápida de almacenar los datos en la tabla temporal es usar SqlBulkCopy para almacenar todos los datos en una tabla de su elección.

-1

Parece una inserción directa.

private ToonModel _db = new ToonModel(); 
Toon t = new Toon(); 
t.ToonId = 1; 
t.BossId = 2; 
t.LastKillTime = DateTime.Now(); 
_db.Toons.InsertOnSubmit(t); 
_db.SubmitChanges(); 
+2

¿No me dará "identificación duplicada" si ya tengo Toon con Id = 1? –

6

Si está utilizando LINQ to SQL, upserts no son tan fea ..

foreach (var line in linesFromService) { 
    var kill = db.Kills.FirstOrDefault(t=>t.ToonId==line.ToonId && t.BossId==line.BossId); 
    if (kill == null) { 
     kill = new Kills() { ToonId = line.ToonId, BossId = line.BossId }; 
     db.Kills.InsertOnSubmit(kill); 
    } 
    kill.LastKillTime = line.LastKillTime; 
} 
db.SubmitChanges(); 
No

una obra de arte, pero mejor que en SQL. Además, con solo 100 filas, no me preocuparía demasiado el rendimiento.

+0

Acepto, el rendimiento no es una preocupación aquí, así que use el enfoque LINQ sobre el feo SQL –

0

Para actualizar sin consultar primero los registros, puede hacer lo siguiente. Todavía llegará a la db vez para comprobar si existe registro, pero no se tire el registro:

var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK) 

if (dbContext.Blobs.Contains(blob)) // if blob exists by PK then update 
{ 
    // This will update all columns that are not set in 'original' object. For 
    // this to work, Blob has to have UpdateCheck=Never for all properties except 
    // for primary keys. This will update the record without querying it first. 
    dbContext.Blobs.Attach(blob, original: new Blob { Id = blob.Id }); 
} 
else // insert 
{ 
    dbContext.Blobs.InsertOnSubmit(blob); 
} 
dbContext.Blobs.SubmitChanges(); 

Ver here de un método de extensión para esto.