簡體   English   中英

EF自定義查詢與相關表

[英]EF custom query with related tables

我有一個代碼第一個數據模型,我需要做一個復雜的查詢返回相關表中的一些聚合信息。 首先是我的簡化模型:

public class Forum 
{
    public virtual int ForumID { get; set; }
    public virtual string Name { get; set; }
    public virtual ICollection<Topic> Topics { get; set; }
}

[NotMapped] 
public class ForumWith : Forum 
{
    public virtual int topics { get; set; }
    public virtual int messages { get; set; }
    public virtual DateTime lastDate { get; set; }
    public virtual int lastUser { get; set; }
}

public class Topic 
{
    public virtual int TopicID { get; set; }
    public virtual string Subject { get; set; }
    public virtual int ForumID { get; set; }
    [ForeignKey("ForumID")]
    public virtual Forum Forum { get; set; }
    public virtual ICollection<Message> Messages { get; set; }
}

public class Message
{
    public virtual int MessageID { get; set; }
    public virtual int TopicID { get; set; }
    [ForeignKey("TopicID")]
    public virtual Topic Topic { get; set; }
    public virtual string Text { get; set; }
    public virtual DateTime CreatedDate { get; set; }
    public virtual User CreatedBy { get; set; }
} 

我想要做的是使用上次創建的消息中的主題數,消息數以及日期和用戶填充“ForumWith”對象。

我的第一個解決方案是在forum.topics和forum.topics.messages集合上使用幾個循環。 這很好用,但性能很糟糕。

為了解決這個問題,我創建了一個SQL查詢,在3個表上進行左連接,包括group by和sum / max聚合。 這個SQL我用context.Database.SqlQuery(sql)執行; 並且數據填充得很好,性能非常好。

我的問題是:

  1. 有沒有什么辦法可以將ForumWith中的“int lastUser”替換為實際的用戶對象“User lastUserObject”,而不必循環遍歷結果集並從context.Users手動填充它。

  2. 有沒有更好的方法通過linq / EF進行這種聚合,同時保持性能?

SQL:

SELECT  dbo.Forum.ForumID ,
        dbo.Forum.Name ,
        COUNT(DISTINCT dbo.Topics.TopicID) AS topics,
        COUNT(DISTINCT MessageID) AS messages, 
        MAX(dbo.Messages.CreatedDate) AS lastDate, 
        (SELECT UserName FROM [User] where UserId = 
        CONVERT(INT,SUBSTRING(max(CONVERT(varchar,dbo.Messages.CreatedDate,20) + '#' + CONVERT(VARCHAR,dbo.Messages.CreatedBy_UserId,20)),21,10))) AS lastUser
FROM dbo.Forum 
    LEFT JOIN dbo.Topics ON dbo.Forum.ForumID = dbo.Topics.ForumID
    LEFT JOIN dbo.Messages ON dbo.Topics.TopicID = dbo.Messages.TopicID
GROUP BY  dbo.Forum.ForumID ,
        dbo.Forum.Name 

有幾種Linq 2 EF方法可以實現這一目標。 下面顯示的第一個可能是兩者中最慢的,但如果沒有您的架構和填充數據,我無法確定。 假設列表都包含填充的論壇列表(很可能會從您的上下文中提取,即dbContext.Forums)

方法1

list.Select(
            x =>
            new ForumWith
                {
                    ForumID = x.ForumID,
                    Name = x.Name,
                    topics = x.Topics.Count,
                    messages = x.Topics.SelectMany(y => y.Messages).Count(),
                    lastDate = x.Topics.SelectMany(y => y.Messages).OrderByDescending(y => y.CreatedDate).First().CreatedDate,
                    lastUser = x.Topics.SelectMany(y => y.Messages).OrderByDescending(y => y.CreatedDate).First().CreatedBy
                });

方法2

from forum in list
let latest = forum.Topics.SelectMany(x => x.Messages).OrderByDescending(x => x.CreatedDate).First()
select
    new ForumWith
        {
            ForumID = forum.ForumID,
            Name = forum.Name,
            topics = forum.Topics.Count,
            messages = forum.Topics.SelectMany(y => y.Messages).Count(),
            lastDate = latest.CreatedDate,
            lastUser = latest.CreatedBy
        };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM