Comments 8
Думаю вам надо было сразу смотреть в исходники Npgsql.EntityFrameworkCore, где они добавляли поддержку Range.
Очень надеюсь что это все не поломается в 3.0, кстати проверьте.
Если станет совсем не в моготу запустить нужную выборку — попробуйте нашу зверушку (ну так как-то называем) linq2db.EntityFrameworkCore. Легким тюнингом, можно Json и в linq ганять, например при использовании LATERAL и
Очень надеюсь что это все не поломается в 3.0, кстати проверьте.
Если станет совсем не в моготу запустить нужную выборку — попробуйте нашу зверушку (ну так как-то называем) linq2db.EntityFrameworkCore. Легким тюнингом, можно Json и в linq ганять, например при использовании LATERAL и
jsonb_to_recordset
.Npgsql же провайдер с нуля. Они делали все на инфраструктуре ef core, а мне надо было вклиниться именно в их инфраструктуру.
А можно живых примеров тюнинга? Просто я пока не могу оценить вашу зверушку, но про jsonb_to_recordset сразу могу сказать, это не то что нужно. У нас ведь динамический набор полей. Все, что я бы выиграл, это исключил необходимость танцев вокруг оператора ->>
Скажем так, в linq2db такие экстеншины пишутся с полпинка
А зверушка позволяет перенаправлять дерево выражений на наш Linq парсер. Да и по ссылке просто почитайте BulkCopy, Delete From, Update From, Insert From.
То что EF от вас спрятал и заставил писать на хранимках или Dapper, вполне себе легко пишется на linq.
Вот вполне себе может понадобиться апдейтнуть одно поле в Jsonb:
Для этого конечно же надо добавить экстеншин
Вот так, в обход ChangeTracker, мы изменили поле в нескольких записях не потянув ни одной записи.
public static class Jsonb
{
[Sql.Expression("{0}->>{1}", ServerSideOnly = true, InlinePrameters = true)]
public static T Value<T>(object field, string propName)
{
throw new NotImplementedException();
}
}
А зверушка позволяет перенаправлять дерево выражений на наш Linq парсер. Да и по ссылке просто почитайте BulkCopy, Delete From, Update From, Insert From.
То что EF от вас спрятал и заставил писать на хранимках или Dapper, вполне себе легко пишется на linq.
Вот вполне себе может понадобиться апдейтнуть одно поле в Jsonb:
ctx.SomeItems
.Where(e => Jsonb.Value<string>(e.Field, "SomeValue") == "Old Value")
.Set(e => e.Field, e => Jsonb.Set(e.Field, "SomeValue", "New Value"))
.Update();
Для этого конечно же надо добавить экстеншин
public static class Jsonb
{
[Sql.Expression("jsonb_set({0}, {1}, {2})", ServerSideOnly = true, InlinePrameters = true)]
public static T Set<T>(T field, string path, string newValue)
{
throw new NotImplementedException();
}
}
Вот так, в обход ChangeTracker, мы изменили поле в нескольких записях не потянув ни одной записи.
Потрясно! Вам следует поработать над документацией и живыми примерами. Ну и еще приложить бенчмарки. Без этого зверушка будет темной лошадкой. Как будет время, обязательно поковыряю исходники и найду применение. Огромное спасибо за пример!
Хотя вот с изменением одного свойства перебор. Когда работаешь с динамическим Jsonb, без чего нибудь типа newtonsoft.json не обойтись. А учитывая факт, что изменять одно свойство внутри json нельзя (postgre все равно перезапишет все поле), производительность будет играть роль. К тому же я могу просто пришедший с фронта json скастить в стрингу и обновить поле.
Кстати, в примере с Set, новое значение типа string. А что, если я захочу datetime или int? Уверен, решение и на это найдется. дайте документацию! :)
Хотя вот с изменением одного свойства перебор. Когда работаешь с динамическим Jsonb, без чего нибудь типа newtonsoft.json не обойтись. А учитывая факт, что изменять одно свойство внутри json нельзя (postgre все равно перезапишет все поле), производительность будет играть роль. К тому же я могу просто пришедший с фронта json скастить в стрингу и обновить поле.
Кстати, в примере с Set, новое значение типа string. А что, если я захочу datetime или int? Уверен, решение и на это найдется. дайте документацию! :)
Мой пример высосан из пальца :) Я не работал с Jsonb в Postgres, просто почитал документацию и решил что можно показать как это гибко.
Если найдете то, что мы не можем превратить в SQL — вперед, создали issue в linq2db репозитории и я лично пошаманю.
С документацией проблема, только начинаешь ее писать — бац реквест на фичу и, к сожалению, плохие мы писатели документации. Спасаеют ссылки на тесты, где человек может увидеть как это работает.
Про типы не переживайте, есть механизм перехвата создания такого экспрешина, крутим как хотим без изменения основного кода. На этом, кстати, создана поддержка оконных функций — работает как часы.
Есть тестовый проект с бенчмарками, так и не оформился в статью, возможно будет вторая реинкарнация на BenchmarkDotNet. Итог очевиден, мы быстрее EF Core, да и Dapper, несмотря на их синтетические тесты — так вот же.
Весь цирк этих тестов выбрать тривиальную вещь и замапать, и никто не ганял это в потоках, с асинками.
Библиотека заточена на самый что ни на есть перформанс, в полоть до того что инлайнить в SQL, а что параметрами прокидывать. И часто бывает, что лучше параметры выкинуть. Гонка за производительностью заставляет библиотеку быть аскетичной но предсказуемой.
Вот и можете, кстати, стать одним из тестеров зверушки, так как мы не работам с EF и поддержали только то что увидели. Но то что у нас SQL лучше и эффективней, я вам гарантирую, хотя бы по тому что библиотека развивается уже второе десятилетие людьми которые знают как готовить базы данных.
Если найдете то, что мы не можем превратить в SQL — вперед, создали issue в linq2db репозитории и я лично пошаманю.
С документацией проблема, только начинаешь ее писать — бац реквест на фичу и, к сожалению, плохие мы писатели документации. Спасаеют ссылки на тесты, где человек может увидеть как это работает.
Про типы не переживайте, есть механизм перехвата создания такого экспрешина, крутим как хотим без изменения основного кода. На этом, кстати, создана поддержка оконных функций — работает как часы.
Есть тестовый проект с бенчмарками, так и не оформился в статью, возможно будет вторая реинкарнация на BenchmarkDotNet. Итог очевиден, мы быстрее EF Core, да и Dapper, несмотря на их синтетические тесты — так вот же.
Весь цирк этих тестов выбрать тривиальную вещь и замапать, и никто не ганял это в потоках, с асинками.
Библиотека заточена на самый что ни на есть перформанс, в полоть до того что инлайнить в SQL, а что параметрами прокидывать. И часто бывает, что лучше параметры выкинуть. Гонка за производительностью заставляет библиотеку быть аскетичной но предсказуемой.
Вот и можете, кстати, стать одним из тестеров зверушки, так как мы не работам с EF и поддержали только то что увидели. Но то что у нас SQL лучше и эффективней, я вам гарантирую, хотя бы по тому что библиотека развивается уже второе десятилетие людьми которые знают как готовить базы данных.
Буквально в последнем превью для .net core 3.0 добавили работу с json/jsonb полями — www.npgsql.org/efcore/mapping/json.html
Я не упоминал в статье нативную поддержку в 3.0, но я упоминал плагин Npgsql.Json.Net, который умеет только мапить json поле в тип Clr. И я объяснил, что там, где есть динамика, статическая типизация не подходит. А jsonb позволяет дополнять сущность дополнительными атрибутами. Как я создам Clr модели на динамические сущности? Разве что закопаться в IL инъекции и рефлексию. Но это будет дорого поддерживать.
В общем мой инструмент решает другую задачу. Есть сущность, у нее есть ряд свойств, которые добавляет/удаляет пользователь. И он хочет по этим полям вести поиск и сортировку. То есть у меня нет возможности выбрать .Where(e => e.Customer.Name == «Joe») как в примере по ссылке, потому что на момент компиляции приложение ничего не знает про состав jsonb поля.
В общем мой инструмент решает другую задачу. Есть сущность, у нее есть ряд свойств, которые добавляет/удаляет пользователь. И он хочет по этим полям вести поиск и сортировку. То есть у меня нет возможности выбрать .Where(e => e.Customer.Name == «Joe») как в примере по ссылке, потому что на момент компиляции приложение ничего не знает про состав jsonb поля.
Sign up to leave a comment.
Доступ к свойствам внутри поля Jsonb для Npgsql