我有以下数据库:
表格消息:
表格电子邮件:
表格联系人:
表格ContactEmails
无论如何,这是一个问题: 我想创建一个查询,选择在特定日期发送的所有邮件。 我想在查询中包含联系人姓名(如果存在)。我创建了以下查询,但速度很慢:
Func<string, Contact> tryGetContact = (email)=>{
var contactEmail = db.ContactEmails.FirstOrDefault(x=>x.IdEmail==email);
if(contactEmail==null)
return null;
return contactEmail.Contact; // navigational property created by entity framework.
};
var query = from msg in db.Messages
join email in db.Emails on msg.ToEmail equals email.Email
where msg.Date < "some date" && msg.Date > "some other date"
select new
{
MessageSubject = msg.Subject,
ToEmail = email.Email,
Contact = tryGetContact(email.Email) // this slows down the query!
};
为了使我的查询执行得更快,我是否需要将所有联系人存储在字典中并将此查询分成2个查询?
将所有联系人存储在字典中会使事情变得更有效率。但是从我不需要大部分数据库的数据库中恢复所有联系人会让我觉得我在浪费资源。
答案 0 :(得分:3)
如果我们能够看到Linq查询生成的实际SQL,那么确定什么会降低查询速度会更容易。但是,我想这可能与你的tryGetContact
Func有关,它与查询的主要部分没有共享相同的上下文。
因此,如果我是对的,每次拨打tryGetContact(email.Email)
时都会因为这一行而执行新的完整查询:
var contactEmail = db.ContactEmails.FirstOrDefault(x=>x.IdEmail==email);
在这种情况下,db.ContactEmails
不是SQL查询中的连接的一部分,因此每次都会重新执行。
所以我要做的是添加另一个join
以在Linq(和后续SQL)查询中包含ContactEmails
。这应该是这样的:
var query = from msg in db.Messages
join email in db.Emails on msg.ToEmail equals email.Email
join contactEmail in db.ContactEmails on contactEmail.IdEmail equals email.Email
where msg.Date < "some date" && msg.Date > "some other date"
select new
{
MessageSubject = msg.Subject,
ToEmail = email.Email,
Contact = (contactEmail==null) ? contactEmail.Contact : null,
};
如果这不起作用,您可能只想对所有db.ContactEmails
调用执行tryGetContact
一次,并将结果存储在Collection(或HashSet中)以获得更好的性能。