Skip to content

Query: SqlFunction to compare byte arrays (necessary to filter on rowversion) #5936

@jnm2

Description

@jnm2

Right now you can look at https://stackoverflow.com/questions/7437970/how-to-query-code-first-entities-based-on-rowversion-timestamp-value and see how difficult this is- it's next to impossible to get right.

Since we can't have comparison operators on byte arrays, the next most idiomatic thing would be to have the following methods in SqlFunctions (or DbFunctions, if possible), naming convention following the Expression class:

  • bool LessThan(byte[], byte[])
  • bool LessThanOrEqual(byte[], byte[])
  • bool GreaterThan(byte[], byte[])
  • bool GreaterThanOrEqual(byte[], byte[])

Questions

  1. I don't know if there is any value in Equal and NotEqual. They would be useful if evaluated client-side, because they would be semantically purer than the == operator which compares byte arrays by reference. The semantics of byte array == are incorrect because SQL compares binary by value (as it should).
  2. Could they be extension methods? Might be a nice experience, might not.

Considered alternatives

Casting

A function that would be cool for other purposes would be long SqlFunctions.Cast(byte[]), but that would not work for this scenario because SQL Server only has signed comparisons, plus it's less performant server-side:

select case when cast(0x0FFFFFFFFFFFFFFF as bigint) < cast(0xFFFFFFFFFFFFFFFF as bigint)
    then 'unsigned' else 'signed - oops' end

Doing a multi-step comparison would get around the signed comparison issue, but that's hacky and slower. Casting to char(8) would subject you to collation comparisons.

Idiomatic binary type

Another alternative would be to use a Binary primitive struct that wraps a byte array and provides all the value-comparison operators and has an implicit conversion to and from a byte array. Additionally, a Timestamp primitive type (mine) for rowversion columns. This puts comparison operators back on the table and would be ideal over SqlFunctions, but obviously will have to wait for #242. If it speeds up #242 all the better!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions