if (_services[serviceType] is not null)
{
return _services[serviceType]!.Invoke(this);
}
// The piece of code above can be replaced with
if (_services[serviceType] is {} service)
{
return service.Invoke(this);
}
Будет здорово когда/если ковариантные возвращаемые типы будут реализованы. С ними можно избавиться от перекрытия через new. Пока имеем, что имеем.
Способ на самом деле удобный. Кажется, что ковариантные возвращаемые значения все-равно не спасут, потому что у свойства еще сеттер есть. Его вроде можно сделать private/protected, если кроме EF Core никто не будет его использовать.
Насчет структуры хранения авторов, согласен, еще проблемы возникнут, когда авторы будут начинаться на одну букву, но моей целью не было создание приложения для чтения стихотворений в консоли, спасибо за развернутый комментарий
Я разбирался как работает elmish, изучил исходный код, убрал из него все, что было излишним для моих задач и написал приложение, чтобы закрепить понимание, как там все устроено, разумеется в разработке я использую elmish, а не мою облегченную модификацию
Это не очень хорошее решение, работа с асинхронным кодом отличается даже на уровне компилятора. Поэтому не стоит объединять это под одним интерфейсом, интерфейс должен быть явным. Да и каждый раз оборачивать возвращаемое значение IQuery в Task ужасно.
Написать один раз вот так легче:
public interface IAsyncQuery<TIn, TOut>: IQuery<TIn, Task<TOut>
{
}
Одна из задач Queryable Provider'a транслировать запрос из Expression Tree(который строится, когда вы пишете LINQ к интерфейсу IQueryable) в SQL и делать запрос к базе данных.
Но тут есть проблемы:
1) Не весь LINQ будет транслирован в Expression Tree, например такой не будет:
2) LINQ который удастся транслировать в Expression Tree, может быть не транслируем в SQL, в таких случаях EF Core 2.1 сделает запрос к базе данных с тем SQL запросом, который смог транслировать, а остальное обработает в памяти, но это поведение можно переопределить и он станет падать каждый раз, когда не может полностью разобрать Expression Tree.
Кстати ReSharper выделяет самые очевидные «проблемные» места запроса.
Я не думаю, что можно переопределить штатный провайдер, вы можете написать обертку для IQueryable которая при вызове ToList/First/Count/… будет переписывать оригинальный Expression, и в этой обертке добавлять часть общих бизнес правил, если тема представляет интерес, сделаю статью, потому что в реализации есть подводные камни
Немножко вброшу про различные возможности проверки на null в современном C# ;)
sharplab
Я когда F# изучал ради интереса опирался на сайт Скота Влашина. Насколько я помню там вообще не было привязки к .net
https://fsharpforfunandprofit.com/fppatterns/
Способ на самом деле удобный. Кажется, что ковариантные возвращаемые значения все-равно не спасут, потому что у свойства еще сеттер есть. Его вроде можно сделать private/protected, если кроме EF Core никто не будет его использовать.
Это поведение c#, он так строит лямбду, так что ef поведение ef корректно
Как с помощью датасета неявно закешировать результаты Query? Тут скорее вопрос методологии и вам CQRS не нравится
Это не очень хорошее решение, работа с асинхронным кодом отличается даже на уровне компилятора. Поэтому не стоит объединять это под одним интерфейсом, интерфейс должен быть явным. Да и каждый раз оборачивать возвращаемое значение IQuery в Task ужасно.
Написать один раз вот так легче:
Но тут есть проблемы:
1) Не весь LINQ будет транслирован в Expression Tree, например такой не будет:
2) LINQ который удастся транслировать в Expression Tree, может быть не транслируем в SQL, в таких случаях EF Core 2.1 сделает запрос к базе данных с тем SQL запросом, который смог транслировать, а остальное обработает в памяти, но это поведение можно переопределить и он станет падать каждый раз, когда не может полностью разобрать Expression Tree.
Кстати ReSharper выделяет самые очевидные «проблемные» места запроса.