Entity Framework присоединяется к столбцам соединения, допускающим значение NULL

Мой провайдер Devart Entity Framework использует следующую ссылку на объекты.

from p in context.BEAT_CONTACT
join cl in context.COMPASS_LOCATIONS
on p.GAZETEER_KEY equals cl.GAZETTEER_KEY
//on new { bcdid = p.GAZETEER_KEY.Value }
//equals new { bcdid = cl.GAZETTEER_KEY.Value }
into myRandomlj
from rr in myRandomlj.DefaultIfEmpty()

Примечание. Столбцы соединения являются нулевыми типами в БД и, следовательно, десятичными? в С#

Сгенерированный SQL:

FROM   NP_TEST.BEAT_CONTACT "Extent1"
LEFT OUTER JOIN NOTTS_DW_OWNER.COMPASS_LOCATIONS "Extent2"
ON ("Extent1".GAZETEER_KEY = "Extent2".GAZETTEER_KEY) 
* OR (("Extent1".GAZETEER_KEY IS NULL) 
* AND ("Extent2".GAZETTEER_KEY IS NULL))

Помеченные звездочкой (*) ИЛИ и И добавляют дополнительные секунды к выполнению моего sql. Когда оператор помещается в жабу (кстати, провайдер oracle devart ef) с удаленными элементами, отмеченными звездочкой, SQL, очевидно, работает намного быстрее.

Мой вопрос: моя ссылка на сущности виновата или чего-то не хватает? Или виноват провайдер Devart EF?

Обновление вопроса: Здравствуйте, как первоначальный создатель этого вопроса, я хотел бы попытаться прояснить этот вопрос, если это возможно. Из комментариев LukLed: «Поставщики Entity Framework по умолчанию работают правильно и не создают таких условий SQL. Это не только неправильно, но и сильно снижает производительность». Меня в основном беспокоит комментарий «нападающего производительности», этот удар огромен, особенно потому, что количество строк увеличивается по обе стороны от соединения. Мне приходилось обходить это поведение с помощью ExecuteStoreQuery‹> или Sproc. Это означало отсутствие linq, и мне пришлось надеть шляпу sql, чтобы выполнить работу.


person Dilbert    schedule 14.02.2011    source источник
comment
Я бы сказал, что это ОГРОМНАЯ ошибка в провайдере.   -  person LukLed    schedule 15.02.2011
comment
@LukLed, это не ошибка. Учитывайте ситуацию с двумя нулевыми значениями в соединенных столбцах. SQL рассматривает два нуля как неравные значения.   -  person Devart    schedule 15.02.2011
comment
@Деварт: я не согласен. Это не ожидаемое поведение. Если кто-то использует этот синтаксис, он ожидает, что он будет переведен на SQL как есть. Если бы программист хотел соединиться по нулям, он бы явно добавил это условие, но кто на самом деле соединяется по NULL? Поставщики Entity Framework по умолчанию работают правильно и не создают таких SQL условий. Это не только неправильно, но и сильно снижает производительность. Кто-то не понимает, что NULL является особым значением в SQL и не должно относиться к нему так же.   -  person LukLed    schedule 15.02.2011
comment
@LukLed, мы только что повторили тест для базы данных NorthwindEF SQL Server, соединение было выполнено для двух столбцов, допускающих значение null, и была выполнена та же проверка на значение null. Вот тестовый запрос LINQ: var q = from a в db.Employees присоединяются к b в db.Products на a.CreationDate равно b.CreationDate в n select n.DefaultIfEmpty();   -  person Devart    schedule 15.02.2011
comment
@Devart: Хм, ты прав. Я проверил это ранее, но, должно быть, сделал что-то не так. Я бы сказал, что это лучшее поведение, но если стандартный провайдер делает то же самое, это не обсуждается. Спасибо за ответы.   -  person LukLed    schedule 15.02.2011
comment
Здравствуйте, как первоначальный создатель этого вопроса, я хотел бы попытаться прояснить этот вопрос, если это возможно. Из комментариев LukLed: поставщики Entity Framework по умолчанию работают правильно и не создают таких условий SQL. Это не только неправильно, но и сильно влияет на производительность. Меня в основном беспокоит комментарий о производительности, этот удар огромен, особенно потому, что количество строк увеличивается по обе стороны от соединения. Мне приходилось обходить это поведение с помощью ExecuteStoreQuery‹› или Sproc. Это означало отсутствие linq, и мне пришлось надеть шляпу sql, чтобы выполнить работу.   -  person Dilbert    schedule 16.02.2011
comment
@Dilbert, если решение SQL совершенно не подходит для вас, вы можете попробовать добавить NOT NULL к определению обоих столбцов, для которых выполняется JOIN (конечно, если данные вашей базы данных допускают такое ограничение). Предложение ИЛИ/И будет удалено.   -  person Devart    schedule 17.02.2011


