如何LINQ当一个键是ArrayOfInt而另一个键时加入int
我试图从数据库中获取消息的某个收件人与用户匹配的消息列表。通常情况下,如果只有一个收件人,你会像下面如何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的字符串是一个整数?
选项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
};
的想法:
- 获取邮件作为原始查询
- 获取其中包含在收件人列表中的所有人员
- 继续与您原来的查询
选项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
};
的想法:
- 获取邮件作为原始查询
- 斯普利特将该字符串转换为Int32列表
- 加入此列表对抗
db.persons
- 继续您的o riginal查询
不知道其中哪些是快,你必须检查。
我也会回避使用逗号分隔的字符串作为外键参考,因为您在这里遇到了麻烦。他们看起来很丑陋,而且操纵真正的痛苦。相反,如果您可以控制架构,请考虑一个具有MessageId
和PersonId
的一对多关系表。当然,如果你没有控制权,你就会陷入困境。
声明:这些未经测试,因此可能需要对代码进行一些调整才能使用。算法应该没问题。
我最初过分简化了查询,现在应该更清楚了。 – sean 2009-07-02 00:55:51
您需要将收件人转换为元素列表作为开始。我假设收件人是来自人员表格的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的工作。因此,数据库将不得不传输大量数据来执行此查询,具体取决于表的大小。如果您在将数据库标记为已存在数据库时拥有数据库视图,或者您可以在数据库中创建一个包含消息标识符的消息收件人的新表格,则可以更轻松地完成此操作(而不是在过程中提到正常化你的数据库)。
它无法完成。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/d2791ad4-3897-4fc0-80e9-72ebc4822898 – sean 2009-07-04 11:58:10
以下内容可能也是有用的信息,http://tomasp.net /blog/linq-expand.aspx – sean 2009-07-06 06:50:38