Альтернативы EF Core
От: Vladek Россия Github
Дата: 14.08.17 11:53
Оценка:
Перевёл тут небольшой проект для UWP с бд Sqlite на использование EF Core и получил неэффективные множественные запросы SQL и жуткие тормоза. Колдовство с нафигейшен пропертис, чехарда join-ов в запросах LINQ практически не помогли. Помогли только самописные запросы, но я как раз пытался от этого уйти. Буду возвращаться обратно на sqlite-net-pcl — запросы EF Core выполняющиеся секундами(!) на десктопе, абсолютно неприемлемы.

Какая связка бд/ORM самая быстрая для .NET Core по вашим впечатлениям?
Re: Альтернативы EF Core
От: Danchik Украина  
Дата: 14.08.17 12:10
Оценка: +2 :)
Здравствуйте, Vladek, Вы писали:

V>Перевёл тут небольшой проект для UWP с бд Sqlite на использование EF Core и получил неэффективные множественные запросы SQL и жуткие тормоза. Колдовство с нафигейшен пропертис, чехарда join-ов в запросах LINQ практически не помогли. Помогли только самописные запросы, но я как раз пытался от этого уйти. Буду возвращаться обратно на sqlite-net-pcl — запросы EF Core выполняющиеся секундами(!) на десктопе, абсолютно неприемлемы.


V>Какая связка бд/ORM самая быстрая для .NET Core по вашим впечатлениям?


Linq2db конечно же.
https://github.com/linq2db/linq2db
Re[2]: Альтернативы EF Core
От: Vladek Россия Github
Дата: 14.08.17 13:11
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Linq2db конечно же.

D>https://github.com/linq2db/linq2db

Оттуда посылают сюда: https://www.nuget.org/packages?q=linq2db Вот это https://www.nuget.org/packages/linq2db.SQLite/ — скомпилированного кода не содержит. Дальше разбираться не стал.

Уточню вопрос — ORM должна добавляться в проект с полпинка через нугет и явно поддерживать .NET Core или UWP.
Re[3]: Альтернативы EF Core
От: Слава  
Дата: 14.08.17 14:00
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Оттуда посылают сюда: https://www.nuget.org/packages?q=linq2db Вот это https://www.nuget.org/packages/linq2db.SQLite/ — скомпилированного кода не содержит. Дальше разбираться не стал.

V>Уточню вопрос — ORM должна добавляться в проект с полпинка через нугет и явно поддерживать .NET Core или UWP.

Linq2db добавляется с полпинка через nuget. .NET Core он не поддерживает, насколько я знаю, зато его можно допилить до работоспособного состояния, и это гораздо более простая задача, чем сделать то же самое с EF. Если не нравится — пользуйтесь даппером, ггг.
Re[3]: Альтернативы EF Core
От: IT Россия linq2db.com
Дата: 14.08.17 14:47
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Оттуда посылают сюда: https://www.nuget.org/packages?q=linq2db Вот это https://www.nuget.org/packages/linq2db.SQLite/ — скомпилированного кода не содержит. Дальше разбираться не стал.


Нужно было пробежаться по зависимостям. Либо не умничать, а просто поставить nuget.

V>Уточню вопрос — ORM должна добавляться в проект с полпинка через нугет и явно поддерживать .NET Core или UWP.


И ставится с полпинка и core поддерживается.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Альтернативы EF Core
От: IT Россия linq2db.com
Дата: 14.08.17 14:48
Оценка: 12 (1)
Здравствуйте, Слава, Вы писали:

С>Linq2db добавляется с полпинка через nuget. .NET Core он не поддерживает


Поддерживает.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Альтернативы EF Core
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 14.08.17 18:17
Оценка: :))) :))
Здравствуйте, Danchik, Вы писали:

V>>Какая связка бд/ORM самая быстрая для .NET Core по вашим впечатлениям?


D>Linq2db конечно же.

D>https://github.com/linq2db/linq2db

Да, но как при этом будет выглядеть код использующий linq2db? Этот вопрос почему-то считается второстепенным по сравнению с вопросом производительности. Хотя он очень важный.
Если мне не изменяет память там наружу торчат коллекции объектов. Типа Users, Organizations, Networks. Туда нужно добавлять новые объекты, оттуда забирать нужные. Вопрос авторам. Зачем так ограничевать пользователя linq2db? У ORM есть вся необходимая информация чтобы не вытаскивать это наружу. В этом плане NHibernate сделан очень грамотно. В итоге для NHibernate style мы получаем unitOfWork следующего вида:
public class UnitOfWork
{
    public void Add(Entity object)...
    public Entity Get(int id)
    public Save()
    public Commit()
}

