我有SQLite数据库的Entity Framework 4模型。模型的一部分看起来像这样
所有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'.
UPDATE:我发现EF生成的SQL查询确实将字符串作为其中一个实体的标识符返回。
转到数据库((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
列的最后一列是证书实体的ID。但是最后一个有类型Guid和前一个 - 字符串。如果我分别运行部分查询,那么我会得到下一个列类型(最后两个):
为什么外部选择返回最后一列而不是一列的字符串?
答案 0 :(得分: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,因此假定它是一个字符串。
答案 1 :(得分:0)
似乎排序就是重点。如果没有排序,最后两列的结果类型是Guid和Objects。订购 - String和Guid。两个订单表达式都依赖于[Extent2].[Id]
列。 SQLite不运行Guid类型,所以我认为,值被转换为String。
这是EF4和System.Data.SQLite集成的难点之一。所以我需要找到一种方法来强制EF不生成排序条款...