Krótka odpowiedź:
Grab to: EntityExtensionMethods.cs
Wyjaśnienie
Aby zrobić upsert w LINQ-SQL bez sprawdzania rekordów pierwsze, można wykonać następujące czynności. Będzie on nadal hit db raz, aby sprawdzić, czy rekord istnieje, ale nie będzie ciągnąć rekord:
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();
metodę rozszerzenia
wymyśliłem następującą metodę rozszerzenia dla niego.
public static class EntityExtensionMethods
{
public static void InsertOrUpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
where TEntity : class, new()
{
if (table.Contains(entity)) // if entity exists by PK then update
{
if (original == null)
{
// Create original object with only primary keys set
original = new TEntity();
var entityType = typeof(TEntity);
var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
{
var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
original, new[] {propValue});
}
}
// This will update all columns that are not set in 'original' object. For
// this to work, entity has to have UpdateCheck=Never for all properties except
// for primary keys. This will update the record without querying it first.
table.Attach(entity, original);
}
else // insert
{
table.InsertOnSubmit(entity);
}
}
}
Używaj go jak poniżej:
var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK)
dbContext.Blobs.InsertOrUpdateOnSubmit(blob);
dbContext.Blobs.SubmitChanges();
dodałem powyżej metodę rozszerzenia z więcej rzeczy do tego GIST: EntityExtensionMethods.cs
Cóż ... cały punkt o upsert jest to, że don” t wiedzieć, czy istnieje, czy nie, po prostu chcesz, aby baza danych miała nową zawartość; upsert oszczędza ci "dodatkowy objazd", aby to ustalić. Twoje rozwiązanie nie odpowiada na to; potrzebne jest sql 'MERGE' jak opisano tutaj: http://stackoverflow.com/questions/2479488/syntax-for-single-row-merge-upsert-in-sql-server. – atlaste
Ta odpowiedź dotyczy Entity Framework. Zobacz moją odpowiedź na rozwiązanie LINQ-SQL. – orad