Рефакторим и переписываем на .NET большой проект. Встаёт дилема/проблема выбора framework-а для работы с данными.
Основная концепция — это разумная автоматизация. Я не хочу делать всё руками, но и не хочу отказываться от стор и написания TSQL кода.
Я для себя набросал некоторые требования к нашему DAL Framework. Может многоуважаемый ALL посоветует какое то готовое решение.
Ну и просто мысли и замечания — велкам. Ответы желательно максимально конкретизировать и избежать обсуждения "сферического коня в вакууме".
DAL Framework должен:
1. Позволять генерировать C# wrapper-ы для
1.1. Вызова хранимых процедур, при этом если хранимая процедура возвращает resultset, то entity класс так же должен быть сгенерирован
1.2. Таблиц/View (CRUD), при этом очень желательно что бы при помощи сгенерированного класса можно было бы обновить как одно или несколько полей, так и все поля
1.3. Custom запросов (не хранимых процедур).
Например мы хотим сделать некоторый select, но нехотим делать хранимую процедуру, при этом мы хотим, что бы entity сгенерировалась DAL Framework-ом автоматически, по полям выборки
1.3. Сгенерированный DAL должен нормально поддерживать транзакционность
Тоесть, должна быть возможность например обновить несколько таблиц и вызвать стору в одной транзакции без использования TransactionScope
Не хочется для одной транзакции использовать несколько соединений с БД, например из за увеличения риска дедлоков
1.4. Сгенерированные entity классы должны легко сериализовываться в XML
1.5. Сгенерированные entity классы должны легко передаваться по WCF
1.6. Сгенерированные entity классы должны быть disconnected от базы
1.7. Чем проще будут сгенерированные entity классы — тем лучше. Естественно, что POCO буде идеалом
1.8. Естественно все сгенерированные классы должны быть Partial
1.9. Гибкое управление (возможность контролировать) сгенерированным C# кодом будет большим плюсом
1.10 Гибкое управление (возможность контролировать) сгенерированным TSQL кодом будет большим плюсом
2. Должна быть возможность генерировать (или обновлять уже существующий) DAL по базе во время билда, а не только из студии или какой либо утилиты
Нужно что бы сгенерированный DAL всегда был бы up to date и иметь compile time проверки
3. В идеале должен быть хорошо поддерживаемым комерческим продуктом, ещё лучше если будут доступны исходники
4. В идеале должен быть заточен, или очень хорошо понимать MS SQL 2005/2008
DAL Framework НЕ должен:
1. Быть полноценным ORM с поддержкой связей, коллекций, многоуровневых внутренних кэшэй и прочей "тяжеловесной" ерунды с которой в будущем придётся бороться
2. Не должен заменять SQL своим языком, или уж если и заменяет то это должна быть полная/полноценная поддержка TSQL 2005/TSQL 2008
Писать велосипед не предлагать
Во флэйм не пускаться
Как я понял нужен просто data mapper и генерилка POCO и маппингов. Как маппер можно использовать iBatis, BLToolkit даже NHibernate не заставляет тебя использовать больше его возможностей чем требуется. Осталось выбрать генерилку маппингов и сущностей по схеме базы. MyGeneration, CodeSmith, ddl2hbm.
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, Tom, Вы писали:
Tom>>Рефакторим и переписываем на .NET большой проект. Встаёт дилема/проблема выбора framework-а для работы с данными.
B>У вас не возникало желания снять с себя весь этот геморрой с бизнес- и сервис-слоями и транспортом, и взять какую-нить ERP-систему?
И получить геморрой в виде ERP-системы %) (Я внедрял несколько, так что знаком не понаслышке)
Здравствуйте, Tom, Вы писали:
Tom>Рефакторим и переписываем на .NET большой проект. Встаёт дилема/проблема выбора framework-а для работы с данными. Tom>Основная концепция — это разумная автоматизация. Я не хочу делать всё руками, но и не хочу отказываться от стор и написания TSQL кода. Tom>Я для себя набросал некоторые требования к нашему DAL Framework. Может многоуважаемый ALL посоветует какое то готовое решение. Tom>Ну и просто мысли и замечания — велкам. Ответы желательно максимально конкретизировать и избежать обсуждения "сферического коня в вакууме".
Для ескольких последник проектов использовал LLBLGen Pro.
Tom>DAL Framework должен: Tom>1. Позволять генерировать C# wrapper-ы для Tom>1.1. Вызова хранимых процедур, при этом если хранимая процедура возвращает resultset, то entity класс так же должен быть сгенерирован
Генерируются wrapper-ы для хранимых процедур. Автоматически определяется, какие процедуры возвращают resultset, какие нет. Для процедур, возвращающих resultset,
результат возвращается в виде DataSet. Entity-класс для этих случаев не генерируется, так как это невозможно сделать в принципе.
Tom>1.2. Таблиц/View (CRUD), при этом очень желательно что бы при помощи сгенерированного класса можно было бы обновить как одно или несколько полей, так и все поля
Генерируются классы как для таблиц, так и для представлений.
Tom>1.3. Custom запросов (не хранимых процедур). Tom>Например мы хотим сделать некоторый select, но не хотим делать хранимую процедуру, при этом мы хотим, что бы entity сгенерировалась DAL Framework-ом автоматически, по полям выборки
Кажется, эта возможность есть и называется Typed View (точно не знаю).
Tom>1.3. Сгенерированный DAL должен нормально поддерживать транзакционность Tom>Тоесть, должна быть возможность например обновить несколько таблиц и вызвать стору в одной транзакции без использования TransactionScope
Да
Tom>Не хочется для одной транзакции использовать несколько соединений с БД, например из за увеличения риска дедлоков Tom>1.4. Сгенерированные entity классы должны легко сериализовываться в XML
Да
Tom>1.5. Сгенерированные entity классы должны легко передаваться по WCF
Точно не знаю, кажется, в последней версии это реализовано.
Tom>1.6. Сгенерированные entity классы должны быть disconnected от базы
Да.
Tom>1.7. Чем проще будут сгенерированные entity классы — тем лучше. Естественно, что POCO буде идеалом
Не знаю, что такое POCO. Можно генерировать классы в двух режимах:
1. Self-servicing — классы содержат данные + всю логику для их чтения из БД,
обработки и сохранения в БД.
2. Adapter — классы содержат только данные. Обработка данных осуществяется отдельными классами.
Tom>1.8. Естественно все сгенерированные классы должны быть Partial
Да
Tom>1.9. Гибкое управление (возможность контролировать) сгенерированным C# кодом будет большим плюсом
Можно создавать свои шаблоны для генерации C#-классов.
Tom>1.10 Гибкое управление (возможность контролировать) сгенерированным TSQL кодом будет большим плюсом
TSQL-код генерируется динамически в процессе работы. Насчет управления процессом его генерации точно не знаю.
Tom>2. Должна быть возможность генерировать (или обновлять уже существующий) DAL по базе во время билда, а не только из студии или какой либо утилиты.
Проект для DAL создается вручную при помощи программы-дизайнера. Впоследствии, при изменении структуры БД его можно обновлять либо вручную, либо про помощи утилиты Cli refresher, работающей из командной строки (я ей не пользовался).
Tom>Нужно что бы сгенерированный DAL всегда был бы up to date и иметь compile time проверки
Наверное, это можно реализовать при помощи cli refresher.
Tom>3. В идеале должен быть хорошо поддерживаемым комерческим продуктом, ещё лучше если будут доступны исходники
Да
Tom>4. В идеале должен быть заточен, или очень хорошо понимать MS SQL 2005/2008
Да
Tom>DAL Framework НЕ должен: Tom>1. Быть полноценным ORM с поддержкой связей, коллекций, многоуровневых внутренних кэшэй и прочей "тяжеловесной" ерунды с которой в будущем придётся бороться
Поддержка связей и коллекций присутствует.
Tom>2. Не должен заменять SQL своим языком, или уж если и заменяет то это должна быть полная/полноценная поддержка TSQL 2005/TSQL 2008
Своего языка нет. Структура генерируемых классов полностью определяется структурой БД.
Дополнительные возможности:
— Загрузка данных по умолчанию lazy, но можно гибко сконфигурировать, какие данные должны загружаться сразу.
— Возможность чтения графа объектов на один раз.
— Поддержка наследования сущностей в БД
— Настройка преобразования типов данных БД в типы данных C# и обратно (это важно в основном при работе с Oracle).
Спасибо!
FD>Генерируются wrapper-ы для хранимых процедур. Автоматически определяется, какие процедуры возвращают resultset, какие нет. Для процедур, возвращающих resultset, FD>результат возвращается в виде DataSet. Entity-класс для этих случаев не генерируется, так как это невозможно сделать в принципе.
Не то что бы невозможно, но иногда невозможно или нетривиально. Linq2Sql генерит энтити по умолчанию и без особых проблем.
B>У вас не возникало желания снять с себя весь этот геморрой с бизнес- и сервис-слоями и транспортом, и взять какую-нить ERP-систему?
Этот вариант не рассматривается в принципе
Z>Как я понял нужен просто data mapper и генерилка POCO и маппингов. Как маппер можно использовать iBatis, BLToolkit даже NHibernate не заставляет тебя использовать больше его возможностей чем требуется. Осталось выбрать генерилку маппингов и сущностей по схеме базы. MyGeneration, CodeSmith, ddl2hbm.
Спасибо, я как то сразу и не догадался что в принципе это разные вещи. Однако лучше конечно интегрированное решение.
Здравствуйте, Tom, Вы писали:
Tom>Спасибо, я как то сразу и не догадался что в принципе это разные вещи. Однако лучше конечно интегрированное решение.
Скорее всего все интегрированные решения будут накладывать ограничения несовместимые с требованиями. Как минимум генерить они будут только под свой ORM, а все коммерческие ORM жутко навороченны на мой взгляд. Всетаки с такими четкими критериями придется много тюнить, а интегрированные решения с очень большой вероятностью не позволят это делать.
Z>Скорее всего все интегрированные решения будут накладывать ограничения несовместимые с требованиями. Как минимум генерить они будут только под свой ORM, а все коммерческие ORM жутко навороченны на мой взгляд. Всетаки с такими четкими критериями придется много тюнить, а интегрированные решения с очень большой вероятностью не позволят это делать.
Вот вот, по этому в идеале то что генерится — должно настраиваться. Шаблонами
Здравствуйте, Tom, Вы писали:
Tom>Спасибо!
FD>>Генерируются wrapper-ы для хранимых процедур. Автоматически определяется, какие процедуры возвращают resultset, какие нет. Для процедур, возвращающих resultset, FD>>результат возвращается в виде DataSet. Entity-класс для этих случаев не генерируется, так как это невозможно сделать в принципе. Tom>Не то что бы невозможно, но иногда невозможно или нетривиально. Linq2Sql генерит энтити по умолчанию и без особых проблем.
Мы говорим об SQL Server ? В этом случае сгенерировать Entity-класс для результата храномой процедуры невозможно, так как структура возвращаемого хранимой процедурой resultset определяется динамически в процессе вызова процедуры. И resultset может быть разным в зависимости от логики процедуры. Например, в приведенном примере хранимая процедура может возвращать результат одного из двух типов:
create procedure person_or_company(@flag bit)
as
begin
if @flag = 1
select * from Person
else
select * from Company
end
Не говоря уже о таком примере:
create procedure proc_with_different_result_sets(@select nvarchar(4000))
as
begin
exec dbo.sp_executesql @select
end
Или, может быть, ты имеешь в виду результат, возвращаемый функцией типа table-valued ? В таком случае структура результата известна и Entity-класс сгенерировать можно.
Здравствуйте, Flying Dutchman, Вы писали:
FD>>>Генерируются wrapper-ы для хранимых процедур. Автоматически определяется, какие процедуры возвращают resultset, какие нет. Для процедур, возвращающих resultset, FD>>>результат возвращается в виде DataSet. Entity-класс для этих случаев не генерируется, так как это невозможно сделать в принципе. Tom>>Не то что бы невозможно, но иногда невозможно или нетривиально. Linq2Sql генерит энтити по умолчанию и без особых проблем.
FD>Мы говорим об SQL Server ? В этом случае сгенерировать Entity-класс для результата храномой процедуры невозможно, так как структура возвращаемого хранимой процедурой resultset определяется динамически в процессе вызова процедуры.
Можно генерировать для тех процедур, у которых структура resultset статична.
Например, Codesmith чтобы определить resultset процедуры запускает процедуру
с параметрами по умолчанию, нам этого хватало в 90% случаев.
Я бы отмел те фреймворки которые обязывают завязывать классы данных на себя, наследованием от их объекта например. XPO, CSLA.Net, Net tiers(?). Объекты которые подобно Мюнхгаузену вытаскивают себя из базы и сохраняют обратно (ActiveRecord) это антипаттерн, который допустим лишь для быстрой разработки простых приложений. Кстати, почему в списке нет iBatis? Довольно простой и прозрачный для программиста маппер.
Здравствуйте, achmed, Вы писали:
A>Здравствуйте, Flying Dutchman, Вы писали:
FD>>Мы говорим об SQL Server ? В этом случае сгенерировать Entity-класс для результата храномой процедуры невозможно, так как структура возвращаемого хранимой процедурой resultset определяется динамически в процессе вызова процедуры.
A>Можно генерировать для тех процедур, у которых структура resultset статична. A>Например, Codesmith чтобы определить resultset процедуры запускает процедуру A>с параметрами по умолчанию, нам этого хватало в 90% случаев.
Я бы в этом случае использовал функции типа table-valued вместо хранимых процедур. Для них тип resultset известен.
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, Tom, Вы писали:
Z>Я бы отмел те фреймворки которые обязывают завязывать классы данных на себя, наследованием от их объекта например. XPO, CSLA.Net, Net tiers(?). Объекты которые подобно Мюнхгаузену вытаскивают себя из базы и сохраняют обратно (ActiveRecord) это антипаттерн, который допустим лишь для быстрой разработки простых приложений. Кстати, почему в списке нет iBatis? Довольно простой и прозрачный для программиста маппер.
Да, абсолютно согласен, ещё я хочу отмести тех кто не позволяет гибко управлять генерацией C#/SQL. И тех у кого нет будущего. Тоесть Linq2Sql/EF тоже похоже уходят. По крайней мере Linq2Sql на 90% отметается
FD>Я бы в этом случае использовал функции типа table-valued вместо хранимых процедур. Для них тип resultset известен.
В чём приймущестово, можно пояснить, я чессно говоря просто не вкурсе что это такое.