2010-01-21 65 views
3

我有兩個表,我正在使用Linq to SQL。這些表格有一對多關聯。數據庫模式的重要組成部分如下:LINQ to SQL能否生成無效的SQL?

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 

然而,當我對databa執行第二次查詢我得到一個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)。

如何編寫類似於LINQ to SQL將很樂意執行的第二個查詢(在where子句中執行查詢)?

+0

很奇怪 - 看起來像你發現了一個錯誤。儘管如此,使用連接幾乎總是比子查詢更好,所以我會選擇Robert Harvey的答案。 – Aaronaught 2010-01-21 03:30:47

回答

1

在這個特殊的例子中,我認爲你需要在你的Linq語句中加入你的兩個表。這將允許您在不使用.SerialNumber.Length關聯的情況下獲得SerialNumber的實例。這樣的事情(未經測試):

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; 
+0

您的解決方案確實有效。另一種方法是使用db.Cameras.Where(c => c.Id == n.CameraFk).SingleOrDefault(z => z.SerialNumber.Length == 10)!= null作爲where子句。我的問題是在我的真實場景中,動態生成LINQ查詢的框架不會輕易讓我重寫查詢以使用連接等。因此,爲什麼我想了解爲什麼現有結構的查詢會拋出SQL Exceptions。 – 2010-01-21 03:29:47