Linq to SQL DTO和复合对象

时间:2009-03-04 18:15:48

标签: linq-to-sql dto separation-of-concerns

我正在使用类似的方法将LINQ对象保留在我的LINQ数据提供程序中并返回IQueryable以允许过滤等。这适用于通过它的ID或其他属性过滤简单对象,但我有一个由其他子对象组成的连接表对象的问题

    //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 Object,我正在返回一个DTO位置,它由User,OrgUnit和Role组成(底层表是一个带有UserID,RoleID和OrgUnitID的连接表)

我遇到的问题是,当我尝试在Iqueryable上添加过滤器时,我收到一条SQL错误,说我的DTO.User对象没有可用的翻译

public static IQueryable<Position> WithUserID(this IQueryable<Position> query, int userID)
    {
        return query.Where(p => p.User.ID == userID);
    }

我完全不知道如何解决这个问题,因为我的所有Google搜索结果似乎都是直接使用生成的LINQ对象的人

有没有考虑如何使这项工作,或者我在这里做了一些完全错误的事情?

由于

3 个答案:

答案 0 :(得分:1)

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)
                      };
}

答案 1 :(得分:1)

我已经能够以类似的方法成功地工作:

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:与上述方案相比,这是相似的,因为:

  • Map返回一个IQueryable,它是一个POCO对象。
  • 在调用使用POCO对象返回IQueryable的Map方法后,我正在对它应用过滤器。

答案 2 :(得分:1)

我最终没有为我的复杂查询使用过滤器。相反,我向存储库添加了方法,以满足更复杂的查询要求。我觉得这会使系统更易于理解和维护。