[英]Saved projection expression for re-use in different linq expressions with two source objects
這通常是我保存投影表達式以重新用於DTO的方式:
public class MyUserDTO
{
public string Forename { get; set; }
public string Surname { get; set; }
public static Expression<Func<MyUserDTO, MyUserDBObject>> FromDBUserProjection = u => new MyUserDTO() { Forename = u.Forename, Surname = u.Surname };
public static IQueryable<MyUserDTO> FromDBUser(IQueryable<MyUserDBObject> dbRecords)
{
return dbRecords.Select(FromDBUserProjection);
}
}
這是一個簡單的DTO,具有從特定數據庫對象進行投影所必需的投影表達式。
每當我想從數據庫查詢此數據時,都可以像這樣使用它,這樣我就不必每次都編寫投影:
IQueryable<MyUserDTO> myUsers = MyUserDTO.FromDBUser(context.MyUserDBObjects.Where(u => u.Forename = "Bob"));
通過這種方式,我將數據映射與數據庫查詢分開,並確保在不同查詢之間的映射是一致的。 這通常對我來說很好,但是現在我需要從兩個不同的數據庫對象進行投影,例如:
public class MyCompositeDTO
{
public string User1Forename { get; set; }
public string User1Surname { get; set; }
public string User2Forename { get; set; }
public string User2Surname { get; set; }
}
//simplified example to demonstrate my question
IQueryable<MyCompositeDTO> matchingUsers = from u1 in context.MyUserDBObjects
join u2 in context.MyUserDBObjects on u1.Surname equals u2.Surname
select new MyCompositeDTO()
{
User1Forename = u1.Forename,
User1Surname = u1.Surname,
User2Forename = u2.Forename,
User2Surname = u2.Surname
};
在上面的示例中,我可以輕松地在原始linq查詢中創建投影,因為此時我同時擁有u1和u2。 但是,是否可以像我在第一個示例中所做的那樣,通過某種方式將投影分為不同的函數,並將其保留為IQueryable? 沒有鏈接兩個源記錄的外鍵。
我對查詢語法不太熟悉,因此必須使用方法語法。 實際上,我不確定甚至可以使用查詢語法來完成; 也許其他人可以肯定地說。
給定此表達式:
public static readonly Expression<Func<MyUserDBObjects, MyUserDBObjects, MyCompositeDTO>> CompositeDtoProject =
(u1, u2) =>
new MyCompositeDTO()
{
User1Forename = u1.Forename,
User1Surname = u1.Surname,
User2Forename = u2.Forename,
User2Surname = u2.Surname
};
您可以這樣做:
IQueryable<MyCompositeDTO> matchingUsers =
MyUserDBObjects
.Join(
MyUserDBObjects,
u1 => u1.Surname,
u2 => u2.Surname,
CompositeDtoProject);
我通常不提供人們從未要求的觀點或替代方案,而是回答人們的問題,因為,好吧,當人們對我的問題回答時,我並不在乎。 但是由於我已經為提出的問題提供了解決方案,也許我可以不提出自己的意見。 對我來說,您所做的令人困惑。 我認為可以通過更直接的方式完成同一件事。 考慮一下:
public class MyUserDTO
{
public string Forename { get; set; }
public string Surname { get; set; }
}
public static class MyUserDtoExtensions
{
public static IQueryable<MyUserDTO> AsDto(this IQueryable<MyUserDBObject> source)
{
return
source
.Select(x => new MyUserDTO()
{
Forename = u.Forename,
Surname = u.Surname
}
}
}
然后代替這個
IQueryable<MyUserDTO> myUsers = MyUserDTO.FromDBUser(context.MyUserDBObjects.Where(u => u.Forename = "Bob"));
您可以這樣寫:
IQueryable<MyUserDto> myUser =
context
.MyUserDBObjects
.Where(u => u.Forename = "Bob")
.AsDto();
讀起來比較容易。 將投影分為單獨的擴展類也將使您更輕松地添加其他功能。 例如,如果您發現自己經常搜索該名字,則可以添加另一個擴展方法,如下所示:
public static IQueryable<MyUserDto> WhereForenameIs(this IQueryable<MyUserDto> source, string name)
{
return
source
.Where(u => u.Forename = name);
}
然后執行以下操作:
IQueryable<MyUserDto> myUser =
context
.MyUserDBObjects
.AsDto()
.WhereForenameIs("Bob");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.