我正在尝试将IQueryalbe<ExposedClass>转换为IQueryable<InternalClass>,这样当对.edmx文件进行更改时,我的业务层不会受到直接影响,但可以让它向我发送Linq查询,这样就不会在我的数据访问对象中为每个查询创建一个函数。在我达到这个方法之前,一切都运行得很好:
public ExposedClass Single(IQueryable<ExposedClass> query)
{
// The cast is needed, for some reasons Provider isn't resolved correctly from DbSet
IQueryProvider provider = ((IQueryable)DbContext.SomeGeneratedDbSet).Provider;
IQueryable<ExposedClass> translated = query.WithTranslations();
IQueryable<InternalClass> newQuery = provider.CreateQuery<InternalClass>(translated.Expression);
return new ExposedClass(newQuery.Single());
}当到达provider.CreateQuery时,我得到了一个InvalidCastException,它告诉can't cast System.Data.Entity.Infrastructure.DbQuery<ExposedClass> to IQueryable<InternalClass>我曾试图封装IQueryable<ExposedClass>或它的表达式,但都没有成功,我如何解决这个问题/如果有其他方法,那么实现目标的最佳方法是什么?
我的提供者是EntityFramework6.Npgsql (Nuget包) InternalClass是EF生成的类之一。我首先使用的是数据库。
发布于 2019-04-18 22:03:27
首先,这并不是真正推荐的。当您的实体更改时,要么您的DTO必须更改,要么您必须调整它们之间的映射。因此,增加这层额外的复杂性是否有用并不明显,更不用说值得付出的代价了。
即使您的DTO定义了另一个系统使用的API的数据契约,并且您需要在您的系统发展过程中维护该API的向后兼容版本,那么您仍然应该根据您的实体实现API方法,并将其转换为DTO的“边缘”。如果你有一个OData应用程序接口,并且客户端正在构造查询,那么你所提出的建议是有意义的。
其次,任何内置的东西都不会为您执行表达式转换。您必须从实体和DTO之间的映射开始,不仅在对象实例之间来回投影时使用它,而且在转换查询表达式时也使用它。
看起来AutoMapper也许能帮上忙,请看:
Using EntityFramework as an example
dataContext.OrderLines.UseAsDataSource().For<OrderLineDTO>().Where(dto => dto.Name.StartsWith("A"))http://docs.automapper.org/en/stable/Expression-Translation-(UseAsDataSource).html
https://stackoverflow.com/questions/55744024
复制相似问题