连接不包含任何关系的表
Join tables that contain no relationship
我有以下数据库:
Table 消息:
- 负责存储发送给不同电子邮件地址的邮件。
Table 电子邮件:
- 只负责存储邮箱地址(主键=Email)
(toEmail 与 table 电子邮件有关系)(Sotres Foo@gmail.com、Foo2@gmail.com 等...)
Table 联系人:
- 用于存储用户的联系人。 (商店马克、约翰、汤姆等...)
Table 联系邮箱
- 需要这个 table 因为一个联系人可能有多个电子邮件地址。 (存储在 table 电子邮件中找到的 ID)
总之问题是:
我想创建一个查询,该查询将 select 在特定日期发送的所有消息。 我想在查询中包含联系人姓名(如果存在)。我创建了以下查询,但速度很慢:
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 个查询?
将所有联系人存储在字典中将使事情变得更有效率。但是从我不需要的数据库中检索所有联系人让我觉得我在浪费资源。
如果我们能看到您的 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,
};
如果这不起作用,您可能希望对所有 tryGetContact
调用仅执行一次 db.ContactEmails
并将结果存储在集合中(或 HashSet 以获得更好的性能)。
我有以下数据库:
Table 消息:
- 负责存储发送给不同电子邮件地址的邮件。
Table 电子邮件:
- 只负责存储邮箱地址(主键=Email) (toEmail 与 table 电子邮件有关系)(Sotres Foo@gmail.com、Foo2@gmail.com 等...)
Table 联系人:
- 用于存储用户的联系人。 (商店马克、约翰、汤姆等...)
Table 联系邮箱
- 需要这个 table 因为一个联系人可能有多个电子邮件地址。 (存储在 table 电子邮件中找到的 ID)
总之问题是: 我想创建一个查询,该查询将 select 在特定日期发送的所有消息。 我想在查询中包含联系人姓名(如果存在)。我创建了以下查询,但速度很慢:
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 个查询?
将所有联系人存储在字典中将使事情变得更有效率。但是从我不需要的数据库中检索所有联系人让我觉得我在浪费资源。
如果我们能看到您的 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,
};
如果这不起作用,您可能希望对所有 tryGetContact
调用仅执行一次 db.ContactEmails
并将结果存储在集合中(或 HashSet 以获得更好的性能)。