使用linq查找匹配多个行值的外键

时间:2013-10-08 08:53:52

标签: c# sql linq

我有一个名为对话的表格,列出了同一个对话中的用户。例如:

id | conversation | user
1  |  1           |  Bob
2  |  1           |  Jane
3  |  2           |  Tim
4  |  2           |  Lily
5  |  2           |  Rick

我有一些用户喜欢这样的列表..

List<string> usernames = new List<string>{"Bob","Jane"};

我现在想要检查用户何时想要与其他用户开始对话,无论他们之前是否曾与其他用户进行对话(仅限于此)。

EG。鲍勃希望与简创建一个新的对话。(我的用户名列表值中有鲍勃和简,以便比较之前是否已进行过对话?)

正如我们看到他们两人已经进行了对话,我想让对话ID属于这两个人。

如果我的列表包含以下数据......

List<string> usernames = new List<string>{"Bob","Jane","Tim"};

这一次,我期待之前没有对话。

我想知道没有对话我可以为他们创建一个新的。

我在Linq尝试这个但到目前为止无法得到任何正确的结果。

提前感谢您的帮助;

5 个答案:

答案 0 :(得分:2)

您可以按会话ID进行分组,并将这些群组与您的用户列表进行匹配:

var previousConversations = userConversations
    .GroupBy(uc => uc.Conversation)
    .Where(g => g.OrderBy(uc => uc.user).Select(uc => uc.user)
        .SequenceEqual(usernames.Sort()));

答案 1 :(得分:1)

您可以使用SequenceEqual方法比较2个序列。

var users1 = new List<String> { "Bob", "Jane" };
var users2 = new List<String> { "Bob", "Jane", "Tim" };
var tableData = new List<YourTable>
    {
        new YourTable {foreignKey = 1, name = "Bob"},
        new YourTable {foreignKey = 1, name = "Jane"},
        new YourTable {foreignKey = 2, name = "Tim"},
        new YourTable {foreignKey = 2, name = "Lily"},
        new YourTable {foreignKey = 2, name = "Rick"},
    };
var keyFound = (from t in tableData
                group t by t.foreignKey into users
                where users.Select(u => u.name).SequenceEqual(users1)
                select users.Key).FirstOrDefault();

var keyNull = (from t in tableData
               group t by t.foreignKey into users
               where users.Select(u => u.name).SequenceEqual(users2)
               select users.Key).FirstOrDefault();

编辑: 您使用linq作为从数据库获取数据的方法,并非所有操作都以这种方式支持。我们可以做的是在内存中提取选择,然后我们可以再次使用所有操作 根据你的情况,这可能不是一个好主意,通常你想让sql处理所有查询功能,因为他更擅长。
但如果您选择的是一个不那么大的桌子,您可以轻松拉入内存,随意这样做:

var rawData = (from t in tableData
               group t by t.foreignKey into users
               select users).ToList();

var key = (from d in rawData
           where d.Select(u => u.name).SequenceEqual(users2)
           select d.Key).FirstOrDefault();

如果另一方面数据太大而你想在sql端执行,我会考虑为此创建一个存储过程。

答案 2 :(得分:0)

您基本上正在执行“这些标记”查询,此处可以回答:

Select items by tag when searching multiple tags

应用于您的问题,它看起来像:

int userCount = myUsers.Count;

List<int> conversationIds = conversationsUsers
  .Where(cu => myUsers.Contains(cu.UserName))
  .GroupBy(cu => cu.ConversationId)
  .Where(g => g.Select(cu => cu.Username).Distinct().Count() == userCount)
  .Select(g => g.Key)

  

(完全)。

好吧,好吧......将用户过滤转移到群组过滤中。

int userCount = myUsers.Count;

List<int> conversationIds = conversationsUsers
  .GroupBy(cu => cu.ConversationId)
  .Where(g => g.Select(cu => cu.Username).Distinct().Count() == userCount)
  .Where(g => g.Select(cu => cu.UserName).All(userName => myUsers.Contains(userName)))
  .Select(g => g.Key)

答案 3 :(得分:0)

请检查以下linq。如果任何会话为空,它将导致会话ID(枚举不产生结果)。您可以相应地检查您的条件。

var cust = new List<Table>
                       {
                           new Table {Conversation = 1, Id = 1, User = "Bob"},
                           new Table {Conversation = 1, Id = 2, User = "Jane"},
                           new Table {Conversation = 2, Id = 3, User = "Tim"},
                           new Table {Conversation = 2, Id = 4, User = "Lily"},
                           new Table {Conversation = 2, Id = 5, User = "Rick"}
                       };
        var names = new List<string> { "Rick", "Lily", "Tim" };


        var res = from x in cust
                  group x by x.Conversation
                  into y
                  where y.Select(z => z.User).Intersect(names).Count() == names.Count
                  select y.Key;

答案 4 :(得分:0)

感谢大家的帮助和回答。下面的代码完成了这个技巧并给了我想要的结果。感谢Kristof提供此代码和您的努力。我在第二个查询中附加了order by子句,否则它不会给出正确的结果。希望这可以帮助那些需要类似东西的人。

var users1 = new List<String> { "Bob", "Jane" };
var users2 = new List<String> { "Bob", "Jane", "Tim" };

var tableData = new List<YourTable>
    {
        new YourTable {foreignKey = 1, name = "Bob"},
        new YourTable {foreignKey = 1, name = "Jane"},
        new YourTable {foreignKey = 2, name = "Tim"},
        new YourTable {foreignKey = 2, name = "Lily"},
        new YourTable {foreignKey = 2, name = "Rick"},
    };



var rawData = (from t in tableData
               group t by t.foreignKey into users
               select users).ToList();

var key = (from d in rawData
           where d.Select(u => u.name).OrderBy(s=> s).SequenceEqual(users2.OrderBy(s=>s))
           select d.Key).FirstOrDefault();