2010-05-20 21 views
2

J'ai une classe membre qui a renvoyé IQueryable d'un contexte de donnéesComment se départir contexte de données après utilisation

public static IQueryable<TB_Country> GetCountriesQ() 
    { 
     IQueryable<TB_Country> country; 

     Bn_Master_DataDataContext db = new Bn_Master_DataDataContext(); 

     country = db.TB_Countries 
      .OrderBy(o => o.CountryName); 

     return country; 
    } 

Comme vous pouvez le voir, je ne supprime pas le contexte de données après utilisation. Parce que si je le supprime, le code qui appelle cette méthode ne peut pas utiliser le IQueryable (peut-être en raison de l'exécution différée?). Comment forcer l'exécution immédiate à cette méthode? Je peux donc disposer le contexte de données ..

Merci: D

+0

N'oubliez pas d'indiquer votre réponse favorite. – Steven

Répondre

3

L'exemple donné par Codeka est correct, et je Je conseillerais d'écrire votre code avec ceci quand la méthode est appelée par la couche de présentation. Cependant, disposer de classes DataContext est un peu difficile, donc j'aime ajouter quelque chose à ce sujet. Les objets de domaine générés par LINQ to SQL (dans votre cas, la classe TB_Countries) contiennent souvent une référence à la classe DataContext.Cette référence interne est nécessaire pour le chargement paresseux. Lorsque vous accédez par exemple à la liste des objets référencés (disons par exemple: TB_Country.States) LINQ to SQL interrogera la base de données pour vous. Cela se produira également avec des colonnes chargées paresseuses. Lorsque vous disposez du DataContext, vous évitez qu'il soit à nouveau utilisé. Par conséquent, lorsque vous renvoyez un ensemble d'objets comme vous l'avez fait dans votre exemple, il est impossible d'appeler la propriété States sur une instance TB_Country, car elle va lancer un ObjectDisposedException. Cela ne veut pas dire que vous ne devez pas jeter le DataContext, parce que je crois que vous devriez le faire. Comment résoudre ce problème dépend un peu de l'architecture que vous choisissez, mais vous avez essentiellement deux options:

Option 1. Fournissez un DataContext à la méthode GetCountriesQ. Normalement, vous voulez le faire lorsque votre méthode est une méthode interne de votre couche de gestion et qu'elle fait partie d'une transaction plus importante (entreprise). Lorsque vous fournissez un DataContext de l'extérieur, il est créé en dehors de la portée de la méthode et il ne doit pas le jeter. Vous pouvez le disposer à un niveau supérieur. Dans cette situation, votre méthode ressemble fondamentalement ceci:

public static IQueryable<TB_Country> GetCountriesQ(
    Bn_Master_DataDataContext db) 
{ 
    return db.TB_Countries.OrderBy(o => o.CountryName); 
} 

Option 2. Ne pas renvoyer aucun objet de domaine de la méthode GetCountriesQ. Cette solution est utile lorsque la méthode est publique dans votre couche de gestion et sera appelée par la couche de présentation. Vous pouvez envelopper les données dans un objet spécialement conçu (un DTO) qui contient uniquement des données et aucune référence cachée au DataContext. De cette façon, vous avez un contrôle total sur la communication avec la base de données et vous pouvez disposer du DataContext comme vous le devriez. J'ai écrit plus à propos de son sur SO here. Dans cette situation, votre méthode ressemble fondamentalement ceci:

public static CountryDTO[] GetCountriesQ() 
{ 
    using (var db = new Bn_Master_DataDataContext()) 
    { 
     var countries; 
      from country in db.TB_Countries 
      orderby country.CountryName 
      select new CountryDTO() 
      { 
       Name = country.CountryName, 
       States = (
        from state in country.States 
        order by state.Name 
        select state.Name).ToList(); 
      }; 

     return countries.ToArray(); 
    } 
} 

public class CountryDTO 
{ 
    public string Name { get; set; } 
    public List<StateDTO> States { get; set; } 
} 

Comme vous le lirez here il y a des choses intelligentes que vous pouvez faire qui rendent l'utilisation DTO moins douloureux.

J'espère que cela aide.

3

Vous pouvez convertir le interrogeable à une liste, comme suit:

public static List<TB_Country> GetCountriesQ() 
{ 
    using(var db = new Bn_Master_DataDataContext()) 
    { 
     return db.TB_Countries 
      .OrderBy(o => o.CountryName).ToList(); 
    } 
} 
+0

+1 A propos d'Erwin, l'instruction using va prendre soin de disposer le contexte de données (la classe implémente IDisposable) Il libère toutes les ressources utilisées par System.Data.Linq.DataContext. – CRice

+0

Oui, je suppose que .net a une bonne collection de garbage –