[英]EF FromSql() with related entities
免責聲明:這些要求不是我設定的,除非這是一項不可能完成的任務,否則我無法說服老板。
假設我們有兩個實體: Item
和ItemTranslation
。
public class Item
{
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<Item> Children { get; set; }
public virtual Item Parent { get; set; }
public virtual ICollection<ItemTranslation> Translations { get; set; }
}
public class ItemTranslation
{
public int Id { get; set; }
public string CultureId { get; set; }
public string Description { get; set; }
public virtual Item Item { get; set; }
}
要求是Item
。 Description
應根據默認選擇的語言進行填寫,但也可以根據用戶的需要指定。 該Item
。 Description
列實際上在數據庫中不存在。
在SQL中,這很容易:您要做的就是像這樣查詢兩個表
SELECT [Item].[Id], [ItemTranslation].[Description], [Item].[ParentId]
FROM [Item]
LEFT JOIN [ItemTranslation] ON [Item].[Id] = [ItemTranslation].[ItemId]
WHERE [CultureId] = {cultureId}
或根據您的實現使用外部應用。 我已將此查詢添加到實體框架中內置的.FromSql()
函數中。
將所有這些放到OData API中,對於一個Item
一切正常。 但是,一旦您開始使用$ expand(在幕后是一種.include()),它就不再起作用。 發送到數據庫的相關實體的查詢不再包含我在.FromSql()
指定的SQL。 只有第一個查詢。 最重要的是,當您從其他控制器(例如ItemTranslation
查詢Item
,這也將不再起作用,因為.FromSql()
僅應用於其他控制器。
我可以編寫一個查詢攔截器,該查詢攔截器FROM [Item] LEFT JOIN [ItemTranslation] ON [Item].[Id] = [ItemTranslation].[ItemId] WHERE [CultureId] = {cultureId}
Entity Framework替換生成的SQL,然后將FROM [Item]
替換為FROM [Item] LEFT JOIN [ItemTranslation] ON [Item].[Id] = [ItemTranslation].[ItemId] WHERE [CultureId] = {cultureId}
但我想知道是否有比這更好的實現。 甚至可以重新設計模型。 我願意提出建議。
FromSql有一些局限性 。 我懷疑這是Include無法起作用的原因。
但是一旦使用EF,為什么要搞亂SQL? 該查詢有哪些困難使您無法在LINQ中進行查詢? 左加入也許?
from item in ctx.Items
from itemTranslation in ctx.ItemTranslations.Where(it => it.Item.Id == item.Id).DefaultIfEmpty()
where itemTranslation.CultureId == cultureId
select new { item.Id, itemTranslation.Description, ParentId = item.Parent.Id };
更新
再次討論這個問題,我看到了另一個問題。 Include僅適用於IQueryable <T> ,其中T是其導航屬性已正確映射的實體。 現在,從這個角度來看,如果使用FromSql或LINQ生成的是某個投影的IQueryable而不是實體,則無所謂, Include顯然不能工作。
為了能夠包含ItemTranslation實體,您的操作方法應如下所示:
[Queryable]
public IQueryable<Item> GetItems()
{
return db.Items;
}
因此,框架可以對您返回的IQueryable <Item>執行$ expand 。 但是,這將包括所有項目的翻譯,而不僅僅是具有所需文化的項目。 如果我正確理解,這是您的核心問題。
同樣很明顯,您不能將此區域性過濾器應用於IQueryable <Item> 。 但是您不應該這樣做,因為這是通過OData中的$ filter實現的:
GET https://.../Items/$expand=Translations&$filter=Translations/CultureId eq culture
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.