3

Mon scénario:ASP.Net Entity Framework et LINQ référentiel

Ceci est une application Web ASP.NET 4.0 programmé via C#

I mettre en place un modèle référentiel. Mes référentiels partagent tous le même ObjectContext, qui est stocké dans httpContext.Items. Chaque référentiel crée une nouvelle ObjectSet de type E. Heres un code de mon dépôt:

public class Repository<E> : IRepository<E>, IDisposable 
    where E : class 
{ 
    private DataModelContainer _context = ContextHelper<DataModelContainer>.GetCurrentContext(); 
    private IObjectSet<E> _objectSet; 
    private IObjectSet<E> objectSet 
    { 
     get 
     { 
      if (_objectSet == null) 
      { 
       _objectSet = this._context.CreateObjectSet<E>(); 
      } 
      return _objectSet; 
     } 
    } 

    public IQueryable<E> GetQuery() 
    { 
     return objectSet; 
    } 

Disons que j'ai 2 repositorys, 1 pour les Etats et 1 pour les payements et que vous souhaitez créer une requête LINQ contre les deux. Notez que j'utilise les classes POCO avec le framework d'entité. État et pays sont 2 de ces classes POCO.

Repository stateRepo = new Repository<State>(); 
Repository countryRepo = new Repository<Country>(); 

IEnumerable<State> states = (from s in _stateRepo.GetQuery() 
          join c in _countryRepo.GetQuery() on s.countryID equals c.countryID 
          select s).ToList(); 
Debug.WriteLine(states.First().Country.country) 

essentiellement, je souhaite récupérer l'état et l'entité de pays associée. La requête ne renvoie que les données d'état ... et je reçois une exception d'argument null sur le Debug.WriteLine

LazyLoading est désactivé dans mon .edmx ... c'est comme je le veux.

Répondre

2

Vous faites une jointure sans rien récupérer. Il y a plusieurs solutions à votre problème:

  • Utilisez Include pour charger les entités dépendantes: from s in ((ObjectSet<State>) _stateRepo.GetQuery).Include("Country"). Le problème avec cette approche est que vous devez exposer le ObjectSet directement plutôt que comme IQueryable si vous voulez éviter la diffusion.
  • Utilisez context.LoadProperty(states.First(), s => s.Country) pour charger explicitement le pays de la base de données pour un état donné.
  • Sélectionnez les deux entités dans la requête: from s in ... join c ... select new { s, c }. Vous ne serez pas en mesure d'accéder directement à la propriété Country de l'état, mais vous l'avez dans le type anonyme.
  • Activer le chargement paresseux.
+0

Je fais quelque chose de similaire à http://stackoverflow.com/questions/542595/entity-framework-singletonish-objectcontext-good-bad-or-overthinking pour mon ObjectContext. –

+0

Selon http://www.4guysfromrolla.com/articles/060904-1.aspx, HttpContext.Items fonctionne sur une base par requête. Par conséquent, des demandes différentes ne doivent pas provoquer de conditions de concurrence avec le contexte de l'objet. –

+0

Vous avez raison pour HttpContext.Items. Retiré cette partie de ma réponse, merci. –

1

L'implémentation de votre référentiel est très similaire à la mienne, en particulier la façon dont vous stockez ObjectContext. Cela fonctionne bien pour moi, donc je ne pense pas que ce soit un problème conceptuel. Essayez d'utiliser un objet statique (pas de wrapper) juste pour voir si cela résout le problème. Il y a peut-être un bug dans votre ContextHelper qui fait que votre contexte est éliminé et recréé.

+0

I Debug.WriteLine chaque fois qu'un nouveau ObjectContext est créé et que son fonctionnement est positif. Le chargement paresseux est-il activé dans votre projet? –

+0

@Chris Klepeis: Oui, c'est le cas. –

+0

Nous l'avons désactivé parce que notre application est n couche et ne veut pas que les autres couches puissent exécuter des requêtes de cette façon. –