2016-03-24 8 views

Antwort

12

Es wartet auf die Implementierung. Siehe Ausgaben #629 & #4526.

+1

Ihre Antwort ist ein datiert und vor einem halben Jahr. Wartet es noch auf die Implementierung? Es scheint, dass es alle zusammen fallen gelassen wurde ... –

+1

Wir haben ein alternatives Design für Seed-Daten entwickelt, so dass es nicht als Teil davon implementiert wird. Das andere Problem ist immer noch eine Möglichkeit. – bricelam

+0

hi @bricelam, welche Alternativen gibt es heute, um Daten in EF Core zu seed? Könnten Sie sie teilen? – octavioccl

2

können Sie diese Erweiterung Methode Ich habe unsere Code-Basis für die Migration auf EF Core-Patch:

public static void AddOrUpdate<T>(this DbSet<T> dbSet, T data) where T : class 
     { 
      var t = typeof(T); 
      PropertyInfo keyField = null; 
      foreach (var propt in t.GetProperties()) 
      { 
       var keyAttr = propt.GetCustomAttribute<KeyAttribute>(); 
       if (keyAttr != null) 
       { 
        keyField = propt; 
        break; // assume no composite keys 
       } 
      } 
      if (keyField == null) 
      { 
       throw new Exception($"{t.FullName} does not have a KeyAttribute field. Unable to exec AddOrUpdate call."); 
      } 
      var keyVal = keyField.GetValue(data); 
      var dbVal = dbSet.Find(keyVal); 
      if (dbVal != null) 
      { 
       dbSet.Update(data); 
       return; 
      } 
      dbSet.Add(data); 
     } 
+1

Dies funktioniert nicht wirklich, da EF Core nur den üblichen Tracking Error auslöst. Es sieht so aus, als würde EF Core die Entität nach 'find()' verfolgen und wenn 'update' aufgerufen wird, wird ein Fehler ausgegeben, dass diese Entity bereits verfolgt wird. Es ist peinlich, weil EF möglicherweise bereits die Entity verfolgt, und das kann sie greifen, wenn sie zur DB geht. –

+0

Ich habe das gerade in meinem EF Core 1.1 Projekt überprüft und es funktioniert gut. Der Code arbeitet seit Ende Mai an der Produktion. – Tjaart

+0

Ich stimme Douglas Gaskell zu, diese Lösung funktioniert nur, wenn die Änderungsverfolgung auf Kontextebene deaktiviert ist, was für uns keine Option war. Siehe meine Lösung unten für eine alternative Implementierung. – MSC

2

Diese Lösung ist, denke ich, eine einfachere Lösung für dieses Problem, wenn eine Basis-Entity-Klasse eine legitime Option ist. Die Einfachheit kommt von Ihren Domain-Entities, die DomainEntityBase implementieren, wodurch viele der Komplexitäten in den anderen vorgeschlagenen Lösungen gemildert werden.

public static class DbContextExtensions 
{ 
    public static void AddOrUpdate<T>(this DbSet<T> dbSet, IEnumerable<T> records) 
     where T : DomainEntityBase 
    { 
     foreach (var data in records) 
     { 
      var exists = dbSet.AsNoTracking().Any(x => x.Id == data.Id); 
      if (exists) 
      { 
       dbSet.Update(data); 
       continue; 
      } 
      dbSet.Add(data); 
     } 
    } 
} 

public class DomainEntityBase 
{ 
    [Key] 
    public Guid Id { get; set; } 
} 
+0

Das zwingt Sie, jedes Modell von dieser Basis zu erben, und das ist keine gute Idee für die Domäne, denke ich. – SuperJMN

+0

Guter Punkt. Beachten Sie, dass wir nur add-or-update für Seeding-Test-/Referenzdaten verwenden und dass alle Entitäten, die wir verwenden, Guid-IDs haben, sodass es für unseren Anwendungsfall gut funktioniert. – MSC

+0

Sie kehren nach dem ersten Update von der Schleife zurück. Ist es beabsichtigt? –

1

Ich habe eine schöne Lösung gefunden, die Sie die Eigenschaft festlegen können, die übereinstimmen sollten. Es benötigt jedoch keine einzelne Entität, sondern eine Liste in jedem Aufruf. Es kann Ihnen einige Hinweise geben, wie Sie eine bessere Version implementieren können, die wie die gute Version funktioniert.

https://github.com/aspnet/MusicStore/blob/7787e963dd0b7293ff95b28dcae92407231e0300/samples/MusicStore/Models/SampleData.cs#L48

(-Code ist nicht meine)

+0

Es lädt alle vorhandenen Datensätze im Speicher, die überhaupt nicht skalierbar sind. –

+0

Kennen Sie einen besseren Weg? ;) – SuperJMN

+0

https://github.com/mcshaz/PicuCalendars/blob/master/PicuCalendars/DataAccess/EFExtensions.cs, möglicherweise [Wo wird eine Dublettenprüfung für eine Entität ausgeführt] (// stackoverflow.com/a/16647237), –

0

Es ist eine Erweiterung Methode Upsert.

context.Upsert(new Role { Name = "Employee", NormalizedName = "employee" }) 
     .On(r => new { r.Name }) 
     .Run(); 

On Github