2010-10-12 12 views
6

Im usando EF4 in VS2010, POCO e l'approccio del primo modello.Come aggiornare automaticamente la proprietà modificata su un'entità in Entity Framework 4 quando si salva?

La mia entità ha le seguenti proprietà: Id: Guid, Nome: String, Creato: DateTime, Modificato: DateTime, Revision: Int32.

Ho creato la mia entità, impostato il nome e salvato nel database utilizzando il contesto EF4. Questo dovrebbe impostare Id su un nuovo Guid (funziona con Identity-SGP), Creato su adesso, Modificato a sinistra come null, Revision su 0. Ritrovo l'entità, cambio il nome e lo salvi di nuovo. Questa volta il valore modificato dovrebbe essere impostato su ora e la revisione dovrebbe essere 1.

Come faccio a ottenere questo risultato utilizzando EF4 con il progettista EDMX?

Aggiornamento:

Questo era quello che ho finito per usare:

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

che costerà di lavoro ... :(

Il problema è che l'entry.State è ancora non modificato anche se eseguo esplicitamente il metodo MarkAsModified(). Non riesco a ottenere questo ...

Perché il rilevamento delle modifiche non è abilitato per impostazione predefinita? le entità di auto-tracciamento, quindi perché dovrei volerlo e accenderlo esplicitamente ogni volta? E perché le entità sono tenute a db anche se lo stato non è modificato? E qual è la differenza tra EntityState e ObjectState? Al momento sto facendo tutte le modifiche e aggiorno i server, ma userò anche un servizio WCF per trasferire le entità avanti e indietro qualche tempo dopo ... C'è una differenza nel modo in cui le modifiche vengono trattate qui? Se serveride tutte le modifiche, indipendentemente dall'attivazione/disattivazione del changetracking, vengono mantenute ?? Quello che voglio è che nulla dovrebbe mai essere in grado di essere memorizzato senza aggiornare anche Modified, Revision ecc. Queste proprietà dovrebbero sempre essere impostate sul server quando l'oggetto viene ricevuto e modificato. (Non sto parlando sql-server-side qui ma il servizio-lato server)

risposta

3

Supponiamo che il nome Tipo di entità è prodotto:

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++; 
} 


Se siete alla ricerca per utilizzare questo codice per popolare comune campo come ad esempio ModifiedDate o ModifiedBy per tutti i soggetti quindi si prega di dare un'occhiata a questo post:
Entity Framework - Auditing Activity

a proposito, StoreGeneratedPattern e ConcurrencyMode non ha nulla a che fare con questo, sono lì per cose completamente diverse e non correlate.

+0

Grazie, proverò, ma c'è un modo per farlo sullo sql-server durante l'aggiornamento? –

+0

Ovviamente, è possibile scrivere un "trigger" del database che aggiorna la tabella su insert e update. Questa è una soluzione per farlo sul lato client con il framework di entità. –

+0

Ho provato il metodo, ma ho problemi a impostare una proprietà int in una proprietà ComplexType sull'entità aggiornata. Ho una versione ComplexType con tre interi e voglio solo aggiornare l'ultimo valore. L'impostazione di una nuova versione fallisce completamente con un'eccezione che mi dice che devo implementare IExtendedDataRecord. È davvero necessario? –

0

Sono parziale a una soluzione basata sul codice lato client, personalmente. Dal momento che stai usando POCO, probabilmente sarebbe più semplice avere l'oggetto stesso a fare l'aggiornamento. Aggiorna il set accessor sulla proprietà Name per chiamare un metodo "objectModified" che modifica le proprietà Modified e Revision.

Se ciò non è gradevole a causa della differenza di tempo tra il momento in cui la proprietà viene modificata e il momento in cui l'oggetto viene salvato, è possibile toccare la classe parziale sull'oggetto Entities. Ciò consentirà di ignorare il metodo SaveChanges in cui puoi toccare le tue entrate nella loro proprietà ObjectSet <T> nell'oggetto Entities.Qualcosa di simile:

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

Ma se aggiorno il mio SQL da un altro posto che non usa EF4, vorrei comunque che la colonna Revision aumentasse e sarebbe bello se anche la colonna Modified fosse cambiata. Devo pensarci su, posso usare una soluzione combinata. Grazie per la tua risposta! –

+0

Ho provato il metodo che hai suggerito ma quando aggiungi nuovi oggetti non vengono visualizzati nel mio contesto.Entities. È vuoto ... qualche idea del perché? –

+0

Notato che ho dovuto eseguire esplicitamente entity.StartTracking() per farlo cambiare stato a modificato. Come posso accedervi per impostazione predefinita? E perché le mie modifiche vengono salvate quando si esegue SaveChanges() quando ChangeTracking è OFF e State == Invariato ??? Weird ... –

0

Possiamo usare classe parziale e sovrascrivere il metodo SaveChanges per raggiungere questo obiettivo.

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(); 
     } 
    } 
} 
Problemi correlati