MERGE используя Linq to SQL - PullRequest
7 голосов
/ 06 июля 2010

SQL Server 2008 Ent ASP.NET MVC 2.0 Linq-to-SQL

Я создаю игровой сайт, который отслеживает, когда определенный игрок (toon) сбил определенного монстра (босса).Таблица выглядит примерно так:

int ToonId
int BossId
datetime LastKillTime

Я использую службу сторонней организации, которая возвращает мне последнюю информацию (toon, boss, time).
Теперь я хочу обновить свою базу данных этой новой информацией.
Подход грубой силы состоит в том, чтобы сделать поэтапное наступление.Но это выглядит некрасиво (с точки зрения кода) и, вероятно, слишком медленно.

Я думаю, что лучшим решением было бы вставить новые данные (используя временную таблицу?), А затем выполнить инструкцию MERGE.

это хорошая идея?Я знаю, что временные таблицы «лучше избегать».Должен ли я создать постоянную «временную» таблицу только для этой операции?
Или я должен просто прочитать весь текущий набор (не более 100 строк), выполнить слияние и вернуть его изнутри приложения?

Любые указатели/ предложения всегда приветствуются.

Ответы [ 4 ]

7 голосов
/ 06 июля 2010

Если вы используете Linq-to-SQL, upserts не так уж и страшны ..

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

Не произведение искусства, но лучше, чем в SQL. Кроме того, с только 100 строками, я не был бы слишком обеспокоен производительностью.

7 голосов
/ 06 июля 2010

ORM - это неправильный инструмент для выполнения пакетных операций, и Linq-to-SQL не является исключением. В этом случае я думаю, что вы выбрали правильное решение: быстро сохраните все записи во временной таблице, а затем выполните UPSERT, используя слияние.

Самый быстрый способ сохранить данные во временной таблице - использовать SqlBulkCopy для сохранения всех данных в таблице по вашему выбору.

0 голосов
/ 23 ноября 2016

Для обновления без запроса записей вы можете сделать следующее. Он все равно ударит по БД один раз, чтобы проверить, существует ли запись, но не получит запись:

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

См. здесь , чтобы узнать способ расширения для этого.

0 голосов
/ 06 июля 2010

Выглядит как прямая вставка.

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();
...