Интересное поведение LinqToSql - PullRequest
3 голосов
/ 01 июня 2010

У нас есть таблица базы данных, в которой хранится местоположение некоторых волновых файлов плюс связанные метаданные. На таблице есть внешний ключ (employeeid), который ссылается на таблицу employee. Однако не все файлы WAV относятся к сотруднику, для этих записей employeeid является нулевым. Мы используем LinqToSQl для доступа к базе данных, запрос на извлечение всех записей wav-файлов, не связанных с сотрудниками, выглядит следующим образом:

var results = from Wavs in db.WaveFiles
              where Wavs.employeeid == null;

За исключением того, что это не возвращает никаких записей, несмотря на то, что есть записи, где employeeid равен нулю. На сервере SQL профилирования я обнаружил, что причина, по которой записи не возвращаются, в том, что LinqToSQl превращает его в SQL, который очень похож на:

SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE 1=0

Очевидно, это не возвращает строк. Однако, если я зайду в конструктор DBML, удаляю ассоциацию и сохраняю. Внезапно тот же самый запрос LINQ превращается в

SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE EmployeeID IS NULL

т.е. если существует ассоциация, тогда LinqToSql предполагает, что все записи имеют значение для внешнего ключа (даже если оно имеет значение NULL и свойство отображается как NULL) для объекта WaveFile) и в качестве такового доставляет конструкцию оператора where, который не будет возвращать никаких записей. .

Кто-нибудь знает, есть ли способ сохранить связь в LinqToSQL, но остановить это поведение? Обходной путь, о котором я могу быстро подумать, - это иметь вычисляемое поле с именем IsSystemFile и установить его в 1, если employeeid равен нулю, и 0 в противном случае. Однако это выглядит как хак для обхода странного поведения LinqToSQl, и я бы предпочел сделать что-то в файле DBML или определить что-то в ограничении внешнего ключа, которое предотвратит это поведение.

Ответы [ 3 ]

5 голосов
/ 01 июня 2010

Я думаю, вам следует дважды проверить ваш dbml-файл. Звучит так, будто Линк не знает, что employeeid это обнуляемый столбец Или посмотрите на ваш файл .cs. Атрибуты для этого столбца должны выглядеть следующим образом:

[Column(Storage="_employeeid", DbType="Int")]

а не:

[Column(Storage="_employeeid", DbType="Int NOT NULL")]
0 голосов
/ 16 июня 2010

Столбец определяется как:

[Column(Storage="_employeeid", DbType="Int")]

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

0 голосов
/ 06 июня 2010

попробуйте это:

var results = from Wavs in db.WaveFiles
              where DbNull.Value.Equals(Wavs.employeeid)

Другой способ и хороший способ - это ввести сотрудника по умолчанию, с которым связан каждый волновой файл, который не связан с реальным сотрудником

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...