ExpressionVisitor.Visit выбрасывает ошибку "должен быть приводимым узлом" в Visitor Query Service Data

У меня проблема с реализацией шаблона репозитория для моей службы данных WCF. Подводя итог, я пытаюсь использовать шаблон репозитория в клиентском приложении, которое использует подключаемую модель для требуемых репозиториев. Основная проблема заключается в том, что мой интерфейс репозитория IRepository может знать только о варианте типа интерфейса элемента, который он хранит. Это необходимо для отвлечения клиентского приложения от реализации сервиса данных, например

IRepository<IOrder> : IQueryable<T>

В целом, эта концепция работает нормально, пока не включатся Data Services. В настоящее время я использую Data Services v5.4 от NuGet. Если я выполняю такое же простое действие, как ToList(), в моем хранилище, все работает нормально, и перевод превращает результат в список заказов из службы OData. Однако, если я попытаюсь выполнить orderby, выражение запроса станет более сложным и не сможет заполнить возвращаемый тип, поскольку он попытается создать экземпляр варианта интерфейса запрашиваемого типа. т.е. пытается создать экземпляр IOrder вместо Order.

repository.OrderBy(order => order.Id).ToList(); // Fails

На уровне клиента, однако, если я форсирую тип с помощью Cast, он работает...

repository.Cast<Order>(order => order.Id).ToList(); // Suceeds

Очевидно, что это противоречит мантре об отключенных типах, так как мое клиентское приложение должно было бы знать о строгом типе "Заказ" из библиотеки служб данных, которого я хочу избегать на случай, если в будущем я захочу отключить OData.

Затем я наткнулся на класс контекста на стороне клиента службы данных, который позволяет вам получить представление о методах разрешения типов, однако в моем случае по какой-либо причине разрешение никогда не вызывалось.

Впоследствии я начал изучать ExpressionVisitors, который я до сих пор считаю своим билетом из этого беспорядка, который должен быть способен преобразовывать любые параметры IOrder в параметры Order в моем хранилище, чтобы запрос возвращал строгие типы, но продолжал фасад тип интерфейса

При использовании пустой реализации ExpressionVisitor оболочки, например

MyVisitor : ExpressionVisitor

Это прекрасно работает для запросов, не относящихся к службе данных (например, что-то вроде списка как запрашиваемого), но для запросов шаблона репозитория службы данных вы получаете бесполезное (по крайней мере для меня) сообщение "должен быть приводимый узел". Я предполагаю, что посетитель дерева выражений натолкнулся на тип узла, настроенный для запроса к службе данных, и не знает, что с этим делать. Тем не менее, я думал, что ExpressionVisitor просто скопирует то, что было в дереве, если не сказано сделать что-то по-другому?

В любом случае, я спрашиваю, как заменить тип возврата моего запроса с помощью этого ExpressionVisitor с запросами OData? Я попытался найти своего рода посетителя Expression Data Services, но не смог его найти. Я хочу, чтобы моя служба данных на стороне клиента генерировала запрос из запроса типа интерфейса, но возвращала мне строгие типы с тем же именем.

1 ответ

Взгляните на MongOData, это поставщик OData MongoDB, построенный с использованием специального поставщика WCF Data Services:

https://github.com/object/MongOData

Он имеет дело с посетителями выражений как при преобразовании запросов в выражения MongoDB LINQ, так и при преобразовании результатов в DSPResource.

NB! То, что вы пытаетесь достичь, не легко. Но надеюсь, что этот пример помогает.

Другие вопросы по тегам