连接不包含任何关系的表

Join tables that contain no relationship

我有以下数据库:

  1. Table 消息:

    • 负责存储发送给不同电子邮件地址的邮件。
  2. Table 电子邮件:

    • 只负责存储邮箱地址(主键=Email) (toEmail 与 table 电子邮件有关系)(Sotres Foo@gmail.com、Foo2@gmail.com 等...)
  3. Table 联系人:

    • 用于存储用户的联系人。 (商店马克、约翰、汤姆等...)
  4. 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 以获得更好的性能)。