Интересная на мой взгляд задача… Допустим у нас есть клиенты и сервер, общающиеся по WCF. Мы не хотим на клиентах деплоить сборки NHibernate и всего что с ним связано (в случае например, если клиенты написаны на Silverlight — это очень актуально), однако хотим воспользоваться некоторыми видами запросов с клиентской стороны (типа Criteria в Nhibernate).
Как к этому подступиться?
Попробуем разобраться по порядку. NHibernate устроен так, что создает прокси-объекты в пределах сессии, эти прокси объекты конечно же нельзя передавать через DataContract (так как они в принципе не помечены DataContractAttribute). Прокси нужны нам для того, чтобы разрешить ленивую загрузки, и тп. Это проблема номер раз… Вывод — запретить прокси (default-lazy = false). Как показывает практика, даже при запрещении default-lazy, прокси все равно создаются. Кроме того NHibernate использует специализированные типы для хранения коллекций, такие как GenericBag и т.п. Это добро тоже не может передаваться в WCF канал.
Сделав такие выводы, я было очень сильно огорчился и хотел уже переходить на EF 😉
Видимо скоро я так и поступлю (но по другим соображениям), однако данная статья направлена на то, чтобы подтолкнуть нас на правильную мысль.
Сейчас хочу лишь сказать, что вышеуказанную проблему можно решить и об этом будет другая статья.
Вторая проблема, о которой я здесь скажу — специализированные запросы с критериями и условиями (Criteria). Я захотел сделать здесь более универсальную возможность и прикрутить к NHibernate старый добрый LINQ, потому как LINQ есть LINQ 😉
Но:
1) LINQ — язык выражений (класс Expression), которые нельзя сериализировать штатным способом.
2) NHibernate в настоящий момент не поддерживает LINQ.
Второй минус решился использованием NHContrib — в которой есть либа LINQ2NHibernate (УРА!!)
Первый минус — решается использованием Dynamic LINQ. Выражение на клиенте записывается в строку, а затем на сервере — парсится специальным классом.
Отлично. Еще один нюанс, на который стоит обратить внимание — использование generic’ов. Как вы знаете, в WCF есть ограничение на этот счет. Как здесь поступить? Ответ: пользоваться классом NetDataContractSerializer для сериализациидесериаоизации тела сообщения.
Ну в общем то вот такие вот перед нами стоят проблемы, будем решать их по порядку 😉
Продолжение следует…