none
Factory Dinamique RRS feed

  • Question

  • Bonjour,

    J'ai développer un fonction qui me permet de créé une factory suivant le type de base de donnée,

    si Access,Sql Server, je prend la factory de base

    si MySql je prend la factory MySql.

    Je souhaiterai pour MySql faire une chargement a la volée,

    la class sera integrer dans de nombreux projet, et tout les projet non pas le l'assemblie MySql.Data ajouté au projet,

    si l'assemblie n'est pas ajouté le code pose une erreur, et impossible de compilé, je souhaiterai que le code ce compile et que l'exception soit lever a l'execution.

    Une methode a peu pres identique est pour Excel de ne pas integrer la reference excel, mais de fair un CreateObject("Excel.Application"), l'exception est lever a l'execution de ligne si excel n'es pas installer. je cherche la meme chose pour l'assemblie MySql.

    la ligne

    Factory = MySql.Data.MySqlClient.MySqlClientFactory.Instance

    deviendrai un truc dans ce style

    Factory = Createobject("MySql.Data.MySqlClient.MySqlClientFactory.Instance")

    mais je ne trouve pas la syntaxe,

    Merci,

    Voici la fonction :

      Public Sub Connexion(ByVal pConnexionString As String, ByVal pDBType As EnumTypeBaseDonne)

            DataBaseType = pDBType

            Dim lProviderName As String = GetProviderName(pDBType)

            Select Case lProviderName.ToLower

                Case ProviderNameMySql.ToLower

                    Factory = MySql.Data.MySqlClient.MySqlClientFactory.Instance
                    Provider = Enum_TypeProviderConnexion.MySql

                Case Else

                    Factory = Common.DbProviderFactories.GetFactory(lProviderName)
                    Provider = Enum_TypeProviderConnexion.Oledb

            End Select

            DataBase = Factory.CreateConnection
            DataBase.ConnectionString = pConnexionString
            DataBase.Open()

        End Sub

    mardi 30 mars 2010 12:50

Réponses

  • Bonjour,

    Voici le code à utiliser :

    Assembly a;
    Type t;
    FieldInfo f;
    DbProviderFactory factory;
    
    // Charger l'assembly
    a = Assembly.LoadFrom("< Emplacement de l'assembly >");
    
    // Récupérer le type MySqlClientFactory
    t = a.GetType("MySql.Data.MySqlClient.MySqlClientFactory");
    
    // Prendre le champ statique "Instance"
    f = t.GetField("Instance");
    
    // Récupérer le factory du champ statique
    factory = (DbProviderFactory)f.GetValue(null);
    

    Cordialement


    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    • Marqué comme réponse 3magroup jeudi 1 avril 2010 12:06
    mercredi 31 mars 2010 22:36
    Modérateur
  • Bonjour,

    Je voulais vous remercie, j'ai trouver la solution votre proposition ma mis sur la bonne voie,

    voici la fonction terminer elle en fait meme plus que ce que je pensais, maintenant elle permet de charger celui qui est referencer dans le projet, si elle ne le trouve pas alors je charge celui qui ce trouve sur le disque dur. cela permet a ma class de connexion de developper sur une base de donnée, et si un jour on veux migrer, il suffit de rajouter dans le repertoir le MySql.Data.dll, pour que l'application puisse ce connecter au serveur MySql.

    Merci encors,

    Sebastien

     


        ''' <summary>
        ''' Retourne une factory MySql
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetFactoryMySqlData() As Common.DbProviderFactory

            Dim lAssemblieMySqlData As System.Reflection.Assembly
            Dim lType As Type
            Dim lFiledInfo As System.Reflection.FieldInfo

            Try


                'on charge l'assemblie courent
                Dim lAssemblie As System.Reflection.Assembly = System.Reflection.Assembly.GetCallingAssembly

                Dim lIsMySql As Boolean = False

                'on boucle sur la liste des assemblies inclue dans cette assemblie
                For Each lAss As System.Reflection.AssemblyName In lAssemblie.GetReferencedAssemblies

                    'si on trouve l'assemblie en memoire, on le charge
                    If lAss.Name.ToLower = "MySql.Data".ToLower Then
                        lAssemblieMySqlData = Reflection.Assembly.Load(lAss)
                        lIsMySql = True
                    End If

                Next

                'Si l'assemblie ne peu etre charger du projet on prend celui qui ce trouve sur le repertoir
                If lIsMySql = False Then

                    lAssemblieMySqlData = System.Reflection.Assembly.Load("MySql.Data")

                End If

                lType = lAssemblieMySqlData.GetType("MySql.Data.MySqlClient.MySqlClientFactory")
                lFiledInfo = lType.GetField("Instance")

            Catch ex As Exception
                Throw New Exception("<fx>ClassDataBaseConnector.GetFactoryMySqlData</fx><msg>" & ex.Message & "</msg>", ex)
            End Try

            Return CType(lFiledInfo.GetValue(Nothing), Common.DbProviderFactory)

        End Function

    • Marqué comme réponse 3magroup jeudi 1 avril 2010 12:06
    jeudi 1 avril 2010 10:02

