6

Im mit EF4 in VS2010, POCO und der Modell-erste Ansatz.Wie aktualisiert man automatisch die Modified-Eigenschaft einer Entität in Entity Framework 4 beim Speichern?

Meine Entität hat die folgenden Eigenschaften: ID: Guid, Name: Zeichenfolge, Erstellt: DateTime, Geändert: DateTime, Revision: Int32.

Ich erstelle meine Entität, setze den Namen und speichere ihn mit dem EF4-Kontext in der Datenbank. Dies sollte Id zu einem neuen Guid setzen (arbeitet mit Identity-SGP), Created jetzt gesetzt, Modified links wie Null, Revision auf 0 gesetzt. Ich erhole die Entity, ändere den Namen und speichere ihn erneut. Diesmal sollte der Modified-Wert auf jetzt gesetzt werden und die Revision sollte 1.

Wie erreiche ich das am besten mit EF4 mit dem EDMX-Designer?

Update:

Das war, was ich am Ende mit:

public override int SaveChanges(System.Data.Objects.SaveOptions options) 
{ 
    foreach (ObjectStateEntry entry in ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Where(e => e.Entity is EntityBase)) 
    { 
     EntityBase entity = entry.Entity as EntityBase; 
     if (entry.State == EntityState.Added) 
     { 
      entity.Version = new Version() { Major = 1, Minor = 0, Revision = 0 }; 
      entity.Created = DateTime.Now; 
      if (OperationContext.Current != null) entity.CreatedBy = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name; 
     } 
     else if (entry.State == EntityState.Modified) 
     { 
      entity.Version.Revision++; 
      entity.Modified = DateTime.Now; 
      if (OperationContext.Current != null) entity.ModifiedBy = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name; 
     } 
    } 

    return base.SaveChanges(options); 
} 

Welche Arbeit ist nicht ... :(

Das Problem ist, dass die entry.State ist noch nicht modifizierte selbst wenn ich die MarkAsModified() - Methode explizit ausführe, bekomme ich das nicht ...

Warum ist das Änderungs-Tracking nicht standardmäßig aktiviert? Selbst-Tracking-Entitäten so warum sollte ich es wollen und explizit jedes Mal einschalten? Und warum bleiben Entitäten auch dann auf db, wenn der Status unverändert ist? Und was ist der Unterschied zwischen EntityState und ObjectState? Im Moment mache ich alle Änderungen und Updates serverseitig, aber ich werde auch einen WCF-Dienst verwenden, um Entitäten einige Zeit später hin und her zu transferieren ... Gibt es einen Unterschied darin, wie Änderungen hier behandelt werden? Wenn serverseitig alle Änderungen, egal ob Changetracking ein/aus ist, bleibt bestehen ?? Was ich will, ist, dass nichts jemals gespeichert werden könnte, ohne auch Modifiziert, Revision usw. zu aktualisieren. Diese Eigenschaften sollten immer auf dem Server gesetzt werden, wenn das Objekt zurück empfangen und geändert wurde. (Im nicht SQL-Server-Seite hier zu sprechen, aber die Service-Server-Seite)

Antwort

3

Lassen Sie sich Ihren Entitätstyp Namen nehmen ist Produkt:

partial void OnContextCreated() { 
    this.SavingChanges += Context_SavingChanges; 
} 

void Context_SavingChanges(object sender, EventArgs e) { 

    IEnumerable objectStateEntries = 
      from ose 
      in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | 
                  EntityState.Modified) 
      where ose.Entity is Product 
      select ose; 

    Product product = objectStateEntries.Single().Entity as Product; 

    product.ModifiedDate = DateTime.Now; 
    product.ComplexProperty.Revision++; 
} 


Wenn Sie schauen, um diesen Code zu verwenden, zum Bestücken gemeinsamen Feld wie ModifiedDate oder ModifiedBy für alle Ihre Entitäten dann nehmen Sie bitte einen Blick auf diesen Beitrag:
Entity Framework - Auditing Activity

By the way, StoreGeneratedPattern und ConcurrencyMode hat nichts damit zu tun, sie sind für völlig andere und nicht verwandte Dinge da.

+0

Danke Ich werde es ausprobieren, aber gibt es eine Möglichkeit, dies auf dem SQL-Server auf Update zu tun? –

+0

Natürlich können Sie eine Datenbank "Trigger" schreiben, die die Tabelle beim Einfügen und Aktualisieren aktualisieren. Dies ist eine Lösung, um es auf der Client-Seite mit Entity-Framework zu tun. –

