[英]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.