我正在尝试将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
,告诉我不能将System.Data.Entity.Infrastructure.DbQuery<ExposedClass>
强制转换为IQueryable<InternalClass>
,我试图封装IQueryable<ExposedClass>
或表达,但都不起作用,如何解决这个问题?如果有其他解决方法,那是达到我目标的最佳方法?
我的提供程序是EntityFramework6.Npgsql(Nuget程序包)InternalClass
是EF生成的类之一。我先使用数据库。
答案 0 :(得分:0)
首先,不建议这样做。当您的实体更改时,您的DTO必须更改,或者您必须调整它们之间的映射。因此,增加这种额外的复杂性甚至还不是很有用,更不用说付出代价了。
即使您的DTO定义了另一个系统使用的API的数据合同,并且在您开发系统时仍需要维护该API的向后兼容版本,您仍应根据您的实体来实现API方法,并翻译成DTO的“边缘”。您提出的唯一有意义的方案是,如果您具有OData API,并且客户端正在构造查询。
第二,没有任何内置函数可以为您执行表达式翻译。您必须从实体和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