これは興味深い質問です。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を拡張し、データのより特殊なビューのプロパティを追加する場合にもわずかに制限されます。つまり、同様のコードを持つ複数の式が作成される可能性があります。
ただし、オプション2は非常に気に入っていますが、このオプションは単一タイプのプロジェクションに制限されている可能性が高いと確信しています。次の例を検討してください。
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を使用して動的選択を作成できるかどうかも確認したいと思います。