如何使用 LINQ 和 Entity Framework 计算一行中所有列的校验和?

How do I calculate a checksum on all columns in a row using LINQ and Entity Framework?

我尝试执行的查询与此类似:

var checksum = from i in db.Items
    where i.Id == id
    select SqlFunctions.Checksum("*");

但是,这个returns字符串的校验和值"*"而不是评估通配符。有没有办法计算所有列的校验和?

更新:

var checksum = db.Database.SqlQuery<int?>("SELECT CHECKSUM(*) FROM [Catalog].[Item] WHERE Id = @p0", id);

这给了我想要的结果,但看起来很脏。有没有内联的方法来做到这一点 SQL?

这可以通过 SqlFunctions class 来完成。此 Class 允许 linq-to-entities 代码包含可轻松转换为 Sql 的方法。

首先在您当前的编辑中:使用内联 SQL 不是 'dirty' 并且在大多数(如果不是全部)情况下完全没问题。 ORM 并不能提供一切,尤其是在不存在良好的对象-列映射的情况下。但是,由于您使用的是 entity framework,您还不如熟悉 SqlFunctions 静态方法。

在这种情况下,有很多用于执行校验和的重载,但是它们必须都是同一类型。由于您没有 post 您的列的类型或数量,我不想在示例中推荐错误的重载供您使用。

以下是您的选择:

SqlFunctions.Checksum():

  • bool?
  • char[]
  • DateTime?
  • DateTimeOffset?
  • Decimal?
  • double?
  • Guid?
  • TimeSpan?
  • String

以上所有都有重载以允许最多 3 个参数(相同类型)。

SqlFunctions.AggregateChecksum():

  • IEnumerable<int>
  • IEnumerable<int?>

如果查看这些函数的文档,您会发现传递的参数是 VALUES,而不是列名。所以你应该在 Select() 子句中使用它们。这就是为什么当您将 "*" 传递给操作时,它会对包含单个星号而不是所有列的字符串进行校验和。另外请记住,这些函数不能直接调用,只能在 Linq-To-Entities 查询中使用。

假设您名为 "ItemName" 和 "Description" 的列都是字符串,并且您还需要您的 ID,即 int:

var checksum = db.Items.Where(i => i.Id == id)
                       .Select(i => SqlFunctions.Checksum(i.Id.ToString(), i.ItemName, i.Description));

不幸的是,正如您在上面的示例中看到的那样,我们不得不将 int 转换为字符串。没有重载允许使用不同类型的参数来计算校验和,也没有任何选项允许在校验和函数中使用超过 3 个参数;但是,正如我上面提到的,有时您需要执行内联 SQL 命令,这没关系。