У нас есть таблица базы данных, в которой хранится местоположение некоторых волновых файлов плюс связанные метаданные. На таблице есть внешний ключ (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 или определить что-то в ограничении внешнего ключа, которое предотвратит это поведение.