2017-07-14 4 views
1

Hallo! Ich habe Entity Framework Core 2.xx ORM-Lösung und alle meine Objekte im Modell haben erstellt (UTC-Zeitstempel der Datenbankerstellungszeit - nie aktualisiert) und geändert Feld (immer aktualisiert, wenn Entität aktualisiert wird). Ich lese eine Vorschlagsimplementierung für dieses sehr häufige Problem und es sieht so aus, als ob das Framework es noch nicht gut unterstützt, da es keinen guten Weg gibt, dies zu tun, ohne die Zuordnung für jede Entität separat zu definieren. Eine Problemumgehung, die ich fand, war, eine nicht zugeordnete Superklasse zu definieren und dann manuell einen Wertgenerierungsschritt zu generieren. Da db UTCDatetime db side feature ist, muss ich auch manuell definieren, dass ich die utc datetime Funktion in db verwende. Ich weiß, wie das wie das mit fließend api in Modellgeneration zu tun:Entity Framework Core Geänderte und erstellte Felder mit Concurrency-Tokens

// dieses Beispiel fehlt die Definition dessen, was db Anruf:

modelBuilder.Entity<MyObject>() 
     .Property(p => p.Timestamp) 
     .ValueGeneratedOnAddOrUpdate() 
     .IsConcurrencyToken(); 

und ich kann UTC-Zeit Generation in der Migration wie hinzufügen dies:

AddColumn("MyObject", "Created", n => n.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"));` 

Aber meine Frage ist: Wie kann ich das tun, wenn ich alles automatisch mit MyBaseObject Superklasse mache? (Es hat diese Felder Modified und Created und ist nicht zugeordnet). Ich mache es zur Zeit so, aber ich weiß nicht, wie Back-End-Feld Erstellt Aufruf ‚getUTCDate()‘ definieren

if (entityType.ClrType.IsSubclassOf(typeof(MyBaseObject))) 
{ 
        var guidProperty = entityType.FindProperty(nameof(MyBaseObject.GUID)); 
        var createdProperty = entityType.FindProperty(nameof(MyBaseObject.Created)); 
        var modifiedProperty = entityType.FindProperty(nameof(MyBaseObject.Modified)); 

        entityType.AddKey(guidProperty); 
        entityType.SetPrimaryKey(guidProperty);      
        guidProperty.ValueGenerated = ValueGenerated.OnAdd; 


        modifiedProperty.ValueGenerated = ValueGenerated.OnAddOrUpdate; 
        modifiedProperty.IsReadOnlyBeforeSave = true; 
        //modifiedProperty.SetValueGeneratorFactory(); 

        createdProperty.ValueGenerated = ValueGenerated.OnAdd; 
        createdProperty.IsReadOnlyBeforeSave = true; 

        entityType.AddProperty("GUID", typeof(Guid)); 
        entityType.AddProperty("Created", typeof(DateTime)); 
        entityType.AddProperty("Modified", typeof(DateTime)); 
        entityType.AddIndex(modifiedProperty); 
        entityType.AddIndex(createdProperty); 
} 

Antwort

3

Ich würde vorschlagen, eine erzwungenes generische Methode oder Klasse zu schaffen und mit einem normalen fließend API innen um die allgemeinen Attribute zu konfigurieren.

Zum Beispiel eine generische Klasse ModelBuilder im Konstruktor Empfang:

class MyBaseObjectConfiguration<TEntity> where TEntity : MyBaseObject 
{ 
    public MyBaseObjectConfiguration(ModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<TEntity>() 
      .HasKey(e => e.GUID); 

     modelBuilder.Entity<TEntity>() 
      .Property(e => e.GUID) 
      .ValueGeneratedNever(); 

     modelBuilder.Entity<TEntity>() 
      .Property(e => e.Created) 
      .ValueGeneratedOnAdd() 
      .HasDefaultValueSql("GETUTCDATE()"); 

     modelBuilder.Entity<TEntity>() 
      .Property(e => e.Modified) 
      .ValueGeneratedOnAddOrUpdate() 
      .HasDefaultValueSql("GETUTCDATE()") 
      .IsConcurrencyToken(); 
    } 
} 

und nennen es mit Reflexion im Inneren OnModelCreating:

foreach (var type in modelBuilder.Model.GetEntityTypes().Where(t => t.ClrType.IsSubclassOf(typeof(MyBaseObject)))) 
    Activator.CreateInstance(typeof(MyBaseObjectConfiguration<>).MakeGenericType(type.ClrType), modelBuilder); 
+0

Danke - das eigentlich war, was ich zu finden, ideal! – kamakaze

Verwandte Themen