All streams
Search
Write a publication
Pull to refresh
4
0
Send message
Вот и я надеюсь что вы когда-то вытянете голову из EF. Все возможно, но не на их архитектуре. Их задача работать с деревом объектов, как только вы начинаете делать шаг влево — вам бьют порукам.

И да на linq to objects, можно написать что угодно, но это не забирает у людей права пользоваться опытом/здравым смыслом ;)
Оптимизатора в EF, можно сказать нет. Так что минные поля тут в том, сможет ли он это дело распарсить. А, учитывая его ограничения, лучше сразу сторед процедуру писать, сэкономив время и нервы :)
Придется, так как эти трансляторы это еще то минное поле. Интерестно на сколько сложные LINQ выражения вы писали в своей практике?
Это почему же нельзя?? Я постоянно этим пользуюсь, естественно не EF провайдером.
Вам придется переучиваться когда перейдете на EF Core. И не в оптимизаторе дело а в трансляторе LINQ.
Именно такую оптимизацию мы не делаем, потому, как вы правильно сказали, эти два запроса не эквивалентны. Вы как то странно прочитали мое сообщение и тут же решили от чего-то решительно отказаться.
Может у вас есть кейсы когда linq2db слишком много взял? Я внимательно выслушаю.
Нет, извините что так выглядит. Просто показал как запросы генерятся под конкретный случай. Такую оптимизация я бы и не подумал делать, все упирается в данные и статистику. Такое предугадать это отдельная научная статья.
Вообще-то, это известный способ написания INNER JOIN со сложным условием. Тут мы упираемся в ограниченность LINQ Query синтаксиса. Так что лучше так чем никак. Вспомните только как left join описывается, хотя на это, думаю, и не жалуетесь ;)
Про RIGHT, FULL JOIN, я вообще молчу — их в EF просто нет.
Все кому это доступно. Если ты на опенсорс проекте несколько лет, то твое мнение что-то да значит. И как правило, я пишу почему конкретный кусок кода не подходит и как это исправить.
Я так понял эта статья о проблеме LINQ провайдера, а точнее EF 6, который строит отвратительные заросы. Первый же запрос неправилен, так как вытягивет три поля вместо двух. Все остальное как заставить EF сгенерировать правильный запрос к специфическим данным. Никакой LINQ провайдер это дело сам не соптимизирует.

Перепишите оригинальный запрос на

var query = from e1 in db.Customer
            from e2 in db.Ref.Where(e2 => (e1.Ref_ID == e2.ID) || (e1.Ref_ID2 == e2.ID2))
            select new { Data1 = e1.Name, Data2 = e2.Name };

И получите INNER JOIN, а не CROSS JOIN
Но это не изменяет того факта, что этот запрос не эффективен для этого набора данных, скорее всего без UNION тут не обойтись.
Опять же SQL отвратителен и тянет лишнее.

SELECT TOP (1000)
    [Extent1].[Ref_ID] AS [Ref_ID], 
    [Extent1].[Name] AS [Name], 
    [Extent2].[Name] AS [Name1]
    FROM  [dbo].[Customer] AS [Extent1]
    INNER JOIN [dbo].[Ref] AS [Extent2] ON [Extent1].[Ref_ID] = [Extent2].[ID] OR [Extent1].[Ref_ID2] = [Extent2].[ID2]


Вам привет от LINQ провайдера linq2db

SELECT TOP (1000)
    [e1].[Name],
    [e2].[Name]
FROM
    [Customer] [e1]
        INNER JOIN [Ref] [e2] ON ([e1].[Ref_ID] = [e2].[ID] OR [e1].[Ref_ID2] = [e2].[ID2])

----

SELECT TOP (1000)
    [t1].[Data1],
    [t1].[Data2]
FROM
    (
        SELECT
            [e1_1].[Name] as [Data1],
            [e2_1].[Name] as [Data2]
        FROM
            [Customer] [e1_1]
                INNER JOIN [Ref] [e2_1] ON [e1_1].[Ref_ID] = [e2_1].[ID]
        UNION
        SELECT
            [e1_2].[Name] as [Data1],
            [e2_2].[Name] as [Data2]
        FROM
            [Customer] [e1_2]
                INNER JOIN [Ref] [e2_2] ON [e1_2].[Ref_ID2] = [e2_2].[ID2]
    ) [t1]
