Ho un progetto MVC ASP.Net dove aggiungo in una vista un'entità studentesca al mio repository Entity Framework 6.
class Student
public long Id { get; set; }
public virtual Book Favorite { get; set; }
class Book
public long Id { get; set; }
public string Title { get; set; }
La proprietà Favorite
è impostata da un menu a discesa nella vista. Nel controller in post, viene impostato solo l' Id
per il libro. Per dire a Entity Framework, per aggiungere solo lo studente, ma non per aggiungere il libro di riferimento, imposto l'EntityState per il libro a Unchanged come descritto qui
Dopo aver salvato le mie modifiche, ho il record degli studenti corretto nel database e anche il record del libro rimane invariato, ma ogni volta che interrogo il libro dal mio repository (non tramite lo studente), ottengo un'entità del libro di nuovo dove solo l'Id è set e Title e tutte le altre proprietà sono nulle.
Il mio controller (semplificato):
public ActionResult Create()
{
StudentViewModel result = new StudentViewModel();
result.BookList = new SelectList(DbContext.Books, "Id", "Name");
return View(result);
}
[HttpPost]
public ActionResult Create(StudentViewModel viewModel)
{
DbContext.Entry(viewModel.NewStudent.Favorite).State = EntityState.UnChanged);
DbContext.Add(viewModel.NewStudent);
DbContext.SaveChanges();
Book missingProperties =
DbContext.Books.Single(book => book.Id == viewModel.NewStudent.Favorite.Id);
}
My View (semplificato):
@using System.Linq
@model StudentViewModel
@using (Html.BeginForm())
{
...
@Html.TextBoxFor(model => model.NewStudent.Name)
@Html.DropDownListFor(model => model.NewStudent.Favorite.Id, Model.BookList)
...
}
Il problema è che Entity Framwork DbContext memorizza le entità nella cache.
Con il caricamento lento, è sufficiente fare qualche riferimento ai dati relativi e Entity Framework controllerà se è stato caricato in memoria. In caso contrario, Entity Framework creerà ed eseguirà una query dietro le quinte, popolando i relativi dati.
Per impostazione predefinita, Visual Studio definirà i nuovi modelli creati per impostare LazyLoadingEnabled su true.
(da MSDN )
Una volta caricato da db, non verrà più caricato per la durata DbContext. EntityState.UnChanged
impedisce a Entity Framework di salvare l'entità nel database. Ma ogni volta che l'entità viene richiamata dal contesto una seconda volta, non viene preso il valore corretto dal database, ma il modificato, che ora si trova anche nella cache.
È inoltre necessario aggiornare l'entità modificata. Allegarlo in DbContext e quindi ricaricarlo.
Book result = Attach(book);
Entry(book).Reload();
Penso che questo risponda al problema, ma non sono sicuro che la risposta di GuruStron usi lo schema migliore.
Dovresti eseguire una ricerca per Favorite
il db, prima di salvare il nuovo studente (e controllare se ce n'è uno, perché non dovresti avere qualcosa che proviene dal client =), questo porterebbe il libro al contesto, quindi devi semplicemente impostarlo sullo studente :
Book book = DbContext.Books.Single(book => book.Id == viewModel.NewStudent.Favorite.Id);
if(book!=null)
{
viewModel.NewStudent.Favorite = book;
}
else
{
throw new Exception();
}
DbContext.Add(viewModel.NewStudent);
DbContext.SaveChanges();