在 IQueryable 的 Select 中调用 DTO 转换器
我有以下代码来查询 EntityContext(通过存储库)并将其映射到 DTO:
public class QueryQuestionsConsumer : IConsumerOf<QueryQuestionsRequest>
{
public void Consume(QueryQuestionsRequest request)
{
var repo = IoC.Resolve<IUnitOfWork>().CreateRepository<Question>();
var filter = FilterTranslator.CreateFilterExpression<Question>(request.Filters);
var questions = repo
.GetAll()
.Where(filter)
Result = questions.Select(question => QuestionTranslator.ToDTO(question)).ToArray()
}
}
这显然会失败,因为 ToDTO() 不是 EntityFramework 提供程序中可识别的函数。我可以使用对象初始值设定项创建 DTO 对象,但我想将其委托给另一个类 (QuestionTranslator)。
在这种情况下你会做什么?
更新: 此外,我不想通过水化完整的问题对象来做到这一点。我希望依靠 Provider 创建 DTO 对象的能力。
I have the following code to query an EntityContext (through a repository) and map it unto a DTO:
public class QueryQuestionsConsumer : IConsumerOf<QueryQuestionsRequest>
{
public void Consume(QueryQuestionsRequest request)
{
var repo = IoC.Resolve<IUnitOfWork>().CreateRepository<Question>();
var filter = FilterTranslator.CreateFilterExpression<Question>(request.Filters);
var questions = repo
.GetAll()
.Where(filter)
Result = questions.Select(question => QuestionTranslator.ToDTO(question)).ToArray()
}
}
This would obviously fail because ToDTO() isn't a recognized function in EntityFramework provider. I could create a DTO object using an object initializer but I'd like to delegate it to another class (QuestionTranslator).
What do you do in this case?
UPDATED:
Additionally, I don't want to hydrate a full Question Object to do that. I'd like to count on Provider's ability to create DTO objects.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
除了使用
questions.AsEnumerable().Select(...)
强制 EF 检索完整记录然后将它们映射到客户端的明显选项之外,您还可以使 ToDTO 方法返回一个表达式:Besides the obvious option of using
questions.AsEnumerable().Select(...)
to force EF to retrieve full records and then mapping them client side, you can make your ToDTO method return an expression:您可以将其转换为可枚举,然后在本地进行翻译:
这将导致查询被转换为(本地)可枚举,这样它就可以安全地通过您的
QuestionTranslator
传递。You can convert it to an enumerable, then translate it locally:
This will cause the query to be converted to a (local) enumerable, where it can be safely passed through your
QuestionTranslator
.有一个很棒的博客系列解释了如何在不强制评估查询的情况下实现此类功能。它基本上依赖于实现
IQueryProvider
。这不是一项简单的任务,以下链接提供了构建一个很好的案例研究。 http://blogs.msdn.com/b /mattwar/archive/2008/11/18/linq-links.aspxThere is a great blog series that explains how to implement this type of functionality without force-evaluating the query. It basically relies on implementing an
IQueryProvider
. This is not a trivial task, and the following link gives a great case study of building one. http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx我使用 AutoMapper 从实体映射到 DTO,因为如果您为
Question
创建映射,那么它将自动知道如何映射IEnumerable
执行这两个查询的问题一个语句中的映射是,当发生不好的事情时,它往往会导致您的数据映射器抛出难以破译的错误(很难判断问题是在查询执行中还是在映射中)
我发现遵循“fire”要容易得多“通过执行
.ToList()/.AsEnumerable()
等查询,然后将该变量传递给映射器。这使得出现问题时异常情况能够非常清晰,明确问题是出在查询中还是映射中。I use AutoMapper to map from entities to DTO's because if you create a Mapping for
Question
then it will automatically know how to MapIEnumerable<Question>
The problem with doing both the query and mapping in one statement is that it tends to cause your datamapper to throw hard to decipher errors when bad things happen (hard to tell if the problem was in the query execution or in the mapping)
I found it much easier to follow to "fire" the query by doing a
.ToList()/.AsEnumerable()
etc, and then pass that variable to the mapper. This allows the exceptions to be very clear when problems occur, making it clear whether the problem was in the query or in the mapping.请参阅这篇文章:自动投影 LINQ 查询。
当您使用它时,您将查询如下:
如果使用 NHibernate/EF,则应该在服务器上发生(发送到数据库的查询将仅具有预计的属性)。仍应针对内存中已有的对象正常工作(LINQ To Objects)。
See this post: Autoprojecting LINQ queries.
When you use it, you'll query will be like:
Should happen on the server if using NHibernate/EF (the query sent to DB will only have the projected properties). Should still work normally against objects alread in memory (LINQ To Objects).