2014-11-20 1 views
15

Я немного искал свою проблему, но не могу найти ничего, что действительно поможет.Entity Framework - UPSERT по уникальным индексам

Так что моя проблема/Дилем остается так: Я знаю, что база данных MySQL имеет уникальную систему индексов, которые могут быть использованы для вставки/обновления в одном запросе, используя этот формат: insert into t(a,b,c) values(1,1,1) on duplicate keys update b=values(b),c=values(c); и заменить формат, используемый для замены существующая запись по этому индексу.

быть честным только аналогичный материал, который я видел в MSSQL это merge, но я действительно не нравится вообще, и проверки запроса для вставки или обновления не уникальный индекс, основанный в конце концов ...

Итак, как я могу подражать уникальному UPSERT mysql в Entity Framework? это моя главная проблема ...

Я имею в виду, не получив запись из набора объектов и проверив ее, если она равна нулю или нет для возможной вставки или обновления;

Могу ли я получить его? Или нет? Любой намек может быть полезным

Я видел this, но не появляется в версии 6 ...

пример объекта:

[Table("boats")] 
    public class Boat 
    { 
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
     public int id { get; set; } 
     [MaxLength(15)] 
     [Index("IX_ProviderBoat",1,IsUnique=true)] 
     public string provider_code { get; set; } 
     public string name { get; set; } 
     [Index("IX_ProviderBoat", 3, IsUnique = true)] 
     [MaxLength(50)] 
     public string model { get; set; } 
     [Index("IX_ProviderBoat", 2, IsUnique = true)] 
     [MaxLength(15)] 
     [Key] 
     public string boat_code { get; set; } 
     public string type { get; set; } 
     public int built { get; set; } 
     public int length { get; set; }    
    } 

Так что я хочу, чтобы обновить/вставить на основе моего IX_ProviderBoat уникальный индекс, используя EF

enter image description here

+1

Ваша модель данных не идеальна для EF. Вам нужно иметь «Boat.id», а также три уникальных ключа на вашей лодке? Почему бы вам не использовать «Boat.provider_code» в качестве основного ключа? Кроме того, 'AddOrUpdate()' доступен в EF6. – wahwahwah

+0

AddOrUpdate доступен в EntityFramework6. Возможно, вам придется проверять другие перегрузки, например, упомянутые http://stackoverflow.com/questions/22287852/entityframework-6-addorupdate-not-working-with-compound-or-composite-primary-key –

+0

@wahwahwah 1) id это просто идентификатор (а не первичный ключ); 2) AddOrUpdate не просматривается в моей версии 6.0.0.0 EF; 3) provider_code - это первичный ключ, а также уникальная группа элементов индекса; – HellBaby

ответ

15

метод AddOrUpdate является членом IDBSet и является доступный в EF6.

AddOrUpdate метод не является атомарной операцией, требует от нескольких потоков не гарантирует второй поток Update вместо Add снова рый - так что вы можете получить дубликаты записей хранятся.

Этот пример был протестирован и работает с вашими ожиданиями:

 Boat boat = new Boat // nullable fields omitted for brevity 
     { 
      boat_code = "HelloWorld", 
      id = 1, 
      name = "Fast Boat", 
      built = 1, 
      length = 100 
     }; 

     using (BoatContext context = new BoatContext()) // or whatever your context is 
     { 
      context.Set<Boat>().AddOrUpdate(boat); // <-- IDBSet!!! 
      context.SaveChanges(); 
     } 

Если мы изменим boat_code метод AddOrUpdate() добавит новую запись. Если boat_code является «HelloWorld», он обновит существующую запись. Я считаю, что это то, что вы ищете ...

Надеюсь, это поможет!

+7

Просто чтобы вы знали ... этот вопрос не является потоковым ... как я нашел в производстве на днях ...> _ < – Aron

+0

Это зависит от того, как вы распоряжаетесь своим контекстом ... этот метод не имеет ничего общего с безопасностью потоков. И когда я говорю «ничего не делать», я имею в виду, вы должны явно называть GC в какой-то момент вашего кода, если только вы не используете шаблон EF. – wahwahwah

+7

Два потока, два контекста, одна команда, одно и то же время. Дублированные вставки ... много веселья! Я надеялся, что EF будет использовать «MERGE» атомарно. Но он использует select/insert/update. – Aron