Ho un'applicazione MVC che utilizza Entity Framework 5. In alcuni punti ho un codice che crea o aggiorna le entità e quindi devo eseguire un qualche tipo di operazioni sui dati aggiornati . Alcune di queste operazioni richiedono l'accesso alle proprietà di navigazione e non riesco a farle aggiornare.Entity Framework 5 - Aggiorna immediatamente DbContext dopo aver salvato le modifiche
Ecco l'esempio (codice semplificato che ho)
modelle
class User : Model
{
public Guid Id { get; set; }
public string Name { get; set; }
}
class Car : Model
{
public Guid Id { get; set; }
public Guid DriverId { get; set; }
public virtual User Driver { get; set; }
[NotMapped]
public string DriverName
{
get { return this.Driver.Name; }
}
}
controller
public CarController
{
public Create()
{
return this.View();
}
[HttpPost]
public Create(Car car)
{
if (this.ModelState.IsValid)
{
this.Context.Cars.Create(booking);
this.Context.SaveChanges();
// here I need to access some of the resolved nav properties
var test = booking.DriverName;
}
// error handling (I'm removing it in the example as it's not important)
}
}
L'esempio di cui sopra è per il metodo Create ma ho anche lo stesso problema con il metodo di aggiornamento che è molto simile prende solo il oggetto dal contesto nell'azione GET
e lo memorizza utilizzando il metodo Update
nell'azione POST
.
public virtual void Create(TObject obj)
{
return this.DbSet.Add(obj);
}
public virtual void Update(TObject obj)
{
var currentEntry = this.DbSet.Find(obj.Id);
this.Context.Entry(currentEntry).CurrentValues.SetValues(obj);
currentEntry.LastModifiedDate = DateTime.Now;
}
Ora ho provato diversi approcci che ho cercato su google o trovato nello stack ma nulla sembra funzionare per me.
Nel mio ultimo tentativo, ho provato a forzare una ricarica dopo aver chiamato il metodo SaveChanges
e aver richiesto i dati dal database. Ecco cosa ho fatto.
ho ovewrite il metodo SaveChanges
per aggiornare contesto dell'oggetto subito dopo il salvataggio
public int SaveChanges()
{
var rowsNumber = this.Context.SaveChanges();
var objectContext = ((IObjectContextAdapter)this.Context).ObjectContext;
objectContext.Refresh(RefreshMode.StoreWins, this.Context.Bookings);
return rowsNumber;
}
Ho provato ottenere i dati oggetto aggiornato con l'aggiunta di questa riga di codice immediatamente dopo SaveChanges
chiamata nel mio HTTP
Create
e Update
azioni:
car = this.Context.Cars.Find(car.Id);
Purtroppo la proprietà di navigazione è ancora null
. Come posso aggiornare correttamente DbContext subito dopo aver modificato i dati?
EDIT
ho dimenticato di menzionare in origine che so una soluzione, ma è brutto e non mi piace. Ogni volta che utilizzo la proprietà di navigazione posso verificare se è null
e se è possibile posso creare manualmente nuovo DbContext e aggiornare i dati. Ma mi piacerebbe davvero evitare gli hack come questo.
class Car : Model
{
[NotMapped]
public string DriverName
{
get
{
if (this.Driver == null)
{
using (var context = new DbContext())
{
this.Driver = this.context.Users.Find(this.DriverId);
}
}
return this.Driver.Name;
}
}
}
E la mia 'metodo Update'? Devo anche recuperare l'oggetto originale diverso da 'this.Context.Cars.Find (id)'? – RaYell
Il 'Find' restituirà un oggetto proxy dal database, ma se stai cercando e aggiornando un oggetto che è stato aggiunto localmente durante questa transazione, troverà l'oggetto che hai aggiunto. – qujck
Ho provato a seguire la tua soluzione ma questo mi ha portato a 'System.InvalidOperationException: membro 'CurrentValues' non può essere chiamato per l'entità di tipo 'Car' perché l'entità non esiste nel contesto. Per aggiungere un'entità al contesto chiama il metodo Add o Attach di DbSet. 'Ho aggiunto' this.Context.Set () .Attach (newEntry); 'subito dopo la prima riga e ora sto ottenendo' System.InvalidOperationException: la proprietà 'Id' è parte delle informazioni chiave dell'oggetto e non può essere modificata. –
RaYell