IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entity Framework Discussion :

WriteXML avec Code First


Sujet :

Entity Framework

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut WriteXML avec Code First
    Bonjour à tous,

    Travaillant actuellement au développement d'un soft .NET, j'utilise "Code First" d'Entity Framework pour accéder aux données de ma base.

    J'ai besoin de pouvoir Exporter ces données en Xml, et de pouvoir en importer d'autres, depuis Xml. Je devrais également par la suite pouvoir upgrader une base en runtime.

    Je sais qu'il existe une méthode WriteXml avec les dataSet, seulement, je suis contraint d'utiliser "CodeFirst".

    Avez-vous une solution à cette problématique?

    Merci pour votre aide,
    Thlac.

    PS: Certain des paramètres de cette problématique sont imposés pour ce projet. Ils faudra donc composer avec :
    • "Code First"
    • L'import export en XML (au minimum) et CSV (pour le bonus)

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Tu peux toujours sérialiser/désérialiser les entités en XML comme indiquer dans ce tuto

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Tu peux toujours sérialiser/désérialiser les entités en XML comme indiquer dans ce tuto
    Merci TomLev pour ta réponse rapide.

    J'ai en effet déjà envisagé cette solution, sauf que j'ai une bonne centaine de tables (donc autant de classes) qui peuvent avoir jusqu'à 50 propriétés pour certaines.

    Je ne peux donc pas me permettre de faira "à la mano" la serialization de tous les types :
    XmlSerializer xs = new XmlSerializer(typeof(Voiture)).

    Peut-être à tu une solution pour automatiser cela?

    Thlac

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par thlac Voir le message
    Je ne peux donc pas me permettre de faira "à la mano" la serialization de tous les types :
    XmlSerializer xs = new XmlSerializer(typeof(Voiture)).
    Bah à un moment donné, tu vas quand même devoir faire du code spécifique pour chaque table, pour l'enregistrement... donc ajouter la désérialisation ne fait pas une très grosse différence il me semble.

    Sinon, tu peux toujours essayer de passer par la réflexion, mais c'est pas forcément évident.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    En fait je viens de penser à un truc... tu pourrais te débrouiller avec une méthode générique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void ImportEntitiesFromXml<T>(DbSet<T> table, string fileName)
    {
        XmlSerializer xs = new XmlSerializer(typeof(List<T>));
        using (var reader = XmlReader.Create(fileName))
        {
            var list = (List<T>)xs.Deserialize(reader);
            foreach (var item in list)
            {
                table.Add(item);
            }
        }
    }
    Et tu l'utilises comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    using (var context = new MyDbContext())
    {
        ImportEntitiesFromXml(context.Products, "products.xml");
        ImportEntitiesFromXml(context.Orders, "orders.xml");
        ImportEntitiesFromXml(context.Clients, "clients.xml");
        ...
        context.SaveChanges();
    }
    Donc au final, même avec beaucoup de tables, ça reste pas trop méchant...

    Sinon j'ai pas trop compris ce que le nombre de propriétés vient faire là-dedans ?

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par tomlev Voir le message
    ...tu vas quand même devoir faire du code spécifique pour chaque table...
    Ah

    Je pensais plutôt à un truc du genre:

    public void WriteXml()
    {
    Prend toutes les propriétés, de toutes les entités, de chaque type, se trouvant dans le DbContext.
    Les écrit dans un fichier xml en face de leur valeur.
    }

    Je vie dans un rêve ?

    Thlac

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par thlac Voir le message
    Je vie dans un rêve ?
    Un peu

    Sinon, tu as vu ma 2e réponse ? Vu que tu as posté juste après, tu l'as peut-être manquée...

    Après, tu peux toujours pousser encore un peu plus loin l'automatisation, mais c'est moche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public void ImportAllEntitiesFromXml(string directory)
    {
        using (var context = new MyDbContext())
        {
            var tableProperties = typeof(MyDbContext).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                                     .Where(p => p.PropertyType.IsGenericType && p.GetGenericTypeDefinition() == typeof(DbSet<>))
                                                     .ToArray();
            foreach(var prop in tableProperties)
            {
                Type entityType = prop.PropertyType.GetGenericArguments()[0];
                var table = prop.GetProperty(context, null);
                var method = this.GetType().GetMethod("ImportEntitiesFromXml").MakeGenericMethod(entityType);
                string fileName = string.Format("{0}.xml", prop.Name);
                method.Invoke(table, fileName)
            }
            context.SaveChanges();
        }
    }
    (j'ai pas testé, mais le principe est là...)

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    J'ai testé avec le méthode générique, mais le <T> a du mal à passer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public void ImportEntitiesFromXml<T>(DbSet<T> table, string fileName)
    {
         XmlSerializer xs = new XmlSerializer(typeof(List<T>));
         using (var reader = XmlReader.Create(fileName))
         {
              var list = (List<T>)xs.Deserialize(reader);
              foreach (var item in list)
              {
                   table.Add(item);
              }
         }
    }
    The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method 'System.Data.Entity.DbSet<TEntity>

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par thlac Voir le message
    Dans le 3éme méthode, à quoi sert le string directory? tu ne t'en sert pas dans la méthode?
    C'est un oubli... voilà ce que je comptais en faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public void ImportAllEntitiesFromXml(string directory)
    {
        using (var context = new MyDbContext())
        {
            var tableProperties = typeof(MyDbContext).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                                     .Where(p => p.PropertyType.IsGenericType && p.GetGenericTypeDefinition() == typeof(DbSet<>))
                                                     .ToArray();
            foreach(var prop in tableProperties)
            {
                Type entityType = prop.PropertyType.GetGenericArguments()[0];
                var table = prop.GetProperty(context, null);
                var method = this.GetType().GetMethod("ImportEntitiesFromXml").MakeGenericMethod(entityType);
                string fileName = string.Format("{0}.xml", prop.Name);
                method.Invoke(table, Path.Combine(directory, fileName))
            }
            context.SaveChanges();
        }
    }


    Citation Envoyé par thlac Voir le message
    pourquoi dit tu que c'est moche?
    Bah disons que c'est un peu bourrin d'utiliser la réflexion comme ça... mais si ça fait le boulot, c'est l'essentiel

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    Ok je comprend mieux l'utilité du directory.

    je ne sais pas si tu as vu mon post précédent. (j'ai mis le bouzon dans les réponses ...)

    j'ai également des erreur avec ta dernière solution :

    'System.Reflection.PropertyInfo' does not contain a definition for 'GetGenericTypeDefinition' and no extension method 'GetGenericTypeDefinition' accepting a first argument of type 'System.Reflection.PropertyInfo' could be found.
    'System.Reflection.PropertyInfo' does not contain a definition for 'GetProperty' and no extension method 'Getproperty' accepting a first argument of type 'System.Reflection.PropertyInfo' could be found.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par thlac Voir le message
    The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method 'System.Data.Entity.DbSet<TEntity>
    ah oui, il faut ajouter une contrainte sur T :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public void ImportEntitiesFromXml<T>(DbSet<T> table, string fileName) where  T : class
    {
        ...
    }
    Citation Envoyé par thlac Voir le message
    'System.Reflection.PropertyInfo' does not contain a definition for 'GetGenericTypeDefinition' and no extension method 'GetGenericTypeDefinition' accepting a first argument of type 'System.Reflection.PropertyInfo' could be found.
    Citation Envoyé par thlac Voir le message
    'System.Reflection.PropertyInfo' does not contain a definition for 'GetProperty' and no extension method 'Getproperty' accepting a first argument of type 'System.Reflection.PropertyInfo' could be found.
    arf, voilà ce que c'est quand on écrit du code sans le tester en dehors de l'IDE

    Le code corrigé complet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public void ImportEntitiesFromXml<T>(DbSet<T> table, string fileName) where T : class
    {
         XmlSerializer xs = new XmlSerializer(typeof(List<T>));
         using (var reader = XmlReader.Create(fileName))
         {
              var list = (List<T>)xs.Deserialize(reader);
              foreach (var item in list)
              {
                   table.Add(item);
              }
         }
    }
     
    public void ImportAllEntitiesFromXml(string directory)
    {
        using (var context = new MyDbContext())
        {
            var tableProperties = typeof(MyDbContext).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                                     .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
                                                     .ToArray();
            foreach(var prop in tableProperties)
            {
                Type entityType = prop.PropertyType.GetGenericArguments()[0];
                var table = prop.GetValue(context, null);
                var method = this.GetType().GetMethod("ImportEntitiesFromXml").MakeGenericMethod(entityType);
                string fileName = string.Format("{0}.xml", prop.Name);
                method.Invoke(table, Path.Combine(directory, fileName))
            }
            context.SaveChanges();
        }
    }

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    Je suis navré de te poster toutes mes erreurs de compilation, mais je comprend pas bien toutes les subtilités du code que tu me propose. (On ne joue pas dans la même cours )

    Une dernière petite erreur:

    The best overloaded method match for 'System.Reflection.MethodBase.Invoke(object, object[])' has some invalid argument.

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par thlac Voir le message
    The best overloaded method match for 'System.Reflection.MethodBase.Invoke(object, object[])' has some invalid argument.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public void ImportEntitiesFromXml<T>(DbSet<T> table, string fileName) where T : class
    {
         XmlSerializer xs = new XmlSerializer(typeof(List<T>));
         using (var reader = XmlReader.Create(fileName))
         {
              var list = (List<T>)xs.Deserialize(reader);
              foreach (var item in list)
              {
                   table.Add(item);
              }
         }
    }
     
    public void ImportAllEntitiesFromXml(string directory)
    {
        using (var context = new MyDbContext())
        {
            var tableProperties = typeof(MyDbContext).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                                     .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
                                                     .ToArray();
            foreach(var prop in tableProperties)
            {
                Type entityType = prop.PropertyType.GetGenericArguments()[0];
                var table = prop.GetValue(context, null);
                var method = this.GetType().GetMethod("ImportEntitiesFromXml").MakeGenericMethod(entityType);
                string fileName = string.Format("{0}.xml", prop.Name);
                method.Invoke(table, new object[] { Path.Combine(directory, fileName) });
            }
            context.SaveChanges();
        }
    }
    On va finir par y arriver

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2011
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2011
    Messages : 40
    Points : 35
    Points
    35
    Par défaut
    Merci beaucoup.

    D'après se que je comprend du code, method.invoke ... est censé appeler la méthode ImportEntitiesFromXml.

    Pourtant, elle n'y passe pas. Aucun fichier Xml n'est donc crée.

    A côté de ça, j'ai retouché la méthode ImportEntitiesFromXml pour en faire une méthode ExportEntitiesToXml. et biensur je me retrouve dnas la même situation : on y passe pas lorsqu'on appel ExportAllEntitiestoXml.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     public void ExportEntitiesToXml<T>(DbSet<T> table, string fileName) where T : class
            {
                XmlSerializer xs = new XmlSerializer(typeof(List<T>));
                using (var writer = XmlWriter.Create(fileName))
                {
                    try
                    {
                        var list = table.ToList<T>();
                        xs.Serialize(writer, list);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
            public void ExportAllEntitiesFromXml(string directory)
            {
                using (var context = new CaveAVinsContext())
                {
                    var tableProperties = typeof(CaveAVinsContext).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                                             .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
                                                             .ToArray();
                    foreach (var prop in tableProperties)
                    {
                        Type entityType = prop.PropertyType.GetGenericArguments()[0];
                        var table = prop.GetValue(context, null);
                        var method = this.GetType().GetMethod("ExportEntitiesToXml").MakeGenericMethod(entityType);
     
                        string fileName = string.Format("{0}.xml", prop.Name);
                        method.Invoke(table, new object[] {Path.Combine(directory, fileName)});
                    }
                    context.SaveChanges();
                }
            }

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Tu as essayé de mettre des points d'arrêt et d'exécuter pas à pas pour voir ce qui se passe ? Si ça n'y passe pas, c'est peut-être que tableProperties est vide, et qu'il y a donc une erreur dans la requête Linq qui cherche les tables... Les tables dans CaveAVinsContext sont bien des propriétés publiques de type DbSet<TEntity> ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 27/05/2014, 16h23
  2. Export de BDD avec Entity Framework Code First
    Par thor76160 dans le forum Entity Framework
    Réponses: 2
    Dernier message: 02/07/2013, 16h05
  3. Code first et Oracle avec odp .net
    Par durnambule dans le forum Entity Framework
    Réponses: 1
    Dernier message: 05/04/2013, 03h26
  4. Réponses: 1
    Dernier message: 30/01/2013, 13h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo