10
votes

Dépendance injecte de la connexion SQL?

Tout d'abord, je commence à utiliser StructureMap, mais un exemple dans n'importe quel di Framework fera.

J'ai une classe comme ça, P>

public void Do()
{
   var geoData = new GeoData();

   if(x)
   {
      geoData.ConnectionString = ConfigurationManager.ConnectionString["LIVEGeoDataConnection"]);
   }
   else
   {
      geoData.ConnectionString = ConfigurationManager.ConnectionString["STAGINGGeoDataConnection"]);
   }

   geoData.GetCountries();
}


0 commentaires

6 Réponses :


6
votes

simple, vous n'avez pas besoin d'un cadre. Avoir un constructeur surchargé pour votre Geodata classe. XXX

La chaîne est votre dépendance. Comme ce n'est pas un type complexe, vous avez eu votre injection de dépendance là-bas.

DI n'est pas une science de la fusée, même si certains aimerions que vous croyiez cela.


6 commentaires

Oui, c'est une autre solution, je me demandais simplement s'il y avait une meilleure façon.


Que est injection de dépendance. Juste sans utiliser de cadre élaboré.


@WIM - Vous avez raison de ne pas avoir à utiliser un cadre DI, mais la chaîne est pas votre dépendance; L'accès des données est. En passant dans une chaîne ne vous permet pas de trouver une logique commerciale de test d'unités dans Geodata sans une base de données. Une solution rapide peut être de passer en idbconnection (permet également de réutiliser des connexions). Une meilleure option pourrait être: martinfowler.com/aacatalog/repository.html


Oui, mais dans ce cas, la dépendance d'accès aux données constitue la chaîne de connexion. C'est ce que l'op voulait. Rien n'a été mentionné sur plusieurs dB support. Si vous souhaitez autoriser plusieurs plates-formes DB, oui, idbconnection peut l'interface correcte à injecter. Personnellement, pas si sûr de l'utilisation de l'idbconnection pour cela, car la responsabilité de fermer maintenant la connexion a été déplacée vers le conteneur. Ou l'a-t-il? C'est le but.


Je pense que c'était l'un de ces moments morts du cerveau pour moi, car il me reste assis sur le loo (où toutes les grandes révélations se produisent), je me suis souvenu que j'ai déjà eu mes propres classes d'accès à l'accès à l'interface, et tout ce que j'ai TODO a été transmettre dans une instance personnalisée de ma classe d'idbfactory.


Nice, c'est vraiment ce que tu voudriez. Et c'est votre propre di - Injectez-le dans la CTOR de votre classe Geodata. Vous avez raison sur le loo cependant. ;-)



0
votes

Martin Fowler dispose d'un article sur le sujet ici , qui explique les différentes approches . Sur une note personnelle, je préfère l'injection d'interface mais c'est une question de goût.


2 commentaires

Vous ne créeriez pas une interface IConnectionsRing avec une propriété à cordes cependant. Si la dépendance est un type complexe que l'injection d'interface dans la CTOR est quelque chose que je préfère aussi. Mais encore une fois, même pas nécessaire d'utiliser un cadre.


D'accord, mais je doute que la seule différence soit des connexions, c'est très probablement juste la pointe de l'iceberg. Si les connexions deviennent vraiment la seule propriété qui diffère alors une méthode de setter fera assez bien



0
votes

Ce que je ferais est de créer une nouvelle classe pour contenir la logique de sélection de chaîne de connexion, puis utilisez-la pour obtenir la chaîne de connexion pour une instance Geodata: xxx

Vous pouvez alors injecter cela Dans la classe contenant la méthode DO pour configurer les instances Geodata comme ceci: xxx


0 commentaires

1
votes

Je créerais une usine qui crée une instance de la classe Geodata , qui, à son tour, implémente une interface avec la méthode do (dites, Idocommand ).

La responsabilité de l'usine d'utiliser un contexte global pour déterminer quelle chaîne de connexion à injecter à l'instance geodata (constructeur est ma technique préférée) ou l'avoir dans son créer méthode comme argument.


4 commentaires

Il serait préférable que vous discutez de la même manière avec un exemple de code comme comment mettre en œuvre. Merci


