3

我在 SQLite 数据库上有实体框架 4 模型。模型的一部分看起来像这样 在此处输入图像描述

所有 Id 字段都具有 Guid 类型(SQLite 表 DDL 中的唯一标识符)。但是当我运行以下 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 查询真正返回字符串作为其中一个实体的标识符。

进入数据库的 SQL((query as ObjectQuery).ToTraceString())如下所示:

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 和前一个 - 字符串。如果我单独运行部分查询,那么我会得到下一个列类型(最后两个):

  1. 首先选择:Guid、Object
  2. 第二个选择:对象,Guid
  3. 联合所有:Guid、Object
  4. 外选:String、Guid

为什么外部选择在最后一列中返回字符串?

4

2 回答 2

0

执行外连接时,当查询遇到缺失值时,该行将CASE WHEN ([Extent2].[Id] IS NULL) THEN NULL ELSE 1 END AS [C1]返回空值。C1在 .NET 中,GUID 是一种值类型(128 位整数),因此不能在不跳过箍的情况下将其设置为 null。(有关 GUID 结构的可空性的更多信息,请参阅为什么没有 Guid.IsNullOrEmpty() 方法。)

由于返回的值可以为空并且格式为 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,因此假定为字符串。

于 2013-07-03T23:14:35.690 回答
0

似乎顺序是重点。没有排序最后两列的结果类型是 Guid 和 Objects。订购 - 字符串和指导。两个订单表达式都取决于[Extent2].[Id]列。SQLite 不操作 Guid 类型,所以我认为值被转换为字符串。这是 EF4 和 System.Data.SQLite 集成的难点之一。所以我需要找到一种方法来强制 EF 不生成排序子句......

于 2013-07-04T08:41:16.483 回答