Linq to SQL DTOおよび複合オブジェクト
-
03-07-2019 - |
質問
LINQオブジェクトをLINQデータプロバイダーに保持し、フィルタリングなどを許可するためにIQueryableを返す際に、他のユーザーと同様のアプローチを使用しています。他の子オブジェクトで構成される結合テーブルオブジェクトの問題
//CoreDBDataContext db = coreDB;
public IQueryable<DTO.Position> GetPositions() {
return from p in coreDB.Positions
select new DTO.Position
{
DTO.User = new DTO.User(p.User.id,p.User.username, p.User.firstName,p.User.lastName,p.User.email,p.User.isActive),
DTO.Role = new DTO.Role(p.Role.id, p.Role.name, p.Role.isActive),
DTO.OrgUnit = new DTO.OrgUnit(p.OrgUnit.id,p.OrgUnit.name,p.OrgUnit.isActive)
};
coreDB.Positionsは私のLinq Positionオブジェクトであり、User、OrgUnit、およびRoleで構成されるDTO Positionを返します(基になるテーブルはUserID、RoleID、およびOrgUnitIDを持つ結合テーブルです)
私が抱えている問題は、Iqueryableにフィルターを追加しようとすると、DTO.Userオブジェクトの翻訳が利用できないというSQLエラーが表示されることです
public static IQueryable<Position> WithUserID(this IQueryable<Position> query, int userID)
{
return query.Where(p => p.User.ID == userID);
}
すべてのGoogleの結果は、生成されたLINQオブジェクトを直接操作している人のものであると思われるため、これを解決する方法について完全に迷っています
この作業を行う方法について何か考えましたか、またはここで完全に間違ったことをしていますか?
ありがとう
解決 3
複雑なクエリにフィルターを使用しないことになりました。代わりに、より複雑なクエリ要件のために、リポジトリにメソッドを追加しました。これにより、システムが理解しやすくなり、保守が容易になります。
他のヒント
同様のアプローチで問題なく作業できました:
var courses = from c in Map(origCourses)
where !expiredStatuses.Contains(c.Status)
select c;
マップの場所:
select new UserCourseListItem
{
CourseID = c.CourseID,
CourseName = cm.CourseName,
CourseType = c.CourseType.Value
...
(コンストラクタではなく)そのタイプの初期化で試してみてください。
これは動作しているアプリケーションの一部であり、expiredStatusesは複雑な式に関連しています。
更新1:これは、前述のシナリオと比較して類似しています。理由は次のとおりです。
- マップは、POCOオブジェクトであるIQueryableを返します。
- POCOオブジェクトでIQueryableを返すMapメソッドを呼び出した後、フィルターを適用しています。
Linq2SQLは、デザイナーが生成したオブジェクトのみを理解します。まあ、それは完全に真実ではありませんが、十分に近いです。
したがって、LinqクエリをLinq2SQLオブジェクトに対して再度記述すると、クエリは書き込まれたときではなく、実際に実行されたときに有効なSQLに変換されます。 DTOオブジェクトはLinq2SQLオブジェクトではないため、Linq2SQLは適切なSQLを作成する方法を知りません。
このように分離を維持する場合は、Linq2SQLオブジェクトのみを使用してクエリを実行し、結果をDTOにマップする方法を見つける必要があります。
クエリメソッドを次のように書き換えることができます:
更新:パラメーターはタイプである必要があります
Expression<>
、およびする必要はありませんIQueryable<>
を返します。おかげで 指摘してくれたフレディ。
public IEnumerable<DTO.Position> FindPositions(Expression<Func<Position, bool>> criteria)
{
return from p in coreDB.Positions
where criteria.Invoke(p)
select new DTO.Position
{
User = new DTO.User(p.User.id, p.User.username, p.User.firstName, p.User.lastName,
p.User.email, p.User.isActive),
Role = new DTO.Role(p.Role.id, p.Role.name, p.Role.isActive),
OrgUnit = new DTO.OrgUnit(p.OrgUnit.id, p.OrgUnit.name, p.OrgUnit.isActive)
};
}