将IQueryable <exposedclass>转换为IQueryable <internalclass>

时间:2019-04-18 10:23:27

标签: c# entity-framework linq entity-framework-6 npgsql

我正在尝试将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生成的类之一。我先使用数据库。

1 个答案:

答案 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