+0

Ich habe Ihre Methode versucht, aber ich habe Probleme beim Setzen einer Int-Eigenschaft innerhalb einer ComplexType-Eigenschaft auf der aktualisierten Entität. Ich habe eine ComplexType Version mit drei Ints und ich möchte nur den letzten Wert aktualisieren. Das Setzen einer neuen Version scheitert komplett mit der Ausnahme, dass ich IExtendedDataRecord implementieren muss. Ist das wirklich notwendig? –

0

Ich bin teilweise auf eine clientseitige Code-basierte Lösung, persönlich. Da Sie POCOs verwenden, ist es wahrscheinlich am einfachsten, wenn das Objekt selbst aktualisiert wird. Aktualisieren Sie den Set-Accessor für die Name-Eigenschaft, um eine "objectModified" -Methode aufzurufen, die die Eigenschaften "Modified" und "Revision" ändert.

Wenn das aufgrund des Zeitunterschieds zwischen dem Ändern der Eigenschaft und dem Zeitpunkt des Speicherns des Objekts unangenehm ist, können Sie auf die partielle Klasse Ihres Entities-Objekts tippen. Dadurch können Sie die SaveChanges-Methode überschreiben, bei der Sie Ihre Entitäten in ihrer ObjectSet-Eigenschaft <T> für das Entities-Objekt berühren können.Etwas wie:

public partial class YourEntities 
{ 
    public override int SaveChanges(System.Data.Objects.SaveOptions options) 
    { 
     //update your objects here 
     return base.SaveChanges(options); 
    } 
} 
+0

Aber wenn ich mein SQL von einem anderen Ort aktualisiere, der EF4 nicht benutzt, möchte ich noch die Revisionspalte erhöhen und es wäre schön, wenn sich die Modified-Spalte auch ändert. Ich muss darüber nachdenken, ich kann eine kombinierte Lösung verwenden. Danke für deine Antwort! –

+0

Ich habe die von Ihnen vorgeschlagene Methode ausprobiert, aber wenn Sie neue Objekte hinzufügen, werden sie in meinem Kontext nicht angezeigt. Es ist leer ... irgendeine Idee warum? –

+0

Ich bemerkte, dass ich Entity.StartTracking() explizit ausführen musste, um den Änderungsstatus in "Modified" zu ändern. Wie kann ich das standardmäßig aktivieren? Und warum werden meine Änderungen gespeichert, wenn SaveChanges() ausgeführt wird, wenn ChangeTracking auf OFF steht und State == Unchanged ??? Seltsam ... –

0

Wir können partielle Klasse und überschreiben SaveChanges-Methode, um dies zu erreichen.

using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Data.Entity.Core.Objects; 
using System.Data.Entity.Infrastructure; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Web; 


namespace TestDatamodel 
{ 
    public partial class DiagnosisPrescriptionManagementEntities 
    { 
     public override int SaveChanges() 
     { 
      ObjectContext context = ((IObjectContextAdapter)this).ObjectContext; 

      foreach (ObjectStateEntry entry in 
        (context.ObjectStateManager 
         .GetObjectStateEntries(EntityState.Added | EntityState.Modified))) 
      {      
       if (!entry.IsRelationship) 
       { 
        CurrentValueRecord entryValues = entry.CurrentValues; 
        if (entryValues.GetOrdinal("ModifiedBy") > 0) 
        { 
         HttpContext currentContext = HttpContext.Current; 
         string userId = "nazrul"; 
         DateTime now = DateTime.Now; 

         if (currContext.User.Identity.IsAuthenticated) 
         { 
          if (currentContext .Session["userId"] != null) 
          { 
           userId = (string)currentContext .Session["userId"]; 
          } 
          else 
          {          
           userId = UserAuthentication.GetUserId(currentContext .User.Identity.UserCode); 
          } 
         } 

         if (entry.State == EntityState.Modified) 
         { 
          entryValues.SetString(entryValues.GetOrdinal("ModifiedBy"), userId); 
          entryValues.SetDateTime(entryValues.GetOrdinal("ModifiedDate"), now); 
         } 

         if (entry.State == EntityState.Added) 
         { 
          entryValues.SetString(entryValues.GetOrdinal("CreatedBy"), userId); 
          entryValues.SetDateTime(entryValues.GetOrdinal("CreatedDate"), now); 
         } 
        } 
       } 
      } 

      return base.SaveChanges(); 
     } 
    } 
} 
Verwandte Themen