Который может использоваться разными репозиториями без проблем. UserRepository, OrganizationRepository, NetworkRepository все они принимают в конструкторе unitOfWork. А в случае с linq2db они что принимают? Явная завязка на orm не вариант. Хотелось бы свести ее к минимуму.
Отредактировано 14.08.2017 18:20 Nikita Lyapin . Предыдущая версия . Еще …
Отредактировано 14.08.2017 18:19 Nikita Lyapin . Предыдущая версия .
Re: Альтернативы EF Core
От: Tom Россия http://www.RSDN.ru
Дата: 14.08.17 18:43
Оценка:
V>Какая связка бд/ORM самая быстрая для .NET Core по вашим впечатлениям?
Жалко ёжиков
Народная мудрось
всем все никому ничего(с).
Re[3]: Альтернативы EF Core
От: Слава  
Дата: 14.08.17 19:27
Оценка: :)
Здравствуйте, Spinifex, Вы писали:

S>Который может использоваться разными репозиториями без проблем. UserRepository, OrganizationRepository, NetworkRepository все они принимают в конструкторе unitOfWork. А в случае с linq2db они что принимают? Явная завязка на orm не вариант. Хотелось бы свести ее к минимуму.


Я давно хочу узнать, как именно адепты репозиториев предлагают решать вопрос с вьюхами, со сложными запросами. На каждый запрос по отдельному репозу делать?

Вдогонку — никто не мешает взять, и разметить один и тот же набор классов атрибутами и linq2db, и NHibernate. И пользоваться тем или другим — по надобности.
Отредактировано 15.08.2017 6:13 Слава . Предыдущая версия .
Re[3]: Альтернативы EF Core
От: IT Россия linq2db.com
Дата: 15.08.17 04:47
Оценка: 55 (2) +6
Здравствуйте, Spinifex, Вы писали:

S>Если мне не изменяет память там наружу торчат коллекции объектов. Типа Users, Organizations, Networks. Туда нужно добавлять новые объекты, оттуда забирать нужные. Вопрос авторам. Зачем так ограничевать пользователя linq2db?


На это ответ давался уже много раз. Модель данных приложения гораздо стабильней и гораздо менее изменчива, чем объектная модель приложения. Более того, у приложения может быть и как правило обывает много объектных моделей. Описываемый сценарий годен в основном только для редактирования справочников приложения и уж для совсем мелких задач, где в принципе всю модель вообще можно зачитать в самом начале работы приложения и больше не париться с базой.

Обычно приложению в чистом виде сами данные из БД не нужны. Зато часто нужны агрегаты, ad hoc проекции, соединения данных из разных таблиц и т.п. По-этому, linq2db не очень заточен на поддержку всевозможных Entity Services, а больше используется как типизированный SQL.

S>У ORM есть вся необходимая информация чтобы не вытаскивать это наружу. В этом плане NHibernate сделан очень грамотно. В итоге для NHibernate style мы получаем unitOfWork следующего вида:


И хибернейт и UoW уже не раз предавались анафеме и не только здесь на сайте. Персистентность объектной модели приложения привлекательна только паначалу, особенно после просмотра учебных роликов. Жизнь она оказывается немного сложнее.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Альтернативы EF Core
От: Danchik Украина  
Дата: 15.08.17 09:10
Оценка:
Здравствуйте, Spinifex, Вы писали:

[Skip]

S>Который может использоваться разными репозиториями без проблем. UserRepository, OrganizationRepository, NetworkRepository все они принимают в конструкторе unitOfWork. А в случае с linq2db они что принимают? Явная завязка на orm не вариант. Хотелось бы свести ее к минимуму.


Зачем вы мучаете ежиков. Что вам дает репозитроий? Призрачный шанс ВСЕПРОТЕСТИРОВАТЬ?
Все равно вернетесь к модели тестирования на базе — IMHO именно она наиболее близка к идеалу.
О перформансе я вообще молчу, иногда мне кажется что GOF придумали дабы дать разработчикам больше заработать и понаписывать побольше бойлерплейт кода.
Смена ORM? И как часто вы его меняете? Смена базы данных — в энтерпрайзе практически никогда.

