Welcome to MSDN Blogs Sign in | Join | Help

News


  • Locations of visitors to this page
GQ08 VII: Linq to Sql mapping

Linq to Sql utilise des informations de mapping pour générer les requêtes Sql.
Comment récupérer ces informations de mapping pour notre propre usage ?

Imaginons un scénario simple pour générer dynamiquement les colonnes d'une grille (en mettant des combos pour les relations par exemple).

var db = new NorthwindDataContext(); var q = from c in db.Customers select c; grid.Columns.Add(...); grid.Columns.Add(...); ... grid.ItemsSource = q.ToList();
Posted: Monday, August 25, 2008 12:24 PM by mitsu
Filed under: , , ,

Comments

Matthieu MEZIL said:

On pourrait envisager quelque chose comme ça :

foreach (var p in from prop in typeof(Product).GetProperties()

                 where prop.GetCustomAttributes(typeof(ColumnAttribute), true).Any()

                 select prop)

   dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = p.Name, DataPropertyName = p.Name });

foreach (var p in from prop in typeof(Product).GetProperties()

                 where prop.GetCustomAttributes(typeof(AssociationAttribute), true).Any()

                 select prop)

   dataGridView1.Columns.Add(new DataGridViewComboBoxColumn { HeaderText = p.Name, DataPropertyName = p.Name, DataSource = db.GetTable(p.PropertyType) });

dataGridView1.DataSource = q;

# August 25, 2008 8:26 AM

Simon said:

var tableMetaType = db.Mapping.GetTable(typeof(Customer)).MetaType;

foreach(var columnMetaData in tableMetaType.DataMembers)

{

  if(columnMetaData.IsAssociation)

  {

      grid.Columns.Add(BuildEntityRefColumn(columnMetaData.Name, columnMetaData.Association.OtherType);

  }

  else

  {

     grid.Columns.Add(new ScalarColumn(columnMetaData.MappedName, columnMetaData.Name);

  }

}

Un truc dans le genre à priori (pas testé, ni même buildé ^^)

# August 25, 2008 8:43 AM

Simon said:

Mathieu, ton code ne fonctionne qu'avec le mapping par attribut :p OUNED !

# August 25, 2008 8:44 AM

Miiitch said:

Voici mon idée: je passe par le TypeDescriptor. On ajoute une méthode MapColumn<T>:

var q =

   from c in db.Customers

   select c;

MapColumn(grid,q);

grid.ItemsSource = q.ToList();

----------------------

Et le code de la méthode (au moins la partie intéressante:

       private void MapColumn<T>(DataGridView gv, IEnumerable<T> result)

       {

           PropertyDescriptorCollection propertyCollection = TypeDescriptor.GetProperties(typeof(T));

           gv.Columns.Clear();

           foreach (PropertyDescriptor prop in propertyCollection)

           {

               if (prop.PropertyType == typeof(bool))

               {

                   // A remplir...

               }

               else if (prop.PropertyType == typeof(DateTime))

               {

                   // A remplir...

               }

               else

               {

                   // A remplir...

               }

           }

       }

# August 25, 2008 8:51 AM

mitsu said:

Et oui...petit piège, bien joué Simon.

Rappel donc:

- Linq to Sql utilise des metas informations sur son modèle objet pour mapper les informations physiques du modèle de base de données. Ex: quelle table correspond à quelle classe.

- Linq to Sql propose deux types de définitions de ce mapping:

1- par attribut

2- via une définition xml

La première solution, plus lisible lorsque l'on parcourt le code est intimement liée à la génération des entités et peut apparaître trop peu flexible.

La solution xml permet d'associer dynamiquement un mapping à un datacontext instancié. Elle permet aussi facilement de créer des moteurs de personnalisation du mapping après utilisation de sqlmetal (outil en ligne de commande de génération du mapping depuis la base de données).

Quoi qu'il en soit les deux méthodes définissent juste le mapping et le reste du moteur de requêtage de Linq to Sql est indépendant de ce choix.

Si vous voulez développer une solution exploitant les métas informations de Linq to Sql qui prenne vraiment en compte ces deux définitions de mapping, le datacontext en offre une asbtraction via une petite API, voir la réponse de Simon ci-dessus.

# August 25, 2008 9:05 AM

mitsu said:

Petite coquille, remplacez 'MetaType' par 'RowType' dans l'exemple de Simon

# August 25, 2008 9:10 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker