Конвертировать IQueryable <ExposedClass>в IQueryable <InternalClass> - PullRequest
0 голосов
/ 18 апреля 2019

Я пытаюсь преобразовать 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 голосов
/ 18 апреля 2019

Во-первых, это не очень рекомендуется. Когда ваши сущности меняются, либо ваши DTO должны измениться, либо вы должны настроить соответствие между ними. Так что не очевидно, что добавление этого дополнительного уровня сложности даже полезно, не говоря уже о стоимости.

Даже если ваши DTO определяют контракт данных API, используемого другой системой, и вам необходимо поддерживать обратно-совместимые версии этого API по мере развития вашей системы, вам все равно следует реализовать методы API с точки зрения ваших сущностей, и перевести на DTO "на грани". Единственное scneario, где то, что вы предлагаете, имеет смысл, - это если у вас есть 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

...