EF Core:仅包含many-nav属性的实例

时间:2017-08-23 21:58:36

标签: c# entity-framework linq entity-framework-core

public class Chat 
{
    public string ChatID { get; set; }
    [Required]
    public ICollection<Message> Messages { get; set; }
}

public class Message 
{
    public string MessageID { get; set; }
    public DateTime Time { get; set; }
    [Required]
    public Chat Chat { get; set; }
}

我如何加载聊天列表,其中包含最新(仅限)(按Message.Time排序})消息,每个请求只有ICollection<Message> Messages导航属性到DB? EF Core中没有包含条件(chat.messages.last())

1 个答案:

答案 0 :(得分:0)

这适用于EF6,在EF Core中不确定

您可以按照@CodeNotFound的想法进行修改,然后 可能 仍可以单独往返数据库,前提是您只对聊天感兴趣有消息

var chatInfos = db.Chats
    .Where(chat => ...) // filter chats if you need to
    .SelectMany(chat =>

        // INNER JOIN with Messages, ORDER by Time, SELECT TOP 1
        chat.Messages.OrderByDescending(m => m.Time).Take(1),

        // Explicitly load Chat, LastMessage and no more than that
        (chat, msg) => new
        {
            Chat = chat,
            LastMessage = msg
        })

     // Materialize!!
     // EF will fix-up Chat-Message navigation and will know that LastMessage is in the Chat's messages collection
    .ToList()

     // Sort again, you have the last message but not the chats ordered by last message 
    .OrderByDescending(x => x.LastMessage.Time)

    // Now you have a list of chats, with last message, sorted by last message time
    .ToList();

foreach (var info in chatInfos)
{
    var chatEntry = db.Entry(info.Chat);
    var messageCollection = chatEntry.Collection(x => x.Messages);

    // Tell EF that the collection is loaded
    // Though the last query only loaded ONE Message entity via Explicit Loading
    messageCollection.IsLoaded = true;
}

// Get the chats, now calls to chat.Messages should not be lazy loaded for these and the collection should contain only one Message
var chats = chatInfos.ConvertAll(x => x.Chat);

我没有测试此代码,但在EF 6上使用类似的代码