我是新來的.Net,ASP,實體框架和Linq的世界,所以忍受着我...在模型上正確實現IQueryable作爲成員變量?
我最初有一個模型設置如下;
public class Pad
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid PadId { get; set; }
public string StreetAddress { get; set; }
public int ZipCode { get; set; }
public virtual ICollection<Mate> Mates { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
(A墊是一個聊天室 - 它包含了許多隊友和數以萬計的消息) 在Web API控制器,我設計獲得從指定的墊25個最近的消息的功能。
public IHttpActionResult GetMessages(string id)
{
var padGuid = new Guid(id);
// Try to find the pad referenced by the passed ID
var pads = (from p in db.Pads
where p.PadId == padGuid
select p);
if (pads.Count() <= 0)
{
return NotFound();
}
var pad = pads.First();
// Grab the last 25 messages in this pad.
// PERFORMANCE PROBLEM
var messages = pad.Messages.OrderBy(c => c.SendTime).Skip(Math.Max(0, pad.Messages.Count() - 25));
var messagesmodel = from m in messages
select m.toViewModel();
return Ok(messagesmodel);
}
這個實現的問題是,它好像EF加載整組消息(數千個)的入內存得到計數,排序等,從而產生了巨大的性能損失之前有很多消息的墊子。
我首先想到的是把Pad.Messages
成員類型轉換爲IQueryable
而不是ICollection
- 這應該推遲LINQ查詢到SQL,我這樣想着。然而,在這樣做的時候,上面的功能就像pad.Messages.Count()
抱怨 - 原來pad.Messages
是空值!並在其他地方中斷,例如將Messages
添加到Pad.Messages
的值。
什麼是這樣的正確實施?在其他地方,我已經看到推薦的解決方案是針對上下文構建第二個查詢,如select Messages where PadId = n
,但是當我可以使用Messages成員值時,這看起來似乎很直觀。
謝謝!
你理解正確。這是EF在這種情況下的表現。 –
並非如此@TMcKeown您可以使用LINQ以避免遇到此問題。看到我的答案。 –
爲什麼不通過SendTime降序訂購25個元素?在記憶中,你總是可以重新命令它們再次上升。 – Dismissile