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

血红的双手。 提交于 2019-12-12 16:39:02

问题


The query I am trying to execute is similar to this:

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

However, this returns the checksum value of the string "*" rather than evaluating the wildcard. Is there a way to calculate the checksum of all the columns instead?

Update:

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

This gives me the result I want but seems dirty. Is there a way to do this without inline SQL?


回答1:


This can be done with the SqlFunctions class. This Class allows for linq-to-entities code to include methods that are easily converted to Sql.

First of all in your current edit: Using inline SQL is not 'dirty' and is totally fine in most (if not all) cases. ORMs don't provide everything, especially if there isn't a good object-column mapping that exists. However, since you're using entity framework you might as well get aquanted with the SqlFunctions static methods.

In this case there are a lot of overloads for performing a checksum, however they must all be of the same type. Since you didn't post what types your columns or how many you have, I don't want to recommend the wrong overload in an example for you to use.

Here are your options:

SqlFunctions.Checksum():

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

All of the above have overloads to allow up to 3 parameters (of the same type).

SqlFunctions.AggregateChecksum():

  • IEnumerable<int>
  • IEnumerable<int?>

If you take a look at the documentation for these functions you'll see that the parameters that you're passing are VALUES, not column names. So you should be using them inside of a Select() clause. This is why when you passed "*" to the operation it checksummed the string containing a single asterisk instead of all columns. Also, keep in mind that these functions cannot be called directly, and must only be used within a Linq-To-Entities query.

Let's assume your columns named "ItemName" & "Description" are both strings, and you also want your id, which is an int:

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

Unfortunately, as you see in the above example we had to cast our int to a string. There are no overloads that allow for different typed parameters for computing a checksum, nor are there any options that allow for more than 3 parameters in the checksum function; however, as I mentioned above sometimes you need to do an inline SQL command and this is OK.



来源:https://stackoverflow.com/questions/29547542/how-do-i-calculate-a-checksum-on-all-columns-in-a-row-using-linq-and-entity-fram

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!