It looks like your confusion comes from misunderstanding what varbinary
is. varbinary
is a string of bytes, not chars. It is not even really a string, it is an array of bytes.
varbinary
can be represented as a string of hexadecimal values and varbinary
constants in T-SQL code are represented as hexadecimal strings. Two hexadecimal characters per byte.
The SUBSTRING
function in T-SQL can work with strings (varchar
) and with bytes (varbinary
).
Syntax
SUBSTRING ( expression ,start , length )
The values for start and length must be specified in number of
characters for ntext
, char
, or varchar
data types and bytes for text
,
image
, binary
, or varbinary
data types.
So, the following T-SQL trigger code
declare @ctxt varbinary(128)
select @ctxt=context_info from master.dbo.sysprocesses where spid = @@spid
set @session=substring(@ctxt,1,4)
takes first 4 bytes (not chars) from the @ctxt
array of bytes and assigns them to the @session
variable. What type is @session
? Most likely it is int
.
Run this sample code in SSMS and you'll see the hexadecimal representation of some integers:
DECLARE @T TABLE (I int);
INSERT INTO @T VALUES
(0),
(1),
(3),
(19),
(255),
(256),
(512),
(768),
(4098),
(65535),
(65536),
(131072),
(1234567890),
(-1),
(-65535);
SELECT
I, CONVERT(varbinary(120), I) AS BinI
FROM @T;
Result
+------------+------------+
| I | BinI |
+------------+------------+
| 0 | 0x00000000 |
| 1 | 0x00000001 |
| 3 | 0x00000003 |
| 19 | 0x00000013 |
| 255 | 0x000000FF |
| 256 | 0x00000100 |
| 512 | 0x00000200 |
| 768 | 0x00000300 |
| 4098 | 0x00001002 |
| 65535 | 0x0000FFFF |
| 65536 | 0x00010000 |
| 131072 | 0x00020000 |
| 1234567890 | 0x499602D2 |
| -1 | 0xFFFFFFFF |
| -65535 | 0xFFFF0001 |
+------------+------------+
Your C# code in the question doesn't make much sense. Wrapping both strInt + strUser
into CONVERT(varbinary(120), N'" + strContextValue + "')
doesn't make sense.
The C# code should construct the binary array. The T-SQL trigger code expects that first 4 bytes of this array is @session
, next 4 bytes is @contextid
. bytes, not characters.
So, if you want to pass, say, 131072
decimal as @session
, 1234567890
decimal as @contextid
, plus myself$
string as extra info you should run the following T-SQL code:
declare @context_info varbinary(128); -- note 128 length here
set @context_info = 0x00020000;
-- note, there are no quotes around the constants, they are numbers, not strings
set @context_info = @context_info + 0x499602D2;
set @context_info = @context_info + CONVERT(varbinary(120), N'myself$');
-- note 120 length here, first 8 bytes are used by two integers
set context_info @context_info;
Run this code in SSMS, but replace of the last line with SELECT @context_info;
to see what it does. You'll get the following result:
+------------------------------------------------+
| (No column name) |
+------------------------------------------------+
| 0x00020000499602D26D007900730065006C0066002400 |
+------------------------------------------------+
You can see the binary representation of two integers plus binary representation of the unicode text string.
In C# you construct this code by concatenating hexadecimal representation of integers.
Note, that you should not enclose 0x00020000
and 0x499602D2
into quotes or CONVERT(varbinary, ...)
. You should enclose only the myself$
string into the CONVERT(varbinary, ...)
.
The C# code should look something like this:
string strUser = "myself$";
int iSession = 131072;
int iContextID = 1234567890;
StringBuilder sb = new StringBuilder();
sb.Append("declare @context_info varbinary(120);");
sb.Append("set @context_info = 0x");
sb.Append(iSession.ToString("X8"));
sb.Append(";");
sb.Append("set @context_info = @context_info + 0x");
sb.Append(iContextID.ToString("X8"));
sb.Append(";");
sb.Append("set @context_info = @context_info + CONVERT(varbinary(120), N'");
sb.Append(strUser);
sb.Append("');");
sb.Append("set context_info @context_info;");
string strContext = sb.ToSTring();
SqlCommand scContext = new SqlCommand(strContext, conn, tran);
scContext.ExecuteNonQuery();
See also C# convert integer to hex and back again