Ответы (2)


это прекрасно, работает так, как ожидалось, дополнительные условия обеспечивают объединение, когда оба являются null из-за того, что null = null не соответствует действительности в SQL

person Kris Ivanov    schedule 14.02.2011
comment
Хорошо. Извините, возможно, мне следовало поставить свой список вопросов в конец. Что я не хочу медленного ответа, когда ИЛИ (( И )) накладывается на соединение. Я получаю такое же количество возвращаемых строк, если я убираю оператор ИЛИ. Я хочу, чтобы производительность менее секунды не позволяла превратить запрос в две/три с небольшим секунды. - person Dilbert; 14.02.2011
comment
что такое оператор выбора, возможно, мы можем переписать оператор LINQ без соединения - person Kris Ivanov; 14.02.2011
comment
Целью запроса linq to entity является заполнение полей из многих таблиц с использованием левых соединений, чтобы позволить мне получить плоское представление данных в моем объекте. Таким образом, вы можете представить, что мой выбор будет select new MyThing { thingID = rr.thingID, thingText = ss.thingText }).toList(); и т. д. соединения вводят необходимые данные так же, как SQL, но без необходимости использовать .Include (все) или .Load (когда я хочу). Я хочу написать свой запрос почти как sql, как, следовательно, левые внешние соединения с использованием DefaultIfEmpty. Я не могу иметь linq для клипа сущностей и пропускать несвязанные данные, такие как значения поиска. - person Dilbert; 14.02.2011
comment
если у вас нет записей с ключами соединения с нулевыми значениями, лучше всего сделать их недействительными в хранилище данных. - person Kris Ivanov; 14.02.2011
comment
Это, скорее всего, ответ, который я хочу/нужна. Однако на данный момент дизайн базы данных исправлен. Как вы можете себе представить, у меня может быть человек с фиксированным адресом вплоть до ключа геолокации, или у меня может быть расплывчатое текстовое описание того, где он может жить. Если у вас нет записей с ключами соединения с нулевыми значениями, лучше всего сделать их недействительными в хранилище данных. - person Dilbert; 14.02.2011
comment
У меня есть требование, которое считает необходимым объединить данные, где возможно существование нулевых значений. Единственный способ для меня добраться до sql: FROM NP_TEST.BEAT_CONTACT Extent1 LEFT OUTER JOIN NOTTS_DW_OWNER.COMPASS_LOCATIONS Extent2 ON (Extent1.GAZETEER_KEY = Extent2.GAZETTEER_KEY), чтобы сделать поля необнуляемыми? - person Dilbert; 14.02.2011
comment
если вы покажете весь оператор linq, может быть способ сделать это без использования соединения, поэтому исключая дополнительные проверки, однако это исключит все совпадения, где оба ключа равны нулю - person Kris Ivanov; 14.02.2011
comment
Спасибо за ваше время сегодня вечером, я опубликую полное заявление завтра, иллюстрирующее мою точку зрения. - person Dilbert; 14.02.2011

@K Иванов, ты прав. Следует также учитывать случай двух нулей, и предложения со звездочкой делают свое дело.

person Devart    schedule 15.02.2011