Mam projekt przy użyciu Entity Framework Code First version 6 z Lazy loading. Na poziomie modelu ma Kurs, który ma Moduły. Klasa Oczywiście jest zadeklarowana następująco:Kod struktury Entity First Child Navigation Property null
public class Course : BaseEntity
{
public String Title { get; set; }
public String Description { get; set; }
public int Revision { get; set; }
//private IList<Module> _modules;
//public virtual IList<Module> Modules
//{
// get { return _modules ?? (_modules = new List<Module>()); }
// set { _modules = value; }
//}
public virtual ICollection<Module> Modules { get; set; }
}
Moja klasa Module jest zadeklarowana następująco:
public class Module : BaseEntity
{
[ForeignKey("Course")]
public Int64 CourseID { get; set; }
public virtual Course Course { get; set; }
public String Title { get; set; }
public Int32 SequenceNo { get; set; }
public override string HumanDisplay
{
get { return Title; }
}
private IList<ModuleItem> _items;
public virtual IList<ModuleItem> Items
{
get { return _items ?? (_items = new List<ModuleItem>()); }
set { _items = value; }
}
}
klasa BaseEntity oboje dziedziczą tylko do zmniejszenia powielania kodu wspólnych właściwości aplikacyjnych. Deklaruje klucz podstawowy dla wszystkich podmiotów, takich jak:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Int64 Id { get; set; }
mogę zawierać więcej szczegółów na temat tego, czy istotne, ale nie mogę zobaczyć, jak oni ingerować i tam jest kilka off topic ramowej rzeczy tam.
Po załadowaniu widoku w celu edycji kursu, który już istnieje w bazie danych, właściwość Moduły kursu jest zawsze pusta, jeśli jest używana w widoku MVC , nawet jeśli powinny być zapisy. Na przykład kurs edycji z identyfikatorem 3 ma zerową właściwość Moduły, pomimo faktu, że istnieje kilka modułów o ID kursu równym 3.
Nawrotna nawigacja związku DOES jakkolwiek działa. Jeśli przejdę do widoku, aby edytować identyfikator modułu 5, właściwość kursu jest ustawiana zgodnie z oczekiwaniami i mogę uzyskać dostęp do wartości kursu. Ten moduł jest powiązany z ID kursu 3.
Mój kod źródłowy podmiotu Najpierw jest używana konfiguracja domyślna, np. Włączone jest ładowanie Lazy. Zweryfikowałem to, sprawdzając wartości debuggera w DBContext, ale także to wyjaśnia, dlaczego właściwość Course działa automatycznie z modułu do kursu.
Jakie są możliwe przyczyny relacji między modułem a kursem, ale nie z kolekcji Course to the Modules?
Jak widać na podstawie skomentowanego kodu w klasie Course, miałem do czynienia z wcześniejszą sytuacją zerową, upewniając się, że właściwość Modules nigdy nie była zerowa, ale ma to znaczenie tylko wtedy, gdy nie ma modułów dla kursu, który nie jest Przypadek tutaj, więc próbowałem zmienić to z powrotem do podstawowej właściwości ICollection, aby wykluczyć to jako problem.
Mam również debugowane, gdy DBContext jest usuwany i jest zdecydowanie po uruchomieniu kodu widoku, więc nie ma niebezpieczeństwa, że DBContext zostanie usunięty przed uzyskaniem dostępu do Collection.
Nie jestem zainteresowany jawnym użyciem instrukcji Uwzględnij. Chcę użyć leniwego ładowania i EF, aby automatycznie uzyskać dane i jestem świadomy ich wpływu na wydajność itp.
Idealnie nie chcę opisywać związku z Entity Framework poza używaniem właściwości powyżej. Jeśli muszę, to mogę, ale proszę wyjaśnij dlaczego, ponieważ jestem pewien, że udało mi się zrobić to proste rodzic - Dziecko, 1 - wiele relacji wcześniej bez problemu.
UPDATE 1
kod działanie kontrolera jest następująca
public virtual ActionResult Edit(long id = 0)
{
if (Session.GetUser().GetCombinedPrivilegeForEntity(Entity).CanRead)
{
String saveSuccess = TempData["successMessage"] as String;
currentModel = GetID(id);
if (currentModel == null)
throw new RecordNotFoundException(id, typeof(Model).Name);
currentVM = Activator.CreateInstance<ViewModel>();
currentVM.Model = currentModel;
currentVM.DB = DB;
currentVM.ViewMode = ViewMode.Edit;
currentVM.SuccessMessage = saveSuccess;
SetViewModelPermissions();
//Cache.AddEntry(Session.SessionID, Entity, currentVM.Model.Id, currentVM);
if (currentModel == null)
{
return HttpNotFound();
}
if (ForcePartial || Request.IsAjaxRequest())
return PartialView(GetViewName("Edit"), currentVM);
else
return View(GetViewName("Edit"), MasterName, currentVM);
}
else
{
throw new PermissionException("read", Entity);
}
}
Gdybym debugowania po następnej linii i inspekcję nieruchomości pobiera automically zaludnionych, jak oczekiwano.
currentModel = GetID(id);
Jak komentuje @Zaphod wygląda na to, że połączenie DB jest zamknięte przed rozpoczęciem renderowania widoku. Nie rozumiem, dlaczego tak się dzieje, ponieważ nadal jesteśmy po stronie serwera i jeszcze nie zwróciliśmy znaczników do przeglądarki. Czy istnieje sposób na umożliwienie leniwego ładowania w widokach i zamykanie połączenia tylko wtedy, gdy kontroler jest usuwany?
Aktualizacja 2
Rzeczywisty kod WezID:
protected virtual Model GetID(long id = 0)
{
return DbSet.Find(id);
}
DbSet jest odpowiednio ustawiona w konstruktora sterownika, aby wskazać DbSet na DbContext:
public CourseController()
: base()
{
this.DbSet = DB.Courses;
}
Nie widzę, jak DbSet mógłby w jakiś sposób złamać zapytania między ostatnim wierszem akcji kontrolera wywołującym widok a th e widok zaczyna biec.
Update 3
powinno mam włączone szczegóły gdzie DbContext jest tworzony, który znajduje się w odziedziczonej konstruktora kontrolera:
public ApplicationCRUDController()
: base()
{
this.DB = eLearn.Models.DbContext.CreateContext(Session);
}
ta jest umieszczona tylko raz w sposobie dysponowania dziedziczone sterownika który nie jest wywoływana, dopóki widok nie zostanie wyświetlony:
protected override void Dispose(bool disposing)
{
if (DB != null)
DB.Dispose();
base.Dispose(disposing);
}
Wciąż d nie rozumiem, dlaczego scenariusz odwrotnej relacji działałby dobrze, ponieważ powinien być leniwy ładowanie w widoku dla niego, ponieważ wszystkie one używają tego samego schematu.
Musisz pokazać kod, w jaki sposób ładujesz kurs. Korzystając z klas, które tu przygotowałeś, leniwy ładunek działa dla mnie w obu kierunkach. Proponuję napisać mały program testowy, aby pokazać, co nie działa. – Richard
Te zajęcia zdecydowanie wyglądają tak, jakby były dla mnie w porządku. Twój problem jest gdzie indziej. – Pharylon
Najprawdopodobniej właściwość nav nie została wypełniona przed zamknięciem połączenia (tj. Wysłaniem danych do widoku). Jak sugerował @Richard, opublikuj kod, w którym pobierzesz encję i przekaż ją do widoku (lub viewmodel) – Zaphod