И да я вот с этим полностью согласен:
http://www.ben-morris.com/why-the-generic-repository-is-just-a-lazy-anti-pattern/
Re[4]: Альтернативы EF Core
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 15.08.17 15:09
Оценка: +1
Здравствуйте, Danchik, Вы писали:

D>Смена ORM? И как часто вы его меняете?


В любом случае прозрачная смена ORM на реальных проектах все равно невозможна, даже с LINQ. Слишком много специфики.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Альтернативы EF Core
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 15.08.17 18:15
Оценка: +1
Здравствуйте, IT, Вы писали:

S>>У ORM есть вся необходимая информация чтобы не вытаскивать это наружу. В этом плане NHibernate сделан очень грамотно. В итоге для NHibernate style мы получаем unitOfWork следующего вида:


IT>И хибернейт и UoW уже не раз предавались анафеме и не только здесь на сайте. Персистентность объектной модели приложения привлекательна только паначалу, особенно после просмотра учебных роликов. Жизнь она оказывается немного сложнее.


Давайте конкретнее выясним где учебные ролики и реальные проекты имеют косяки.
Возьмем типичную реализацию метода веб сервиса. Предположим у нас метод работает с какими-то там доменными сущностями типа Пользователь. Нужно при создании пользователей создавать какие-то там группы, отправлять некие сообщения, а также оповещать сотрудников на этаже в этой организации что появился новый пользователь. Это все придумано для примера, поэтому не будем вдаваться в подробности.
Что мы в таком случае имеем:

