Linq to sql Linq到SQL DTO和复合对象

Linq to sql Linq到SQL DTO和复合对象,linq-to-sql,dto,separation-of-concerns,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

我正在使用与其他人类似的方法将我的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)
             };
//CoreDBDataContext db=coreDB;
公共IQueryable GetPositions(){
从coreDB.位置的p返回
选择新的DTO位置
{
DTO.User=新的DTO.User(p.User.id,p.User.username,p.User.firstName,p.User.lastName,p.User.email,p.User.isActive),
DTO.Role=新的DTO.Role(p.Role.id,p.Role.name,p.Role.isActive),
DTO.OrgUnit=新的DTO.OrgUnit(p.OrgUnit.id,p.OrgUnit.name,p.OrgUnit.isActive)
};
Positions是我的Linq Position对象,我返回一个DTO Position,它由用户、OrgUnit和角色组成(底层表是一个带有UserID、RoleID和OrgUnitID的联接表)

我遇到的问题是,当我尝试在iQueryTable上添加过滤器时,我得到一个SQL错误,表示没有可用于我的DTO.User对象的转换

public static IQueryable<Position> WithUserID(this IQueryable<Position> query, int userID)
    {
        return query.Where(p => p.User.ID == userID);
    }
publicstaticiqueryable with userID(此IQueryable查询,int-userID)
{
返回query.Where(p=>p.User.ID==userID);
}
我完全不知道如何着手解决这个问题,因为我所有的谷歌搜索结果似乎都是与直接处理生成的LINQ对象的人一起工作的

有没有想过如何让这一切顺利进行,或者我在这里做了什么完全错误的事情


谢谢

Linq2SQL只理解设计器生成的对象。嗯,这并不完全正确,但已经足够接近了

因此,当您针对Linq2SQL对象编写Linq查询时,查询将在实际执行时转换为有效的SQL,而不是在编写时。由于您的DTO对象不是Linq2SQL对象,Linq2SQL将不知道如何创建正确的SQL

如果希望以这种方式保持分离,则必须找到一种只使用Linq2SQL对象执行查询的方法,并且只将结果映射到DTO

也许您可以将查询方法重写为:

更新:参数的类型必须为
表达式
,无需 返回一个
IQueryable
。感谢 弗雷迪指出

public IEnumerable FindPositions(表达式条件)
{
从coreDB.位置的p返回
where-criteria.Invoke(p)
选择新的DTO位置
{
User=new DTO.User(p.User.id、p.User.username、p.User.firstName、p.User.lastName、,
p、 User.email,p.User.isActive),
Role=新的DTO.Role(p.Role.id、p.Role.name、p.Role.isActive),
OrgUnit=新数据到OrgUnit(p.OrgUnit.id,p.OrgUnit.name,p.OrgUnit.isActive)
};
}

我已经能够成功地使用类似的方法:

var courses = from c in Map(origCourses)
where !expiredStatuses.Contains(c.Status)
select c;
其中Map有:

    select new UserCourseListItem
    {
        CourseID = c.CourseID,
        CourseName = cm.CourseName,
        CourseType = c.CourseType.Value
        ...
用那种类型的初始化(而不是构造函数)试试怎么样

这是工作应用程序的一部分,ExpiredStatus甚至与复杂表达式相关

更新1:这与上述场景类似,因为:

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

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

但是,为什么要使结果可查询:)顺便说一句,我已经使用了两种方法,请参见我的答案:)Freddy,你说对了。我的错,我太匆忙地复制和粘贴:-(我曾尝试过类似的映射函数,但我正在尝试使我的data repos类尽可能精简,然后使用扩展方法将过滤器添加到我的数据存储库的实现中。我们有一个只使用列表的测试repos,以及一个用于实际生产代码的sql repos,我理解,但我的意思是这可能是由于使用了构造函数(只是猜测)请注意,我的MAP方法返回一个可查询的,这就是为什么我认为过滤器的情况是等价的。因此,这会从数据存储中获取所有数据,然后过滤映射对象吗?通过取取你的意思,如果你不过滤它,它就可以得到所有的数据,是的。当你过滤它时,LIQ2SQL实际上会考虑它。查询,因此您只获取筛选后的数据:)
    select new UserCourseListItem
    {
        CourseID = c.CourseID,
        CourseName = cm.CourseName,
        CourseType = c.CourseType.Value
        ...