这是一个有趣的问题。我认为 DTO 可以在这里为您提供帮助,但是需要注意一些限制和陷阱。以以下LINQPad示例为例:
class ProjectDTO
{
public string Name { get; set; }
public static Expression<Func<Project, ProjectDTO>> ToDTO = (e) => new ProjectDTO
{
Name = e.Name
};
public ProjectDTO() {}
public ProjectDTO(Project project)
{
Name = project.Name;
}
}
void Main()
{
Projects.Select(p => p.Name).Dump();
Projects.Select(ProjectDTO.ToDTO).Dump();
Projects.Select(p => new ProjectDTO(p)).Dump();
}
生成的 SQL:
SELECT [t0].[Name]
FROM [Project] AS [t0]
GO
SELECT [t0].[Name]
FROM [Project] AS [t0]
GO
SELECT [t0].[ProjectId], [t0].[Name], [t0].[Description], [t0].[DateCreated], [t0].[DateModified], [t0].[DateComplete], [t0].[CreatedBy]
FROM [Project] AS [t0]
如您所见,您不能使用复制构造函数来分配 DTO 的属性,因为这会强制从数据库中拉回整个对象。
如果您想扩展基本 DTO 并为更专业的数据视图添加更多属性,这也略有限制,这意味着您最终可能会得到多个具有相似代码的表达式。
但是,我非常喜欢选项二,但我确信此选项很可能仅限于单一类型的投影,请考虑以下示例:
var query = from p in Projects
join t in Tasks on p.ProjectId equals t.ProjectId
select ProjectDTO.ToDTO; //Can't be used like this
我认为您不能在这种类型的查询语法中使用表达式。一般来说,我认为不会有一个全面有效的解决方案。您可能需要检查您的设计,看看您是否可以提供更少的预测,基于一些非常便宜的属性总是包含在查询中?
在不使用动态 LINQ 库或手动构建表达式树的情况下,我还想看看是否可以使用 LINQ-SQL/LINQ-Entities 创建动态选择。