Первым делом это UserWebController который отвечает за работу по http — проверил входные параметры, прописал урл, кинул BadRequest и все на этом. Далее он дергает сервис.
UserService содержит в себе логику по координации вызовов из разных репозиториев. Первым делом он создает транзакцию или сессию или единицу работы здесь названий много.
А также логирование и прочие какие-то обвесы типа отпаравки правильных сообщений в правильные микросервисы.
public sealed class UserService {
...
public void CreateUserInDistributedSystem(...){
    using(var unitOfWork = new UnitOfWork())
    {
        var userRepository = new UserRepository(unitOfWork);
        var messageRepository = new MessageRepository(unitOfWork);
        var organizationRepository = new OrganizationRepository(unitOfWork);
        ...
        if(userRepository.CheckExistanceOfAdminUsers()){
            var adminGroup = userRepositroy.CreateAdminGroup();
            messageRepositroy.SendMessageForGroup(adminGroup, "Welcome message")
        }
        var user = userRepository.CreateAdminUser();
        var usersOnTheFlat = organizationRepository.GetUsersOnTheFlat();
        foreach(var organizationUser in usersOnTheFlat){
            messageRepository.SendMessageForUser(organizationUser, $"{user.Name} was created");
        }
    }

UnitOfWork это во первых транзакция, я всегда могу ее отролбечить, всегда могу из контекста достать данные без обращения в базу. Репозитории содержат в себе логику по доступу к данным. Иногда специфичную для данного ОРМ. Типа QueryOver, желательно Linq (но не всегда это возможно), иногда даже Dapper. Но такие случаи нужно избегать и до последней возможности стараться писать на linq.
Репозитории могут понадобится в других сервисах. Например, получение пользователей для данной организации на данном этаже происходит не только при оповещении о создании нового пользователя, но и при пожарной тревоги.
Отправка сообщений — много где нужна, во многих сервисах. И даже создание пользователя может происходить неявно также во многих случаях.
Таким образом мы имеем четкую структуру. Каждый из классов имеет свою обязанность. Смена ОРМ происходит максимально легко. Конечно это не просто подмена файлика — методы репозиториев и быть может даже сервисов нужно будет переписывать.
Теперь вопрос. Что с этой схемой не так? Как выглядит работа с linq2db? Скорее всего это файл сервиса на 2000 строк где все вперемешку.

P.S. Здесь говорили что менять ОРМ часто не надо. Забавно, но изначальный пост был как раз про это. ОРМ вам нужно поменять, например, при переходе на Core. И вы хотите минимизировать правки.
Отредактировано 15.08.2017 18:30 Nikita Lyapin . Предыдущая версия .
Re[5]: Альтернативы EF Core
От: IT Россия linq2db.com
Дата: 15.08.17 22:51
Оценка: 21 (3) +3 -1
Здравствуйте, Spinifex, Вы писали:

S>Возьмем типичную реализацию метода веб сервиса. Предположим у нас метод работает с какими-то там доменными сущностями типа Пользователь.


Т.е. задача редактирования справочника, вписывается в обозначенные мной сценарии. Вопрос, это приложение только создаёт/редактирует Пользователя или обладает ещё какой-то функциональностью?

S>UnitOfWork это во первых транзакция, я всегда могу ее отролбечить,


И в чём проблема? Транзакции — это святое, это наше всё. Зачем для этого UoW?

S>всегда могу из контекста достать данные без обращения в базу. Репозитории содержат в себе логику по доступу к данным. Иногда специфичную для данного ОРМ. Типа QueryOver, желательно Linq (но не всегда это возможно), иногда даже Dapper. Но такие случаи нужно избегать и до последней возможности стараться писать на linq.


Я без всяких UoW работаю только на Linq. Включая временные таблицы, хинты, bulk copy и прочее. Иногда приходится дописывать свои хелперы типа на отключение констрейнов, но это мелочи и разовая работа.

S>Репозитории могут понадобится в других сервисах. Например, получение пользователей для данной организации на данном этаже происходит не только при оповещении о создании нового пользователя, но и при пожарной тревоги.


Техники повторного использования кода вообще-то никто не отменял. Это всё можно сделать массой разных способов. Да и сам репозиторий как паттерн вполне можно использовать без UoW.

S>Отправка сообщений — много где нужна, во многих сервисах. И даже создание пользователя может происходить неявно также во многих случаях.


Техники повторного использования кода. UoW здесь вовсе не панацея.

S>Таким образом мы имеем четкую структуру. Каждый из классов имеет свою обязанность. Смена ОРМ происходит максимально легко. Конечно это не просто подмена файлика — методы репозиториев и быть может даже сервисов нужно будет переписывать.


И сколько раз в своей жизни ты менял ОРМ в своих проектах? Только честно.

S>Теперь вопрос. Что с этой схемой не так? Как выглядит работа с linq2db? Скорее всего это файл сервиса на 2000 строк где все вперемешку.


Это зависит от задачи. Бывает, что 2000 строк это не предел. Бизнес логика — она такая бизнес логика. Если нужно написать кода на 2000 строк, то здесь не поможет никакой UoW.

S>P.S. Здесь говорили что менять ОРМ часто не надо. Забавно, но изначальный пост был как раз про это. ОРМ вам нужно поменять, например, при переходе на Core. И вы хотите минимизировать правки.


linq2db позволяет менять не только Core, но даже БД без изменения кода бизнес логики. Это вообще как бы не вопрос. И, кстати, Core — это не ОРМ, это фреймворк.

В общем, я в очередной раз не понял зачем нужен UoW.

Есть ещё один философский момент. Все эти UoW, Entity Services, Persistence и прочее, всё это от лукавого. Если хочется работать с базой данных эффективно и надёжно, без гемороя и сайд эффектов, то с базой данных нужно работать именно как с базой данных. Любые попытки поставить между базой и кодом магический щит в виде UoW и прочей дребедени заканчивается очень быстро и наступает жестокое разочарование.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Альтернативы EF Core
От: SergASh  
Дата: 16.08.17 07:23
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>Я без всяких UoW работаю только на Linq. Включая временные таблицы, хинты, bulk copy и прочее. Иногда приходится дописывать свои хелперы типа на отключение констрейнов, но это мелочи и разовая работа.


Spinifex не поленился и привел пусть и схематичный, но все же пример. Можете показать как при вашем способе это выглядит на практике?
Re[7]: Альтернативы EF Core
От: Danchik Украина  
Дата: 16.08.17 14:21
Оценка: 73 (2) :)
Здравствуйте, SergASh, Вы писали:

SAS>Здравствуйте, IT, Вы писали:


IT>>Я без всяких UoW работаю только на Linq. Включая временные таблицы, хинты, bulk copy и прочее. Иногда приходится дописывать свои хелперы типа на отключение констрейнов, но это мелочи и разовая работа.


SAS>Spinifex не поленился и привел пусть и схематичный, но все же пример. Можете показать как при вашем способе это выглядит на практике?


Не буду утверждать за Игоря, но мой дизайн выглядел бы так. Некоторая гибкость в замене ORM теряется, зато скорость разработки подымается в разы.
Заменять коня на переправе никто не будет. Сейчас главное чтобы продукт вовремя попал на рынок.
Для тестирования сервисов я бы использовал функциональное тестирование — эталонная база, с тестовыми данными, котора в CI подымается с бакапа.
Если уж времени совсем вагон — замокать свои имплементации.


Pros

Cons
Re[7]: Альтернативы EF Core
От: IT Россия linq2db.com
Дата: 16.08.17 15:43
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Spinifex не поленился и привел пусть и схематичный, но все же пример. Можете показать как при вашем способе это выглядит на практике?


@Danchik пример уже привел, за что ему большое спасибо. Но на самом деле это выглядит как типизированный SQL. Т.е. любой подход/отход, паттерн/шматтерн, но только вместо SQL — LINQ. Вот и вся разница.
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Альтернативы EF Core
От: sergeya Ниоткуда http://blogtani.ru
Дата: 16.08.17 22:46
Оценка: 18 (1) +1
Привет!

SAS>Spinifex не поленился и привел пусть и схематичный, но все же пример. Можете показать как при вашем способе это выглядит на практике?


Не увидел в примере специфики, завязанной на возможности EF. Его можно повторить на linq2db строка в строку.
Заменить unitOfWork на dataConnection (можно даже назвние прежнее оставить) и код будет совпадать один в один.
Только под капотом у репозиториев будет не EF а linq2db.

Примерный код репозитория:

class OrganizationRepository 
{
    DbNorthwind _db;
    public OrganizationRepository(DbNorthwind dataConnection)
    {
        _db = dataConnection;
    }

