À contre-sens avec Linq

Publié le par ludooo.over-blog.net

Il est assez aisé de trouver de l'information sur la méthode à suivre pour mettre à jour une base de données à partir d'une BindingSource et ce, au travers d'un DataContext et de l'utilisation de Linq-To-SQL.

Mais c'est l'autre sens qui m'intéresse ici : Comment mettre à jour une BindingSource avec le contenu de la base de données ?

Cette information court beaucoup moins les forums en date d'aujourd'hui, et la question promet de s'arracher les cheveux.

Mise en situation:
J'ai une table dans une base de données sur serveur. Cette table est nourrie par plusieurs clients différents. Pour autant, les clients doivent en tout temps voir l'ensemble des enregistrements de cette table (par "en tout temps", on entendra un Refresh du DataGridView toutes le minutes).
Chaque appli client est constituée d'un unique formulaire comportant DatagridView et divers contrôles 'bindés' à une BindingSource 'bs'. Le Datacontext 'dc' est déclaré global au formulaire.

 Problématique:
Rafraîchir la liste des enregistrements de la table chez chacun des clients. 
Note: le Refresh est généré par chaque poste client, non par le serveur. 

Résolutions:
On gère la mise à jour de la BindingSource sur l'évènement Form_Tick (i.e. lorsque le délai est écoulé).

Solution qui paraît l'être et qui ne l'est pas :
 bs.DataSource=dc.MaTable 
Ajoutez autant de dgv.Refresh ou autre grément que vous le souhaitez... vous êtes dans une impasse.

Solution qui cache de futurs problèmes :
(je rappelle ici que j'utilise un DataContext global dans mon Form)
 dc= New MonDataContext 
 bs.DataSource = dc.MaTable 
Là, je ne rentrerai pas dans les détails des conséquences du geste que vous posez ; pas dans cet article du moins... Mais disons que "ça part croche" comme diraient certains.

Solution qui commence à l'être :
 dc.Refresh(Data.Linq.RefreshMode.OverwriteCurrentValues, bs) 
Cette ligne va s'occuper du lot de données 'bs', notre BindingSource, et va comparer ce lot aux données de MaTable, avec comme règle que les données de MaTable priment sur les données de ma BindingSource (OverwriteCurrentValues).
Mais rappelons-nous le contexte:
User1 veut mettre à jour les données affichées sur son poste, après que User2 ait ajouté un élément au travers de son formulaire (et donc de sa BindingSource, pour finir dans MaTable). La BindingSource de User1 est donc bien différente de celle de User2 (oui c'est évident, mais posons l'évidence). Autrement dit, la mise à jour des données de User1 ne sera basée que sur les enregistrements qu'il est en mesure de voir dans son DataGridView. Mais tout nouvel enregistrement (comme celui ajouté par User2) passera au travers des mailles du filet.

En clair, cette solution fera transparaitre toute modification apportée au jeu de données déjà visible chez un utilisateur, mais ne fera transparaître aucun ajout qui aurait été effectué par un autre utilisateur (enfin sur un autre poste)

Solution viable :
C'est la seule solution à ma connaissance qui va tenir compte des éléments ajoutés à la BD :
 bs.DataSource = From elmt In dc.MaTable Select elmt 

Pourquoi cette ligne fonctionne, et pourquoi la première solution envisagée ne fonctionne pas ? Pour moi mystère ; mais à un moment donné, soyons productif... ça fonctionne et je m'en contente très bien

Source :

- la source libératrice

Publié dans Linq

Pour être informé des derniers articles, inscrivez vous :
Commenter cet article