2009-07-02 35 views
0

我试图从数据库中获取消息的某个收件人与用户匹配的消息列表。通常情况下,如果只有一个收件人,你会像下面如何LINQ当一个键是ArrayOfInt而另一个键时加入int

var res = db.messages.Where(m => m.id == message_id) 
       .Join(db.persons, m => m.recipients, p => p.id, (m, p) => new {m, p}) 
       .Select(x => new Message(){ msg = x.m, person = x.p}) 

但是,如果收件人什么是一个逗号分隔的整数和id的字符串是一个整数?

+0

它无法完成。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/d2791ad4-3897-4fc0-80e9-72ebc4822898 – sean 2009-07-04 11:58:10

+0

以下内容可能也是有用的信息,http://tomasp.net /blog/linq-expand.aspx – sean 2009-07-06 06:50:38

回答

0

选项1 - 使用包含:

var res = from m in db.messages 
      where m.id == message_id 
      from p in db.persons 
      where m.recipients.Split(",").Select(i => Int32.Parse(i)) 
       .Contains(p.id) 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

的想法:

  1. 获取邮件作为原始查询
  2. 获取其中包含在收件人列表中的所有人员
  3. 继续与您原来的查询

选项2 - 使用LINQ加入(也许复杂得多,它需要):

var res = from m in db.messages 
      where m.id == message_id 
      from r in m.recipients.Split(",") 
      select new { 
       Message = m, 
       Recipient = Int32.Parse(r) 
      } into rec 
      join p in db.persons on rec equals p.id 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

的想法:

  1. 获取邮件作为原始查询
  2. 斯普利特将该字符串转换为Int32列表
  3. 加入此列表对抗db.persons
  4. 继续您的o riginal查询

不知道其中哪些是快,你必须检查。

我也会回避使用逗号分隔的字符串作为外键参考,因为您在这里遇到了麻烦。他们看起来很丑陋,而且操纵真正的痛苦。相反,如果您可以控制架构,请考虑一个具有MessageIdPersonId的一对多关系表。当然,如果你没有控制权,你就会陷入困境。

声明:这些未经测试,因此可能需要对代码进行一些调整才能使用。算法应该没问题。

+0

我最初过分简化了查询,现在应该更清楚了。 – sean 2009-07-02 00:55:51

1

您需要将收件人转换为元素列表作为开始。我假设收件人是来自人员表格的ID列表。因此,从你的问题你必须传入人员ID做一个选择呢?

var messages=db.messages.Select(
     m => m.id == message_id && 
     (m.recipients.Split(","). 
      Any(recipient => reipient == person_id) 
     ) 

var person = db.Persons.Select(p => p.id == person_id) 

注意,在LINQ这样做是要吃亏的性能损失象外之象.Split是C#,不会对IQueryable的工作。因此,数据库将不得不传输大量数据来执行此查询,具体取决于表的大小。如果您在将数据库标记为已存在数据库时拥有数据库视图,或者您可以在数据库中创建一个包含消息标识符的消息收件人的新表格,则可以更轻松地完成此操作(而不是在过程中提到正常化你的数据库)。

相关问题