    public void Commit()
    {
        _db.Commit();
    }

    public void Rollback() { ... }

    public void BeginTransaction() { ... }

    public List<User> GetUsersOnTheFlat(int flat) 
    {
        return _db.User
            .Where(u => u.Room.Flat == flat)
            .ToList();
    }
}


S>... всегда могу из контекста достать данные без обращения в базу ...


Не всегда, а только если их туда предварительно положить.
И если репозиторий рассчитывает на данные из unitOfWork, то это означает появление неявного контракта со всеми вытекающими неприятностями.
Можно неосторожно забить на сложность получения данных из БД в надежде, что данные уже лежат в контексте. И получить сюрприз, когда сервис будет вызван в другом сценарии.
По мне так надежнее передавать данные между сервисами в явном виде. А если нужен долговременный кэш, то реализовать его в виде специального сервиса.

Подход с кэшированием в unitOfWork хорошо работает на учебных примерах с простыми плоскими моделями.
В реальной жизни появляются сложные развесистые документы, и внезапно оказывается, что разным сервисам нужны разные проекции одного и того же документа.
Сервису рассылки — email, а сервису начисления зарплаты — должность пользователя.
И данные, закешированные одним сервисом, не подойдут для другого.

Поэтому считаю, что в unitOfWork вместо метода Get(id), возвращающего материализованную проекцию, должен торчать IQueryable интерфейс к БД.

Кстати, вызов GetUsersOnTheFlat только для того, чтобы вытащить из базы email пользователей тоже выглядит оверхеадом.
У меня бы метод рассылки уведомлений требовал бы на входе только id пользователя, и сам вытаскивал бы по этому id из БД только данные, необходимые для выполнения рассылки.
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[8]: Альтернативы EF Core
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 17.08.17 17:24
Оценка:
Уже гораздо лучше, чем у @Danchik. Самое главное автору данного кода пришло осознание, что запрос GetUsersOnTheFlat может встречаться более чем в одном сервисе. И нужно куда-то его вынести, чтобы не делать copy/past.
Repository как раз для этого и предназначен.
Причем этот запрос гораздо более сложный может быть c джойнами на организацию, на здание, на информацию по зданию и т.п.
Остался вопрос относительно функций Commit(), Rollback(), BeginTransaction(). Им в репозитории совсем не место. Опять же если вы обратитесь к моему примеру у меня в методе сервиса использовалось 3 репозитория. Чей в таком случае Rollback вызывать? А Commmit? Понятно что для вашего кода это без разницы. Но дизайн кода... Что должен думать программист его использующий?
Хорошо бы вынести эти функции в какой-то класс, который абстрагирует нас от DbNorthwind заодно. Но в случае с linq2db это сделать проблематично, т.к. там торчат наружу коллекции сущностей. Зачем-то. Нафига? Никто не знает ответа. Даже автор.
Поэтому в сервисах будет DbNorthwind и меньший уровень абстракции, чем мог бы быть.

P.S. Обратите внимание как @Danchik был вынужден упростить код моей функции. У него простая вставка в User. В то время как у меня была работа с тремя репозиториями. Это как бы намекает какой из подходов используется в реальных боевых проектах, а какой в учебных.
Отредактировано 17.08.2017 19:11 Nikita Lyapin . Предыдущая версия . Еще …
Отредактировано 17.08.2017 18:39 Nikita Lyapin . Предыдущая версия .
Отредактировано 17.08.2017 17:24 Nikita Lyapin . Предыдущая версия .
Re[9]: Альтернативы EF Core
От: sergeya Ниоткуда http://blogtani.ru
Дата: 17.08.17 19:13
Оценка: +1
Здравствуйте, Spinifex, Вы писали:

S>Уже гораздо лучше, чем у @Danchik. Самое главное автору данного кода пришло осознание, что запрос GetUsersOnTheFlat может встречаться более чем в одном сервисе. И нужно куда-то его вынести, чтобы не делать copy/past.

S>Repository как раз для этого и предназначен.
S>Причем в моем представлении этот запрос гораздо более сложный может быть c джойнами на организацию, на здание, на информацию по зданию и т.п.

Ты неправильно мня понял. Я как раз против универсального GetUsersOnTheFlat. Одно дело, когда нужно получить список пользователей на этаже для того, чтобы отправить им почтовое уведомление, а другое дело, когда нужно начислить им компенсацию за не работающий лифт. Или уволить всех скопом.

Если сделать универсальный метод, возвращающий коллекцию пользователей с полным набором атрибутов, то работать он будет везде неэффективно.

С linq2db можно не бояться джоинов, поскольку он автоматически генерирует схему, включающую и описания таблиц, и связи между ними для легкой навигации parent->child и обратно.
И тогда джоин на здание или организацию будет выполняться простым обращением к свойству.

_db.User.Select(u => new { StreetName = u.Room.Building.Street.Name, OrgName = u.Organization.Name })


S>Остался вопрос относительно функций Commit(), Rollback(), BeginTransaction(). Им в репозитории совсем не место. Опять же если вы обратитесь к моему примеру у меня в методе сервиса использовалось 3 репозитория. Чей в таком случае Rollback вызывать? А Commmit. Понятно что для вашего кода это без разницы. Но дизайн кода, что должен думать программист его использующий?

S>Хорошо бы вынести эти функции в какой-то класс, который абстрагирует нас от DbNorthwind заодно. Но в случае с linq2db это сделать проблематично, т.к. там торчат наружу коллекции сущностей. Зачем-то. Нафига? Никто не знает ответа. Даже автор.

Да, единый коммит и роллбэк будут выполняться через DbNorthwind.
Торчат наружу не коллекции, а IQueriable интерфейсы к таблицам, что позволяет гибко извлекать ровно те данные, которые нужны для конкретного сервиса.

S>Поэтому в сервисах будет DbNorthwind и меньший уровень абстракции, чем мог бы быть.


Ты знаешь, для меня меньший уровень абстракции к СУБД — это большой плюс.
Для меня ORM должна быть тонким типизованным фасадом к данным, а не абстракцией.

Главное — типизация и возможность декомпозиции и реюза запросов.
А уж поверх этого я и абстракцию (какая именно мне нужна) прикручу и все прочее.

И чтобы два раза не вставать, вот пример декомпозиции, позволяющий реюзать фильтр пользователей по этажу.

IQueryable<UserModel> ApplyFilterByFlat(IQueryable<UserModel> source, int flat)
{
    return source.Where(u => u.Room.Flat == flat);
}


Теперь этот предикат можно переиспользовать множество раз, комбинируя с другими условиями. И без copy-paste.

А если подключить LinqKIT, то декомпозировать и переиспользовать можно не только условия выборки, но и составные части проекции.
Я имею ввиду фичу AsExpandable (детали здесь — http://www.albahari.com/nutshell/linqkit.aspx и http://tomasp.net/blog/linq-expand.aspx)

Кстати, давно хочу попросить Игоря IT включить эту фичу в linq2db. С тех пор как нашел ее, использую во всех проектах.
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.