Linq to sql AutoMapper支持Linq吗?
我对具有延迟加载特性的LINQtoSQL非常感兴趣。在我的项目中,我使用AutoMapper将数据库模型映射到域模型(从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
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();