如何使用 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 命令,这没关系。
我尝试执行的查询与此类似:
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 命令,这没关系。