2013-05-06 3 views
2

У меня есть база данных с таблицей, которая хранит user_id s и tag_id s. Я хочу написать функцию, которая принимает два user_id s и возвращает tag_id s, которые оба пользователя имеют вместе.C# Получить общие записи по LINQ

Эти выборки строк из базы данных:

User_id  Tag_id 
    1   100 
    1   101 
    2   100 
    3   100 
    3   101 
    3   102 

Что я хочу от моей функции является то, что, когда я называю функцию как getCommonTagIDs(1, 3), он должен вернуться (100,101). То, что я делал до сих пор, заключается в том, что я сохраняю строки, связанные с user_id в двух разных списках, а затем используя для циклов, возвращаю общие tag_id.

using (TwitterDataContext database = TwitterDataContext.CreateTwitterDataContextWithNoLock()) 
     { 

      IEnumerable<Usr_Tag> tags_1 = database.Usr_Tags.Where(u => u.User_id == userID1).ToList(); 
      IEnumerable<Usr_Tag> tags_2 = database.Usr_Tags.Where(u => u.User_id == userID2).ToList(); 

      foreach (var x in tags_1) 
      { 
       foreach (var y in tags_2) { 
        if (x.Tag_id == y.Tag_id) { 
         var a =database.Hashtags.Where(u => u.Tag_id==x.Tag_id).SingleOrDefault(); 
         Console.WriteLine(a.Tag_val); 
        } 

       } 
      } 
     } 

То, что я хочу спросить, что, вместо того, чтобы все строки из базы данных и поиска общих tag_id с в функции, я хочу, чтобы получить общие tag_id s непосредственно из базы данных с помощью LINQ, делая расчеты на стороне базы данных. Буду признателен, если вы поможете мне.

Это SQL, что я писал:

SELECT [Tag_id] 
FROM [BitirME].[dbo].[User_Tag] 
WHERE USER_ID = '1' AND Tag_id IN (
SELECT [Tag_id] 
FROM [BitirME].[dbo].[User_Tag] 
where USER_ID = '3') 
+0

Если ваш пример вызовет возврат 100, 101 и 102? –

+0

Нет, только 100 и 101, потому что userid = 1 и userid = 2 имеют только 100 и 101 общий – alidogan

ответ

2

То, что вы хотите, это «Перекресток» из тех, два комплекта:

var commonTags = database.Usr_Tags.Where(u => u.User_id == userID1).Select(u => u.Tag_id) 
    .Intersect(database.Usr_Tags.Where(u => u.User_id == userID2).Select(u => u.Tag_id)); 

И вуаля, все готово.

Или, чтобы очистить его немного:

public static IQueryable<int> GetUserTags(int userId) 
{ 
    return database.Usr_Tags 
     .Where(u => u.User_id == userId) 
     .Select(u => u.Tag_id); 
} 

var commonTags = GetUserTags(userID1).Intersect(GetUserTags(userID2)); 
+0

Большое спасибо. Это сработало :) – alidogan

0

Если я получил это право, запрос, как это может быть, что вам нужно

var q = from t in database.Usr_Tags 
     //all Usr_Tags for UserID1 
     where t.User_Id == userID1 && 
     //and there is a User_tag for User_ID2 with same Tag_ID 
     database.User_Tags.Any(t2=>t2.User_ID==userID2 && t2.Tag_ID==t.Tag_ID) 
     select t.Tag_Id; 

var commonTags = q.ToList(); 
+0

Вы действительно хотите сделать внутреннее соединение из Usr_Tags на Usr_Tags вместо того, чтобы выполнять n подселектов. –

1

Вот один из способов сделать это:

int[] users = new int[] {1,3}; // for testing 

database.Ustr_Tags.Where(t => users.Contains(t.User_id)) 
        .GroupBy(t => t.Tag_id) 
        .Where(g => users.All(u => g.Any(gg=>gg.User_id == u))) // all tags where all required users are tagged 
        .Select(g => g.Key); 

Одним из преимуществ это одного он может быть использован для любого количества пользователей (не только 2).

Смежные вопросы