Может ли LINQ To SQL генерировать неверный SQL? - PullRequest
3 голосов
/ 21 января 2010

У меня есть две таблицы, с которыми я использую Linq to SQL. Таблицы имеют связь 1 ко многим. Важной частью схемы базы данных является следующее:

Camera:
  Id (int)
  SerialNumber (string)
  ...

CameraCalibration
  Id (int)
  CameraFk (int)
  ...

Используя LINQ to SQL, я могу получить список всех калибровок камеры для камер с 10-значным серийным номером следующим образом

var query = from n in db.CameraCalibrations
    where n.Camera.SerialNumber.Length == 10
    select n

Исходя из моего понимания LINQ, следующий запрос должен работать одинаково (даже если по сравнению он довольно грубый ...)

var query = from n in db.CameraCalibrations
where db.Cameras.Where(c => c.Id == n.CameraFk).SingleOrDefault()
                .SerialNumber.Length == 10
select n

Однако, когда я выполняю этот второй запрос к базе данных, я получаю исключение SQL, заявляющее, что «Невозможно вызвать методы на nvarchar». Когда я смотрю на сгенерированный SQL, кажется довольно ясным, почему генерируется исключение:

SELECT t0.*
FROM CameraCalibration AS t0
WHERE (
    SELECT t1.serialNumber.Length
    FROM Camera AS t1
    WHERE t1.id = t0.cameraFk
    ) = 10

Обратите внимание, как сгенерированный SQL использует выражение t1.serialNumber.Length? Я ожидал, что это будет переведено в LEN (t1.serialNumber), и действительно с этим изменением запрос работает.

Я что-то здесь не так делаю? Или это ошибка в том, как я структурировал свой запрос и / или ограничение LINQ to SQL?

Хотя я могу легко реструктурировать запрос, который использовал для демонстрации проблемы, в моем реальном сценарии это будет намного сложнее (частично из-за участия динамически генерируемого LINQ).

Как я могу написать запрос, похожий на второй (с поиском, выполненным в предложении where), который LINQ to SQL будет рад выполнить?

1 Ответ

1 голос
/ 21 января 2010

В данном конкретном случае я думаю, что вам нужно объединить две таблицы в вашем выражении Linq.Это позволит вам получить экземпляр SerialNumber без использования ассоциации .SerialNumber.Length.Примерно так (не проверено):

var query = from n in db.CameraCalibrations 
            join c in db.Cameras on c.Id equals n.CameraFk
            where c.SerialNumber.Length == 10
            select n;
...