Эта информация устарела, релинк оттуда выпилили. Они откатились почти назад во времени, ждите новых багов.
Если я такое чуствую, то скорее вы получите отказ в мерже. Очень много времени забирает ревью кода, но без контрибюторов, опен сорс это сизифов труд. Вы пользуетесь продуктом, вам что-то надо, мы можем сказать насколько это сложно и указать места и как это делать, но явный тяпляп это перебор.

Не раз себя ловил на мысли: блин, я бы уже за час это написал, но нет надо держать себя в руках, контрибюторы должны подучиться.
Надо правильные ORM для таких задач выбирать. EF хорош писать сайты быстро, но про скорость забудьте, ее придется тюнать.
На linq2db это пишется с полпинка:

var obligors = from c in db.Clients
   where c.Balance < 0
   select c;

obligors
    .Set(p => p.Description, p => p.balance < -100500 ? "злостный должник" : "должник")
    .Update();

Можно таким же способом их удалить
obligors.Delete();
или вставить в другую таблицу не пишучи SQL.
obligors.Insert(db.Others);

Все происходит на сервере, ничего на клиент не тянется.
Попробуйте linq2db, я на нем писал любые отчеты, вплоть до использования временных таблиц. Такой себе SQL на стероидах.
Тут EF Core работает как надо, жадная загрузка это их все, хотя опять же не все тут гладко.

Проблема в запросах которые пишут хипстеры без знания SQL.
Истина, они такое на linq городят что бедные EF-щики рыдают. Да и в принципе разрулить идеально не могут.
Наинклюдают неглядя с пол базы, хотя надо конкретно небольшие части трех таблиц.
Fire and forget. Лишние операции — больше нагрузка на базу и сеть. Ты еще удивишься как иногда замена параметра на литерал внезапно ускоряет запрос. Всему нужен тюнинг. Если этого нет, тот кто оптимизирует за вами, просто переколбашивает это на SQL.
Ну это дело я могу предсказать для конкретной ORM.
Проблема в том что определенные подходы работы ORM требуют дополнительных телодвижений с базой.
UPDATE — перед тем как изменить рекорд его надо загрузить из базы потом апдейтгуть.
DELETE — те же грабли
INSERT — получим дополнительный селект после вставки, или если умная ORM, то сделает INSERT WITH OUTPUT. Сказать чтобы вообще ничего не тянуло нельзя.

Можно продолжать список
Проблемы есть, это производительность. То что вы их не испытали, скорее говорит о не критичном объёме данных.
Очень часто модель строят по тому как ему удобно, а не так как эффективно движку базы. Потом начинаются рефакторинги сего добра, и дай бог чтобы миграции не загнулись.
Ну в смысле, организовать из API вызов UPDATE foo set bar = '....' WHERE ....? Да, есть такое, но это можно заимплементить на уровне библиотеки тоже (это пока не сделали, но я знаю, как сделать).

Это надо сделать как и Delete, в основном на это плюются. В нашей ORM практически любой запрос, который вы используете для выбоки, легко превращается в UPDATE, UPDATE FROM, DELETE или INSERT INTO — переиспользование налету.

В Java есть отличная штука — TestContainers

Делаем по старинке, надо тестировать на 15 базах: VMWare. Есть такие базы, которые по другому и не поставишь. Майкросфт дал опенсорсу доступ к Azure Pipelines — вот тут уже можно разыграться и докером доставлять нужное, не все конечно.

С другой стороны, у всего есть область применения. И для какой-то супер-производительной работы наверное Celesta не очень подходит, т. к. изначально создавалась под задачи быстрой разработки бэкенда для бизнес-приложений.

Странно, почему вам не подошел старичек Hibernate. Ну что же, через год другой такие проекты попадают в наши высокооплачиваемые руки ;) И это нормально, чтобы взлететь надо чтобы что-то было. Но к сожалению это палка о двух концах, так как новое поколение так и не выучило SQL и не понмает как RDBMS работает.

Information

Rating
Does not participate
Registered
Activity