![](/img/trans.png)
[英]How can i expose dto objects using wcf data service with ef code first?
[英]How can I fetch child entities as DTO in parent using reusable queries/Expression's with EF code first?
我在尋找將實體及其子實體轉換為DTO對象的好方法時遇到問題。 在本文中,我創建了偽代碼,這是一個簡化的示例,省略了數據庫上下文DTO對象。 假設我有一個父實體和一個子實體:
public class Parent {
int Id;
string Name;
List<Child> Children;
}
public class Child {
int Id;
string Name;
Parent Parent;
int ParentId;
}
我研究了兩種可能性,但我一直找不到一個好的解決方案。 請查看兩個示例以及我遇到的問題。
1.使用選擇查詢的示例
要檢索所有父實體作為DTO,可以在Controller中執行以下操作:
public IHttpActionResult GetParents()
{
var children = from c in _context.Children
select new ChildDTO()
{
Id = c.Id,
Name= c.Name
};
var parents = from p in _context.Parents
select new ParentDTO()
{
Id = p.Id,
Name = p.Name
Children = children.ToList(),
};
return parents;
}
這將返回父DTO對象及其所有子對象作為DTO對象。 如果我想創建一個新函數以僅獲取ID為'1'的Parent,那么我現在必須復制select語句以添加where子句:
public IHttpActionResult GetParent(int parentId)
{
var parents = from p in _context.Parents where p.id == parentId
...
在某些情況下,如果我只想顯示父母列表,我也不想讓孩子反對。 這意味着我基本上必須復制代碼並將選擇內容更改為此:
select new ParentDTO()
{
Id = p.Id,
Name = p.Name
//Removed the Children
//Children = children.ToList(),
};
在此示例中,我沒有看到一種盡可能多地重用代碼的好方法,因此,我最終不會一遍又一遍地編寫相同的基本select語句。
2.使用表達式的示例
我也可以為父母和孩子創建表達式,但是我不知道
private static readonly Expression<Func<Child, ChildDTO>> AsChildDTO =
p => new ChildDTO()
{
Id = p.Id,
Name = p.Name
};
private static readonly Expression<Func<Parent, ParentDTO>> AsParentDTO =
p => new ParentDTO()
{
Id = p.Id,
Name = p.Name
};
為了得到父母,我可以在控制器中執行以下操作:
...
//Get list of parents
var parents = _context.Parents.Select(AsParentDTO);
//Or: Get only parent with Id
var specificParent= _context.Parents
.Select(AsParentDTO)
.Where(p => p.Id == 1);
return parents;
...
這個解決方案對我來說似乎很好,因為我可以重復使用Epressions並根據需要擴展它們。 我似乎只能通過這種方式將孩子包括在父母中:
...
var parents = _context.Parents
.Include(p => p.Children)
//I have no idea if it is possible to Invoke the child Expression here...
.Select(p => p.Children= AsChildDTO.Invoke()) //<-- this does not work
.Select(AsParentDTO)
...
正如我在上面的評論中所寫; 我不知道是否有可能在這里調用子表達式。
結尾
這是我嘗試過但仍然堅持的兩件事。 但是也可能是我錯過了一個非常明顯的解決方案。 我的問題是,如何以可以重用盡可能多的代碼的方式解決此問題?
我認為您過於復雜了。
var results=_context.Parents
.Include(p=>p.Children);
將返回您的EF對象。 那就是你應該使用的。 如果要將EF對象轉換為DTO對象,請將其保存為最終投影(我很少使用DTO對象,因為來自EF的POCO對象通常就可以了)。
var parents=results.Select(p=>new ParentDTO
{ id=p.id,name=p.name,children=p.Children.ToList()}
);
如果只需要父母1,則:
var parent=results.Where(p=>p.id==1);
如果您希望將其作為parentDTO:
var parent=results.Where(p=>p.id==1).Select(p=>new ParentDTO {
{ id=p.id,name=p.name,children=p.Children.ToList()}
);
您可以使用AsParentDto之類的東西,但這是否意味着您將要復制整個Parent屬性? (在您的簡單情況下-ID和名稱)。 並且,如果要復制整個屬性列表,為什么要創建一個具有與EF對象相同的屬性的新對象,而不僅僅是重用EF對象? 我唯一使用Dto對象的情況是,如果我想傳遞僅具有某些屬性的父對象,並且希望避免自己從數據庫中檢索其他屬性,在這種情況下,我仍然會使用原始數據庫查詢,然后將其投影到最后一步。
var slimparent=results.Where(p=>p.id==1).Select(p=>new SlimParentDto {
id=p.id });
當然,如果我想要的只是父ID,那么我將使用甚至更簡單的IQueryable<int>
:
var parentids=results.Where(p=>p.id==1).Select(p=>p.id);
-TL; DR-
創建單個方法來檢索您的對象將包括的所有屬性。 然后,所有內容都應以此為基礎,並在控制器中附加進一步的細化以將其過濾為僅所需的數據子集。 然后,作為最后一步,將結果投影到所需的任何DTO中。 在完成投影之前,切勿使用任何方法來枚舉IQueryable。 EF / LINQ隨后將為您生成最佳查詢,只需檢索填充DTO所需的屬性即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.