Toutes les réponses

  • Bonjour,

    dans ADO.Net il existe des interfaces IDbConnection, IDbCommand qui pourraient être utilisées dans ce but.

    Tu trouveras un exemple de factory avec ADO.Net dans cet article sur DotNetGuru

    Cordialement

    mardi 30 mars 2010 13:55
  • Bonjour,

     

    je les utilise deja dans le reste de mon projet, mais la creation de factory n'es pas compatible MySql, il faut utiliser celui de mySql

    ensuite une fois instancier la factory, elle retourne les commande, mais dans ce cas precis je veux charger le MySql.Data a la voler sans avoir besoin de mettre une reference de l'assemblie dans mon projet.

    ma factory dans ma class est

      Public Property Factory() As Common.DbProviderFactory

    il me faut maintenant l'instancier a la voler

    mardi 30 mars 2010 14:48
  • la creation de factory n'es pas compatible MySql, il faut utiliser celui de mySql

    Je ne comprends pas bien. Il est possible d'utiliser MySql.Data.MySqlClient comme avec n'importe quel autre provider. Un code comme

    DbProviderFactories.GetFactory(...)

    fonctionne également pour MySql.

    je veux charger le MySql.Data a la voler sans avoir besoin de mettre une reference de l'assemblie dans mon projet.

    Pour cela tu peux essayer de passer par Assembly.Load ou LoadFrom. Mais pour quelle raison ne souhaites tu pas référencer l'assembly, car dans outs les cas celle-ci devra être présente dans le projet si tu veux utiliser MySql.Data ?

    Cordialement

    mardi 30 mars 2010 15:17
  • Bonjour,

    DbProviderFactories.GetFactory() devrait vous retourner le client MySql si celui est installé correctement et paramétré dans le machine.config de votre poste. Regardez la section : "<system.data>" pour être sur...

    Cordialement


    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    mardi 30 mars 2010 21:33
    Modérateur
  • C'est exactement sa,

    je ne veux pas etre obliger d'inscrir l'assemblie pour que le code marche, si je ne met pas mysql, la class pourra etre importer dans mon projet et fonctionner sans rien fair, ...

    Exemple :

    La class marche avec Access,Sql Server et MySql, mais pour MySql il faut ajouté l'assemblie.

    Je prend un premier projet, il vas tourner sous mysql, j'ajoute l'assemblie mySql.Data, et ma class, je developpe tous est bon.

    Je prend un second projet, il va tourner sous Sql Server, j'ajoute la class, mais la il me met une erreur dans mon code MySql.Data n'existe pas, normal je ne vaus pas l'ajouter il ne vas pas tourner sur MySQl...

    Ce que je veux c'est que je fasse une liaison tardive, ... sa plantera au moment de l'appele de la fonction si MySql n'est pas ajouter dans le projet, et pas au moment ou je met la clas. Sinon je suis chaque fois obliger de modifier mon code pour les projet qui n'on pas MySql ...

    C un peu compliquer comme principe, et je consoie que pas beaucoup de monde on probablement ce type de besoin, mais je pense que l'on peu charger un assemblie a la voler, je vais essayer de voir avec Assembly.Load, mais sa ne correspond pas exactement a ce que je veux, dans ce cas la si c'est un projet MySql, la reference est ajouter, pas besoin de fair un assemblie load... juste une commande qui permet d'appeler la fonction de la class sans que cela la soit explicitement appele.

     

    Cordialement

    Sébastien

     

    mercredi 31 mars 2010 12:33
  • Bonjour,

    Dans ce cas, vous devez en effet utiliser la méthode Assembly.Load et utilisez la Reflection pour utiliser MySQL (du moins pouvoir accéder au Factory de MySql pouvant créer les Command, Connection,...etc).

    Cordialement


    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    mercredi 31 mars 2010 15:09
    Modérateur
  • Bonjour malheureusement cela ne fonctionne apparement pas (j'ai probablement mal saisie le load)

    J'ai cree une fonction qui me retourn l'object assemblie de MySql.Data

    Private Function GetAssemblieMySqlData() As System.Reflection.Assembly

            Return Reflection.Assembly.Load("MySql.Data")

        End Function

     

    et dans le code j'ai changé

                    Factory = MySql.Data.MySqlClient.MySqlClientFactory.Instance

    par
                    Factory = GetAssemblieMySqlData.CreateInstance("MySqlClient.MySqlClientFactory.Instance")

     

    Mais il me dit qu'il n'arrive pas a charger l'assemblie, je precise qu'il est imperatif qu'il prenne celui qui est referencer dans le projet !!! (celui pour lequelle j'ai fait un Reference, ajout et j'y est mi MySql.Data)

     

    Cordialement

    Sébastien

    PS : c'est mon ancien compte MSDN que j'utilise AserfSeb et Aserf sont les mêmes
                  

    mercredi 31 mars 2010 18:46
  • Bonjour,

    Voici le code à utiliser :

    Assembly a;
    Type t;
    FieldInfo f;
    DbProviderFactory factory;
    
    // Charger l'assembly
    a = Assembly.LoadFrom("< Emplacement de l'assembly >");
    
    // Récupérer le type MySqlClientFactory
    t = a.GetType("MySql.Data.MySqlClient.MySqlClientFactory");
    
    // Prendre le champ statique "Instance"
    f = t.GetField("Instance");
    
    // Récupérer le factory du champ statique
    factory = (DbProviderFactory)f.GetValue(null);
    

    Cordialement


    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    • Marqué comme réponse 3magroup jeudi 1 avril 2010 12:06
    mercredi 31 mars 2010 22:36
    Modérateur
  • Bonjour,

     

    j'ai modifier ma fonction ce qui donne ceci,

    ''' <summary>
        ''' Retourne une factory MySql
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetFactoryMySqlData() As Common.DbProviderFactory

            Dim lAssemblieMySqlData As System.Reflection.Assembly
            Dim lType As Type
            Dim lFiledInfo As System.Reflection.FieldInfo

            lAssemblieMySqlData = Reflection.Assembly.Load("MySql.Data")

            lType = lAssemblieMySqlData.GetType("MySql.Data.MySqlClient.MySqlClientFactory")
            lFiledInfo = lType.GetField("Instance")

            Return CType(lFiledInfo.GetValue(Nothing), Common.DbProviderFactory)

        End Function

    J'arrive a faire fonctionner l'assemblie, mais pour cela je doit le copier dans mon repertoir de sortie lors du debug,

    l'avantage avec cette methode est que je ne suis meme pas obliger de le rajouter au projet, juste a glisser l'assemblie dans le repertoir.

    Est ce qu'il existe une methode pour faire Assemblie.Load() d'un assemblie qui ce trouve dans le projet (je c'est cela semble absurde, car il sera deja charger)

    ou alors de pouvoir utiliser la ligne  lAssemblieMySqlData.GetType("MySql.Data.MySqlClient.MySqlClientFactory") sur un assemblie deja ajouté au projet ?

     

    Cordialement

    Sébastien

    jeudi 1 avril 2010 08:30
  • Bonjour,

     

    j'allais oublier, je voulais egalement vous remerciez.

    Cordialement

    Sébastien

    jeudi 1 avril 2010 08:30
  • Bonjour,

    Je voulais vous remercie, j'ai trouver la solution votre proposition ma mis sur la bonne voie,

    voici la fonction terminer elle en fait meme plus que ce que je pensais, maintenant elle permet de charger celui qui est referencer dans le projet, si elle ne le trouve pas alors je charge celui qui ce trouve sur le disque dur. cela permet a ma class de connexion de developper sur une base de donnée, et si un jour on veux migrer, il suffit de rajouter dans le repertoir le MySql.Data.dll, pour que l'application puisse ce connecter au serveur MySql.

    Merci encors,

    Sebastien

     


        ''' <summary>
        ''' Retourne une factory MySql
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetFactoryMySqlData() As Common.DbProviderFactory

            Dim lAssemblieMySqlData As System.Reflection.Assembly
            Dim lType As Type
            Dim lFiledInfo As System.Reflection.FieldInfo

            Try


                'on charge l'assemblie courent
                Dim lAssemblie As System.Reflection.Assembly = System.Reflection.Assembly.GetCallingAssembly

                Dim lIsMySql As Boolean = False

                'on boucle sur la liste des assemblies inclue dans cette assemblie
                For Each lAss As System.Reflection.AssemblyName In lAssemblie.GetReferencedAssemblies

                    'si on trouve l'assemblie en memoire, on le charge
                    If lAss.Name.ToLower = "MySql.Data".ToLower Then
                        lAssemblieMySqlData = Reflection.Assembly.Load(lAss)
                        lIsMySql = True
                    End If

                Next

                'Si l'assemblie ne peu etre charger du projet on prend celui qui ce trouve sur le repertoir
                If lIsMySql = False Then

                    lAssemblieMySqlData = System.Reflection.Assembly.Load("MySql.Data")

                End If

                lType = lAssemblieMySqlData.GetType("MySql.Data.MySqlClient.MySqlClientFactory")
                lFiledInfo = lType.GetField("Instance")

            Catch ex As Exception
                Throw New Exception("<fx>ClassDataBaseConnector.GetFactoryMySqlData</fx><msg>" & ex.Message & "</msg>", ex)
            End Try

            Return CType(lFiledInfo.GetValue(Nothing), Common.DbProviderFactory)

        End Function

    • Marqué comme réponse 3magroup jeudi 1 avril 2010 12:06
    jeudi 1 avril 2010 10:02