2013-06-28 85 views
3

我對SQLite數據庫有Entity Framework 4模型。部分模型看起來像這樣 enter image description hereLINQ to Entities物化錯誤

所有Id字段的類型都是Guid(SQLite表DDL中的uniqueidentifier)。但是當我運行下面的LINQ查詢時,我得到異常。

var query = AbonentPfrs.Select(a => 
    new 
    { 
     AbPfr = a, 
     Pfr = a.PfrCertificates.Select(c => c.Id), 
     Ac = a.AcCertificates.Select(c => c.Id) 
    } 
); 
query.ToList(); 

當我運行它,我得到

System.InvalidOperationException: The type of the key field 'Id' is expected to be 'System.Guid', but the value provided is actually of type 'System.String'. 

更新:我發現EF生成SQL查詢,真正返回一個字符串作爲實體的一個標識符。

行進至DB ((query as ObjectQuery).ToTraceString())的SQL是這樣的:

SELECT 
[UnionAll1].[C2] AS [C1], 
[UnionAll1].[C3] AS [C2], 
[UnionAll1].[Id] AS [C3], 
[UnionAll1].[PfrRegNumber] AS [C4], 
[UnionAll1].[PfrUnitId] AS [C5], 
[UnionAll1].[Account_Id] AS [C6], 
[UnionAll1].[ActiveCertificate_Id] AS [C7], 
[UnionAll1].[C1] AS [C8], 
[UnionAll1].[Id1] AS [C9], 
[UnionAll1].[C4] AS [C10] 
FROM (SELECT 
    CASE WHEN ([Extent2].[Id] IS NULL) THEN NULL ELSE 1 END AS [C1], 
    1 AS [C2], 
    1 AS [C3], 
    [Extent1].[Id] AS [Id], 
    [Extent1].[PfrRegNumber] AS [PfrRegNumber], 
    [Extent1].[PfrUnitId] AS [PfrUnitId], 
    [Extent1].[Account_Id] AS [Account_Id], 
    [Extent1].[ActiveCertificate_Id] AS [ActiveCertificate_Id], 
    [Extent2].[Id] AS [Id1], 
    NULL AS [C4] 
    FROM [AbonentPfrs] AS [Extent1] 
    LEFT OUTER JOIN [Certificates] AS [Extent2] ON [Extent1].[Id] = [Extent2].[AbonentPfr_PfrCertificates_Certificate_Id] 
UNION ALL 
    SELECT 
    2 AS [C1], 
    2 AS [C2], 
    2 AS [C3], 
    [Extent3].[Id] AS [Id], 
    [Extent3].[PfrRegNumber] AS [PfrRegNumber], 
    [Extent3].[PfrUnitId] AS [PfrUnitId], 
    [Extent3].[Account_Id] AS [Account_Id], 
    [Extent3].[ActiveCertificate_Id] AS [ActiveCertificate_Id], 
    NULL AS [C4], 
    [Extent4].[Id] AS [Id1] 
    FROM [AbonentPfrs] AS [Extent3] 
    INNER JOIN [Certificates] AS [Extent4] ON [Extent3].[Id] = [Extent4].[AbonentPfr_AcCertificates_Certificate_Id]) AS [UnionAll1] 
ORDER BY [UnionAll1].[Id] ASC, [UnionAll1].[C1] ASC 

enter image description here

的最後列的證書中的實體ID。但最後有Guid類型和之前的字符串。如果我單獨運行查詢的部分,然後我得到的下一列類型(FOT最後兩個):

  1. 首先選擇:GUID,對象
  2. 第二個選擇:對象,的Guid
  3. UNION ALL:GUID,對象
  4. 外選擇:字符串的Guid

爲什麼在倒數第二個欄外select返回字符串?

+0

我認爲這是因爲兩個關係在同一個表上 - 從AbonentPfr到證書。但我不確定... – sedovav

+0

可能是因爲SQLite存儲GUID作爲字符串? AFAIK SQLite沒有本地GUID數據類型。 – okrumnow

+0

但在所有其他查詢中,它的工作原理相同 – sedovav

回答

0

看來,排序是重點。沒有排序,最後兩列的結果類型是Guid和Objects。訂購 - 字符串和Guid。這兩個順序表達式均取決於[Extent2].[Id]列。 SQLite不會操作Guid類型,所以我認爲,值被轉換爲String。 這是EF4和System.Data.SQLite集成的難點之一。所以我需要找到一種方法來強制EF不會生成訂購條款...

0

執行外部聯接時,行CASE WHEN ([Extent2].[Id] IS NULL) THEN NULL ELSE 1 END AS [C1]將在您的查詢遇到缺失值時返回空值C1。 在.NET中,GUID是一個值類型(128位整數),所以不能設置爲null而不跳過箍環。 (有關GUID結構的更多信息,請參見Why isn't there a Guid.IsNullOrEmpty() method)。

由於返回的值是可以爲空且格式爲xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,因此它被假定爲字符串。

+0

我已經更改了結果的圖片以顯示哪些類型的列。正如你可以看到問題出現在「[Extent2]。[Id]'和'NULL'的」C9「列中。但是「C10」欄很好 - 結果類型是Guid。我看不出差別。 C10是'NULL'和'[Extent4]。[Id]'的結合結果。需要說'[Extent2]。[Id]'和'[Extent4]。[Id]'具有相同的數據庫類型。 – sedovav