简体   繁体   中英

complex query using LINQ and C#

I have a very big problem solving this issue I have 2 tables

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

which contains a modules (id and name)

second table is http://lh6.ggpht.com/_uMvfbnPHuko/SYPJQ4IXGwI/AAAAAAAAAK0/zmTIO6V-UEQ/s800/Untitled-3.jpg

which contains users ids and their preferred modules' numbers

now lets move to the problem I want to generate a list of checkboxes

for example for the userid 1 which has the following modules "3,2 and 4" the result will be

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

notice that "recommended for you" checkbox is not checked because the user 1 does not have module id "1"

I spent a long time trying to solve this problem using c# and LINQ

see the result of my effort :) (the following code does not work)

    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

            };

If LINQ is easy for you please try to solve this one? any questions?

Your query doesn't works because LinqToSQL tries to translate everything to plain SQL.

If you cannot refactor your schema, and use an intermediate table since you clearly have a many-to-many relation ship, you can do something like this:

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

How come you are using a comma-delimited list? The better approach would be to have a table in between which stores the mapping between users and modules.

If you can, it might be best to refactor your tables rather than trying to deal with the data in the format it's in.

In your "usersModule" table, if you change the modules column to "moduleId" and just insert a record for every module associated with the userId, you'll have a much easier time querying the data I believe, and your database will be much easier to maintain.

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

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

If it's an option, you might want to refactor your database schema. Your usersModule table should have one user id and one module id per row, and the moduleId column should be a foreign key to the module table. If you do it this way, the linq query would be trivial.

If you're stuck with the database as-is, you're probably stuck using two queries: one query to retrieve the module id's, and another query to retrieve the actual module info.

It would be something like this I think, but you haven't given enough exact information about your database structure for me to write the query exactly.

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

Edit: oh I just realised you've got a comma-separated thing. Rearrange your database properly first, like the others have said.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM