2010-10-08 5 views
2

J'ai une série d'environ 30 tables de recherche dans mon schéma de base de données, toutes avec la même mise en page (et je préférerais les garder en tant que tables séparées plutôt qu'une seule table de recherche), et donc Le contexte Linq2SQL a 30 entités pour ces tables de recherche.Générer une classe pour gérer plusieurs types

J'ai une classe standard que j'utiliser pour les opérations CRUD sur chacun de ces 30 ENTITES, par exemple:

public class ExampleAttributes : IAttributeList 
{ 
    #region IAttributeList Members 

    public bool AddItem(string Item, int SortOrder) 
    { 
     MyDataContext context = ContextHelper.GetContext(); 
     ExampleAttribute a = new ExampleAttribute(); 
     a.Name = Item; 
     a.SortOrder = SortOrder; 
     context.ExampleAttributes.InsertOnSubmit(a); 

     try 
     { 
      context.SubmitChanges(); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    public bool DeleteItem(int Id) 
    { 
     MyDataContext context = ContextHelper.GetContext(); 

     ExampleAttribute a = (from m in context.ExampleAttributes 
          where m.Id == Id 
          select m).FirstOrDefault(); 

     if (a == null) 
      return true; 

     // Make sure nothing is using it 
     int Count = (from m in context.Businesses 
          where m.ExampleAttributeId == a.Id 
          select m).Count(); 

     if (Count > 0) 
      return false; 

     // Delete the item 
     context.ExampleAttributes.DeleteOnSubmit(a); 

     try 
     { 
      context.SubmitChanges(); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    public bool UpdateItem(int Id, string Item, int SortOrder) 
    { 
     MyDataContext context = ContextHelper.GetContext(); 

     ExampleAttribute a = (from m in context.ExampleAttributes 
          where m.Id == Id 
          select m).FirstOrDefault(); 

     a.Name = Item; 
     a.SortOrder = SortOrder; 

     try 
     { 
      context.SubmitChanges(); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    public String GetItem(int Id) 
    { 
     MyDataContext context = ContextHelper.GetContext(); 
     var Attribute = (from a in context.ExampleAttributes 
         where a.Id == Id 
         select a).FirstOrDefault(); 

     return Attribute.Name; 
    } 

    public Dictionary<int, string> GetItems() 
    { 
     Dictionary<int, string> Attributes = new Dictionary<int, string>(); 

     MyDataContext context = ContextHelper.GetContext(); 
     context.ObjectTrackingEnabled = false; 

     Attributes = (from o in context.ExampleAttributes orderby o.Name select new { o.Id, o.Name }).AsEnumerable().ToDictionary(k => k.Id, v => v.Name); 

     return Attributes; 
    } 

    #endregion 
} 

je pourrais reproduire cette classe 30 fois avec des changements mineurs pour chaque entité de recherche, mais cela semble en quelque sorte désordonné - donc cette classe peut-elle être générialisée pour que je puisse aussi passer le type que je veux, et le faire gérer en interne les différences de type dans les requêtes linq? De cette façon, j'ai une classe à faire des ajouts, une classe à corriger les bugs et al - semble la façon dont il devrait être fait.

MISE À JOUR:

Andrews réponse ci-dessous m'a donné l'option que je cherchais vraiment à en pensant à la question (en passant du type dans) mais j'ai besoin plus de précisions sur la façon de genericise les requêtes LINQ. Quelqu'un peut-il clarifier cela?

Vive

Moo

Répondre

1

Il y a deux choses que vous pouvez essayer. La première consiste à définir une interface qui contient tous les champs pertinents partagés par les trente classes d'entités. Ensuite, vous seriez en mesure d'avoir chaque classe d'entité mettre en œuvre cette interface (Appelons-le IMyEntity) en faisant quelque chose comme

public partial class EntityNumber1 : IMyEntity 
{ 
} 

pour chaque entité (où EntityNumber1 est le nom d'une des classes d'entités). Certes, il s'agit toujours de trente définitions différentes, mais votre classe d'opération CRUD pourrait alors fonctionner sur IMyEntity au lieu de devoir écrire une nouvelle classe à chaque fois.

Une deuxième façon de le faire est simplement genericize la classe opération CRUD, comme vous le suggérez:

public class ExampleAttributes<T> : IAttributeList 
{ 
    ... 

qui vous permet d'utiliser T comme le type sur lequel fonctionner. Certes, cela peut être plus facile en combinaison avec la première méthode, car vous devez toujours vérifier la présence des attributs et convertir l'entité en type ou interface approprié.

Edit:

Pour vérifier la présence des propriétés appropriées sur l'entité, vous pourriez avoir besoin d'utiliser des méthodes de réflexion. Une façon de vérifier si le type donné T a une propriété particulière pourrait être de vérifier

typeof(T).GetProperties().OfType<PropertyInfo>().Count<PropertyInfo>(pi => pi.Name == "MyPropertyName" && pi.GetGetMethod().ReturnType == typeof(TypeIWant)) > 0 

Bien sûr, remplacez TypeIWant avec le type que vous attendez la propriété d'être, et remplacer MyPropertyName avec le nom de la propriété pour lequel vous vérifiez.

+0

Merci pour la réponse, pouvez-vous approfondir la deuxième option? – Moo

+0

@Moo Voir la modification ci-dessus. – Andrew

+0

Salut Andrew, merci pour le détail supplémentaire, malheureusement, c'est la générique du linq basé sur le type donné que j'ai vraiment besoin de clarification - je mettrai à jour la question à cet effet mais merci pour vos efforts. – Moo

0

Ajoutez un paramètre aux constructeurs qui spécifie le type. Ensuite, vous pouvez travailler en interne. Une classe, avec peut-être une instruction switch dans le constructeur.

0

Pour généraliser une requête LINQ, le plus gros problème est que votre DataContext a les collections en fonction du type. Il y a plusieurs façons de contourner cela. Vous pourriez essayer d'y accéder en utilisant la réflexion, mais cela nécessitera pas mal de piratage et détruirait à peu près toute l'efficacité que LINQ to SQL fournirait.

Le moyen le plus simple semble être d'utiliser Dynamic LINQ. Je ne l'ai pas utilisé personnellement, mais il semble que cela devrait l'appuyer. Vous pouvez trouver plus d'informations dans ce fil: Generic LINQ query predicate? et http://aspalliance.com/1569_Dynamic_LINQ_Part_1_Using_the_LINQ_Dynamic_Query_Library.1 Peut-être quelqu'un d'autre peut fournir plus d'informations à ce sujet?

0

Ceci n'est pas nécessairement une réponse à la question, mais peut être une solution à votre problème. Avez-vous envisagé de générer toutes les classes dont vous avez besoin? T4 est intégré dans Visual Studio et peut générer du code pour vous. Le lien ci-dessous décrit assez largement, mais contient des tas de liens pour plus d'informations.

http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

De cette façon, vous pouvez définir toutes les méthodes en un seul endroit, et générer les fichiers de classe pour vos 30 impairs modèles de recherche. Un endroit pour apporter des modifications, etc.

Peut-être utile d'envisager, et si non, encore la peine d'être connu.

Questions connexes