2009-01-31 10 views
0

J'ai un très gros problème pour résoudre ce problème J'ai 2 tablesrequête complexe en utilisant LINQ et C#

première table

est: http://lh3.ggpht.com/_uMvfbnPHuko/SYPJQ1ZsBDI/AAAAAAAAAKs/eq49xquy3jM/s800/Untitled-2.jpg

qui contient un module (id et nom)

la deuxième table est http://lh6.ggpht.com/_uMvfbnPHuko/SYPJQ4IXGwI/AAAAAAAAAK0/zmTIO6V-UEQ/s800/Untitled-3.jpg

qui contient les identifiants des utilisateurs et leurs numéros de modules préférés

permet maintenant passer au problème Je veux générer une liste de cases à cocher

par exemple pour le userid 1 qui comprend les modules suivants « 4 et 3,2 » le résultat sera

http://lh4.ggpht.com/_uMvfbnPHuko/SYPJQ_LJeVI/AAAAAAAAAK8/6RV8a1S8eCY/s800/Untitled-4.jpg

avis que « recommandé pour vous » case à cocher est pas cochée, car l'utilisateur 1 n'a pas id module « 1 »

J'ai passé beaucoup de temps à essayer de résoudre ce problème en utilisant C# et LINQ

voir le résultat de mon effort :) (le code suivant ne fonctionne pas)

var q = from m in db.modules 
      from um in db.usersModules.Where(um2 => um2.userId == myUserId).Single().modules.Trim().Split(',') 
      where um.Contains(m.moduleId.ToString()) 
      select new 
      { 
       moduleid = here i want the module id from modules table 
       modulename = here i want the modulename from modules table 
       ischecked = here i want "true" or "false" depending on if the user has this module or not 

      }; 

Si LINQ est facile pour vous s'il vous plaît essayer de résoudre celui-ci? avez-vous des questions?

Répondre

2

Votre requête ne fonctionne pas car LinqToSQL essaie de tout traduire en SQL normal.

Si vous ne pouvez pas factoriser votre schéma, et utiliser une table intermédiaire puisque vous avez clairement un bateau beaucoup à-plusieurs, vous pouvez faire quelque chose comme ceci:

var userModules = db.userModules.SingleOrDefault(m => m.userId == myUserId).modules; 
// Get the modules of the user (a comma delimited string) 
var integerModules = modules.Split(',').Select(m => int.Parse(m)); 
// Convert the comma delimited string to IEnumerable<int> 

var query = db.modules.Select(x => new { 
       x.moduleId, 
       x.moduleName, 
       isChecked = integerModules.Contains(x.moduleId) 
}); // And finally do the query 
+0

merci l'homme, cela fonctionne !, j'ai essayé depuis longtemps et enfin merci :) – ahmed

+0

Nice CMS :) Ahmed, vous devriez refactoriser votre schéma DB. Ayant 2,3,4 que les données sont mauvaises. Utilisez soit un un à plusieurs table mec ... c'est la bonne chose à faire ici IMO. –

+0

Merci Pure.Krome, je suis également d'accord avec vous, ahmed, vous devriez utiliser une table de liaison entre les utilisateurs et les modules, et si vous voulez garder une trace de la commande (userId, moduleId, number), vous pouvez ajouter un champ entier faites cela, les requêtes seront plus faciles ... – CMS

1

Comment utiliser une liste délimitée par des virgules? La meilleure approche serait d'avoir une table entre lesquels stocke le mappage entre les utilisateurs et les modules.

+0

Je suis d'accord avec vous, mais j'ai choisi cette modèle de base de données pour être en mesure de stocker l'ordre des modules pour chaque utilisateur , par exemple l'utilisateur 1 ont des modules dans cet ordre 3,2,4 – ahmed

+0

@ahmed: Vous pouvez toujours stocker l'ordre, vous avez juste une autre colonne dans la table de mappage avec l'ordre et peupler cela dans l'ordre croissant. – casperOne

1

Si vous le pouvez, il pourrait être préférable de factoriser vos tables plutôt que d'essayer de traiter les données dans le format il se trouve.

Dans votre table « usersModule », si vous changez la colonne de modules « moduleId "et juste insérer un enregistrement pour chaque module associé à l'userId, vous aurez beaucoup plus de temps à interroger les données que je crois, et votre base de données sera beaucoup plus facile à maintenir.

Table: "modules" 
moduleId moduleName 
1   Recommended... 
2   Blah 
3   ... 

Table: "usersModule" 
userId  moduleId 
1   3 
1   2 
1   4 
+0

Je suis d'accord avec mais j'ai choisi ce modèle de base de données pour pouvoir stocker l'ordre des modules pour chaque utilisateur , par exemple l'utilisateur 1 a des modules dans cet ordre 3,2,4 – ahmed

+0

Vous pouvez ajouter une autre colonne à la table comme " order "où vous pourriez stocker le rang du module pour cet utilisateur. Vous ne devriez pas mettre une liste d'identifiants séparés par des virgules dans une colonne, cela rend la requête très difficile. –

+0

Je suis d'accord que cette séparation des colonnes sera beaucoup plus facile à interroger, mais il est juste une requête, enfin il a réglé – ahmed

0

Si c'est une option, vous pouvez refactoriser votre schéma de base de données. Votre table usersModule doit avoir un identifiant utilisateur et un identifiant de module par ligne, et la colonne moduleId doit être une clé étrangère de la table de modules. Si vous le faites de cette façon, la requête linq serait triviale.

Si vous êtes bloqué avec la base de données telle quelle, vous êtes probablement bloqué en utilisant deux requêtes: une requête pour récupérer les ID de module et une autre requête pour récupérer les informations de module réelles.

0

Ce serait quelque chose comme ça, mais je n'ai pas donné suffisamment d'informations précises sur la structure de ma base de données pour que je puisse écrire la requête exactement.

var q = 
    from m in db.modules 
    select new { 
     m.moduleId, 
     m.name, 
     db.usersModules.Exists(um => um.userId == myUserId) 
    }; 

Édition: oh Je viens de réaliser que vous avez une chose séparée par des virgules. Réorganisez votre base de données correctement, comme les autres l'ont dit.

+0

ive obtenu cette erreur "usersModules n'a pas difinition pour Exists et méthode d'extension"? – ahmed

+0

Eh bien, je ne vais pas écrire votre code pour vous! Je viens de dire que ça pourrait être fait comme ça. –

+0

merci l'homme pour essayer d'aider :), meilleures salutations – ahmed

Questions connexes