@Mou je suis d'accord, mais je suis court à l'heure. On peut lire ma réponse en tant que lignes directrices / directions à une solution complète et en être heureux. D'autres peuvent lire ma réponse comme une introduction à un plus grand post. IMHO, je pense toujours que la fourniture d'une réponse de la ligne de directive est meilleure que de ne pas répondre du tout.


@Ronklein 5 ans et toujours court à l'heure? :))))


@ Volkangüven fou, n'est-ce pas? :RÉ



5
votes

La première question à vous poser est ce qui est Geodata? En d'autres termes, quelle est la responsabilité de la classe?

Il semble faire partie du La couche de domaine et peut contenir une logique commerciale. Il peut être utilisé par ( couplé à) Autres classes.

Si c'est le cas, quelles sont les dépendances? Une façon de déterminer cela consiste à tenter d'écrire Tests de l'unité qui testez Geodata isolément. Si le test nécessite une configuration significative, la classe sous test est serrée avec d'autres classes ou comporte de multiples responsabilités (bas Cohésion ).

Disons que nous changeons la classe de sorte que le constructeur prend un paramètre de chaîne de connexion. Comment pouvons-nous tester la méthode des getcountries publics? Eh bien, nous avons d'abord configuré une base de données avec des données de test connues ...

Cela prend beaucoup de temps et fragile (que si quelqu'un met à jour les données?), et le test fonctionnera relativement lentement (il doit se connecter à la base de données).

Eh bien, nous pourrions passer dans un objet implémentant une identification idbconnexion au constructeur (injection de constructeur). Notez que l'injection de dépendance implique normalement passer des interfaces ou des classes abstraites. Pour le tester, nous devrions créer une fausse idbconnection. Nous pourrions utiliser un Cadre d'isolement (moqueur) . Mais ensuite, nous aurions besoin de créer un faux IdbCommand lorsque CreateCommand s'appelait ...

Pour citer Jeremy Miller (auteur de ) "C'est trop d'effort pour trop peu de gain . " Voir son article meilleures et pires pratiques pour des objets simulés .

Une possibilité est d'utiliser le motif de référentiel . Vous passeriez dans une interface sur le référentiel spécifique au constructeur de Geodata. Ce serait facile de simuler (manuellement ou avec une bibliothèque moqueuse) pour tester. Le référentiel concret gérerait tous les accès des données. Il pourrait être combiné avec un Orm framework à une abstrait supplémentaire. La gestion des chaînes de connexion serait effectuée par l'ORM ou via le référentiel (de préférence dans une autre dépendance ou une classe de base).

Si cela semble complexe, c'est parce que c'est. Vous avez choisi l'un des cas les plus difficiles d'injection de dépendance (qui, malheureusement, est également l'un des plus courants).

L'injection de dépendance en soi est un concept assez simple. Si votre classe appelle un service Web, vous pouvez placer le code de service Web dans une classe distincte qui ne fait rien d'autre, implémenter une interface et transmettez cette interface à votre classe d'origine. Les cadres de conteneurs di / ioc peuvent rendre cela plus facile à faire si vous avez beaucoup de cours et / ou de dépendances, mais ils ne sont pas nécessaires.

edit: juste pour être clair, l'injection de dépendance est pas la partie complexe. Séparer l'accès aux données est.


0 commentaires

12
votes

Techniquement, Wim Hollebrandee a déjà répondu à votre question, mais je voulais juste souligner que je le ferais personnellement un autre moyen parce que je n'aime pas avoir à transmettre la chaîne de connexion à chaque fois que j'instécie la classe. Je me rends compte que vous avez un constructeur par défaut, mais je pense que nous pourrions rendre cela un peu plus propre, toujours.

Premièrement, je créerais une classe statique pour obtenir votre connexion, comme suit: P>

public class GeoData
{
   public List GetCountries()
   {
      using (IDbConnection con = ConnectionFactory.GetConnection())
      {
        //Sql stuff to return countries from a database
      }
   }
}


3 commentaires

Commentaire nécrophéliquet de la journée - Comment fermez-vous et éliminez-vous la connexion?


@Oskaraustegardais, je voudrais juste la mettre dans une déclaration en utilisant. IDBConnection implémente Idisposable, de sorte que ce soit le moyen le plus simple.


Suggère de mettre à jour l'exemple pour indiquer que