我正在使用實體框架與MySQL數據庫和DbContext。我有一個實體「消息」,有一個相關的實體「發件人」。 (「消息」也有一個相關的實體「接收者」)。我正在嘗試編寫一個查詢,它將只返回每個接收者的「最新」消息。但是當我這樣做時,我也想加載關聯的「發件人」,以便我可以訪問我要返回的數據傳輸對象中包含的發件人屬性(電子郵件字段)之一。 「MessageDTO」是我返回的數據傳輸對象,包括消息的標識,消息的內容和發件人的電子郵件。如何獲取每個組使用實體框架和MySQL包括相關實體的最新記錄
如果我排除發件人的電子郵件從DTO,那麼下面的查詢返回正是我需要的(即針對每個接收最新消息):
var refGroupQuery = (from m in dbContext.Messages.SqlQuery("select * from messages order by created_at desc")
group m by m.receiver_id into refGroup
select new MessageDTO { id = refGroup.FirstOrDefault().id, content = refGroup.FirstOrDefault().content});
然而,上述說法不加載與該消息相關聯的發送者,所以當我再包括髮送者的電子郵件中DTO我得到一個NullReferenceException,如下圖所示:
var refGroupQuery = (from m in dbContext.Messages.SqlQuery("select * from messages order by created_at desc")
group m by m.receiver_id into refGroup
select new MessageDTO { id = refGroup.FirstOrDefault().id, content = refGroup.FirstOrDefault().content, sender_email = refGroup.FirstOrDefault().sender.email});
refGroup.FirstOrDefault()sender.email拋出一個NullReferenceException因爲發件人爲空。 。
如何在查詢中加載發件人,以便我可以將發件人的電子郵件包含在我的DTO中?
編輯:
按照要求,我包括獲取由格特·阿諾德的建議方法生成的SQL:
{SELECT
1 AS `C1`,
`Apply1`.`id`,
`Apply1`.`sender_id`,
`Apply1`.`RECEIVER_ID1` AS `receiver_id`,
`Apply1`.`created_at`,
`Apply1`.`read_status`,
`Extent3`.`email`
FROM (SELECT
`Distinct1`.`receiver_id`,
(SELECT
`Project2`.`id`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
FROM `messages` AS `Extent2`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `id`,
(SELECT
`Project2`.`sender_id`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`content`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
FROM `messages` AS `Extent2`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `sender_id`,
(SELECT
`Project2`.`receiver_id`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`content`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
FROM `messages` AS `Extent2`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `RECEIVER_ID1`,
(SELECT
`Project2`.`receivable_type`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`content`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `content`,
(SELECT
`Project2`.`created_at`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`content`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
FROM `messages` AS `Extent2`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `created_at`,
(SELECT
`Project2`.`updated_at`
FROM (SELECT
`Extent2`.`id`,
`Extent2`.`sender_id`,
`Extent2`.`receiver_id`,
`Extent2`.`content`,
`Extent2`.`created_at`,
`Extent2`.`read_status`
FROM `messages` AS `Extent2`
WHERE (`Extent1`.`receiver_id` = `Extent2`.`receiver_id`) OR ((`Extent1`.`receiver_id` IS NULL) AND (`Extent2`.`receiver_id` IS NULL))) AS `Project2` LIMIT 1) AS `read_status`
FROM (SELECT DISTINCT
`Extent1`.`receiver_id`
FROM `messages` AS `Extent1`) AS `Distinct1`) AS `Apply1` LEFT OUTER JOIN `users` AS `Extent3` ON `Apply1`.`sender_id` = `Extent3`.`id`}
爲什麼使用'SqlQuery'?沒有它,整個查詢將被翻譯成SQL,並且發件人將被加入。 –
使用SqlQuery是我能夠在「group by」之前執行「order by」的唯一方法。如果我將SqlQuery替換爲「order by」指令,則查詢不會再返回每個組的最新記錄,而是僅返回每個組的一些記錄。我在http://stackoverflow.com/questions/5140785/mysql-order-before-group-中讀到,「每個組中的值的選擇不會受到添加ORDER BY子句的影響。結果集的排序發生在值已被選擇,並且ORDER BY不會影響服務器選擇哪個值「 – Stanley