2010-12-15 17 views
1

Je suis nouveau à Entity Framework. J'ai créé une application multi-niveaux, en MVC, en utilisant Ninject.
J'ai trois tables dans la base de données. Dites le tableau A, B et Tableau C. TableauEntité Entité-Cadre ne montrant pas les propriétés des entités apparentées

Table A has a foreign key relating it to Table B 
Table B has a foreign key relating it to Table C 

Table A => Table B => Table C 

Mon application a un "service" qui sera appelé à partir d'un contrôleur MVC.
Le service agit comme un référentiel pour chaque entité (ie TableAService, TableBService), responsable de la création, lecture, mise à jour ou suppression d'entités du EF DataContext, ainsi que de la logique métier sur ces entités.

Dans mon contrôleur MVC, j'ai une référence au service approprié. Par exemple:

private TableAService _tableAService; 

public TableAController(EFDataContext dataContext) 
{ 
    _tableAService = new TableAService(dataContext); 
} 

public ActionResult Index() 
{ 
    return View(); 
} 

TableAService ressemblerait à quelque chose comme ceci:

private EFDataContext _dataContext; 

public TableAService(EFDataContext dataContext) 
{ 
    _dataContext = dataContext; 
} 

public TableA GetById(int tableAId) 
{ 
    _dataContext.TableA.SingleOrDefault(ta => ta.TableAId == tableAId); 
} 

Je comprends que serait étroitement couplé à la source de données, ma mise en œuvre effective diffère légèrement du service de l'exemple, mais le concept est le même, J'ai un service avec un dataContext auquel j'aimerais retourner des entités.

QUESTION: - Lorsque je suis dans la méthode GetById dans TableAService, SingleOrDefault me ​​donne une propriété de navigation TableB, ce qui me permet d'accéder à toutes les propriétés de TableB, y compris une propriété de navigation TableC. Cependant, lorsque je redonne la TableA au Contrôleur, je ne peux accéder à aucune des propriétés de TableB.

Au sein du service que j'ai aussi essayé:

private ObjectSet<TableA> _objSet = _dataContext.CreateObjectSet<TableA>(); 

et

return _objSet.SingleOrDefault(ta => ta.TableAId == tableAId); 

Cela ne semble pas faire de différence de pouvoir accéder à la propriété de navigation TableC sur TableB de la Entité TableA.

Toute aide serait grandement appréciée!

Cheers,

James

Répondre

0

Il a fallu creuser, mais le problème que je rencontrais était que mon application ne faisait pas référence à System.Data.Entity. L'ajout de la référence à l'application m'a permis d'accéder aux propriétés des objets liés à partir du contrôleur.

Merci pour vos réponses les gars, ils m'ont aidé à écarter les possibilités. J'ai voté chacun.

2

Essayez de changer votre méthode GetById à:

public TableA GetById(int tableAId) 
{ 
    return _dataContext.TableA.Include("TableB").SingleOrDefault(ta => ta.TableAId == tableAId); 
} 

Si vous voulez obtenir le dossier TableC ainsi, utilisez:

public TableA GetById(int tableAId) 
{ 
    return _dataContext.TableA.Include("TableB.TableC").SingleOrDefault(ta => ta.TableAId == tableAId); 
} 

Le raison est que Entity Framework utilise "chargement paresseux", ce qui signifie que n'est pas chargé à partir de la base de données tant que vous n'en avez pas vraiment besoin. Le problème est, une fois que vous êtes hors service, le contexte de données n'existe plus pour obtenir l'enregistrement de la table B. La méthode Include indique à EF de charger immédiatement les données des tables associées.

3

Le contenu d'une propriété de navigation ne peut être chargé que dans le cadre d'un ObjectContext actif.

Ceci est requis car les lignes réelles seront récupérées via un aller-retour vers la base de données.
Dans votre cas, vous essayez d'accéder à une propriété de navigation après le ObjectContext qui a été utilisé pour récupérer les entités en premier lieu a été éliminé et la connexion a été perdue.

En supposant que vous utilisez Entity Framework 4 il y a 2 solutions à ce problème:

  • chargement Désireuse: les entités liées sont chargées à l'avant, que vous est instruisez explicitement Entity Framework pour charger toutes les entités liées tandis que il récupère les résultats de la requête. Cela peut se faire de différentes manières: en incluant les entités associées dans la projection de la requête, en appelant la méthode ObjectQuery.Include ou en appelant la méthode Load sur la propriété de navigation, ou en utilisant la méthode ObjectContext.LoadProperty.
  • Chargement paresseux: les entités associées sont chargées à la demande, c'est-à-dire lorsque le getter de la propriété de navigation est accédé pour la première fois. Notez que cela doit toujours être fait dans le cadre d'un ObjectContext.

Dans votre cas, le chargement désireux selon la méthode Include est probablement la solution la plus appropriée:

public TableA GetById(int tableAId) 
{ 
    return _dataContext.TableA 
     .Include("TableB.TableC") // use dot-notation to specify depth in the object graph 
     .SingleOrDefault(ta => ta.TableAId == tableAId); 
} 

Ressources connexes: