Linq to sql AutoMapper支持Linq吗?

Linq to sql AutoMapper支持Linq吗?,linq-to-sql,automapper,Linq To Sql,Automapper,我对具有延迟加载特性的LINQtoSQL非常感兴趣。在我的项目中,我使用AutoMapper将数据库模型映射到域模型(从DB\u RoleInfo映射到DO\u RoleInfo)。在我的存储库代码中,如下所示: public DO_RoleInfo SelectByKey(Guid Key) { return SelectAll().Where(x => x.Id == Key).SingleOrDefault(); } public I

我对具有延迟加载特性的LINQtoSQL非常感兴趣。在我的项目中,我使用AutoMapper将数据库模型映射到域模型(从
DB\u RoleInfo
映射到
DO\u RoleInfo
)。在我的存储库代码中,如下所示:

    public DO_RoleInfo SelectByKey(Guid Key)
    {
        return SelectAll().Where(x => x.Id == Key).SingleOrDefault();
    }

    public IQueryable<DO_RoleInfo> SelectAll()
    {
        Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
        return from role in _ctx.DB_RoleInfo
               select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
    }

此方法按我希望的方式工作。

将第二个函数更改为:

public IEnumerable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return from role in _ctx.DB_RoleInfo.ToList()
           select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}

现在考虑下面的映射:

Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>
    .ForMember(dest => dest.Role, opt => opt.MapFrom(src =>
        (Role)Enum.Parse(typeof(Role), src.Name)));
这实际上是一种工作,但通过称自己为“可查询的”,这是谎言。如果我试着用它来写,会发生什么

public IEnumerable<DO_RoleInfo> SelectSome()
{
    return from ri in SelectAll()
           where (ri.Role == Role.Administrator) ||
                 (ri.Role == Role.Executive)
           select ri;
}
这是一个实用方法,可为您处理映射,并接受原始实体(而不是映射实体)上的筛选器。如果您有许多不同类型的过滤器,但总是需要进行相同的映射,那么它可能会很有用

就个人而言,我认为您最好只是正确地写出查询,首先确定您需要从数据库中检索什么,然后进行任何投影/映射,最后,如果您需要进一步过滤(您不应该这样做),然后使用
ToList()实现结果
ToArray()
并根据本地列表写入更多条件


不要试图使用AutoMapper或任何其他工具来隐藏linqtosql公开的真实实体。域模型是您的公共界面。您编写的查询是私有实现的一个方面。理解差异并保持良好的关注点分离是很重要的。

尽管@Aaronaught在撰写本文时的回答是正确的,因为世界经常发生变化,并因此而改变。同时,代码库中增加了对转换为表达式的投影的支持,最后是对SQL的支持

核心扩展方法是
ProjectTo
1。这就是您的代码的外观:

using AutoMapper.QueryableExtensions;

public IQueryable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return _ctx.DB_RoleInfo.ProjectTo<DO_RoleInfo>();
}


1
Project().To()
在v之前。4.1.0

谢谢您的回答!但是,按照您给出的方式,SelectAll将从DB中检索所有记录。我想享受延迟加载的好处,这意味着应用程序将在SelectByKey中从DB中选择一条记录,而不是在SelectAll中选择所有记录。作为参考,这里有一个相关的API,除了我的答案之外,还有一个关于您的更新的注释:第二个版本可以工作,因为LinqtoSQL已经知道您已经完成了一个不可逆转的投影;
SelectByKey
实际上只是使用Linq来创建对象。如果您检查正在生成的实际查询,我想您会发现它仍然在从数据库中选择所有实体,这相当于使用
ToList()
,然后过滤结果列表。AutoMapper并不支持LINQ。这是因为LINQtoSQL不支持自动映射。LINQtoSQL查询提供程序查看表达式树以确定如何生成SQL查询。当它到达Mapper.Map块时,它不知道如何生成SQL。这个答案应该成为新答案;我收到以下错误“方法'Where'不能跟随方法'Select'或不受支持”。请参阅此处的问题()。请注意,您可能希望将Mapper.CreateMap移出生产代码的此方法。CreateMap只应在应用程序启动时调用一次,因此将所有CreateMap移动到某种引导程序/从应用程序调用\u Start in global.asax是一种方法。最后一行可以是:
SelectAll().SingleOrDefault(x=>x.Id==Key)
public IQueryable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return from role in _ctx.DB_RoleInfo
           select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
public IEnumerable<DO_RoleInfo> SelectSome()
{
    return from ri in SelectAll()
           where (ri.Role == Role.Administrator) ||
                 (ri.Role == Role.Executive)
           select ri;
}
public IEnumerable<DO_RoleInfo> SelectRoles(Func<DB_RoleInfo, bool> selector)
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return _ctx.DB_RoleInfo
        .Where(selector)
        .Select(dbr => Mapper.Map<DB_RoleInfo, DO_RoleInfo>(dbr));
}
using AutoMapper.QueryableExtensions;

public IQueryable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return _ctx.DB_RoleInfo.ProjectTo<DO_RoleInfo>();
}
SelectAll().Where(x => x.Id == Key).SingleOrDefault();