So I asked one of my senior Dev for help to figure out Transaction scope related problem and he came to my desk and used a different overload on SqlBulkCopy and for SqlBulkCopyOptions parameter he did something like below:
SqlBulkCopyOptions options = (SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints);
It works now, but I don't get what a
bitwise or means here. I thought I had some understanding of it, never really used it, but this usage made me scratch my head. Yep, I didn't ask my senior to explain it to me.. I was hoping someone could help me understand what the statement does. Most of the bitwise or examples on the net are with some numbers, which I get (I think), but this?
An enum can be used as a flag if it has the
[Flags] attribute and has enum values which are independent of each other:
The definition of
SqlBulkCopyOptions is here: https://github.com/Microsoft/referencesource/blob/master/System.Data/System/Data/SqlClient/SqlBulkCopyOptions.cs
Ignore the use of bitshift syntax. The actual values are:
Name Hex Dec Pow 2 Binary Default = 0 = 0 = 0 = 00000000 KeepIdentity = 1 = 1 = 1 = 00000001 CheckConstraints = 2 = 2 = 2 = 00000010 TableLock = 4 = 4 = 3 = 00000100 KeepNulls = 8 = 8 = 4 = 00001000 FireTriggers = 10 = 16 = 5 = 00010000 UseInternalTxn = 20 = 32 = 6 = 00100000
Observe that each value is the next power of 2, which means in binary (last column) their bits are completely mutually exclusive.
This means you can combine them in a way that lets you see each value is set, for example, if you want
0x04. We use the OR operator, but on a per-bit basis, which gives us the behaviour we want:
00000001 00000100 OR -------- 00000101
Observe how the first and third bits are now
KeepIdentity | TableLock == 5).
This approach does not work for enum values which are not powers of two, for example, if
KeepIdentity had a value of
CheckConstraints had a value of
TableLock had a value of
3, then in binary they are:
00000001 KeepIdentity 00000010 CheckConstraints 00000011 TableLock
Observe that by analysing the bits of
00000011 it is impossible to determine if this is the combination of
CheckConstraints, or a single
TableLock value. This is why flags enum values must be: 1. Powers of 2, and 2: mutually-exclusive (with exceptions for shorthand and combination values).
The principle is exactly the same with an
enum as it is with numbers, as the underlying type of an
enum is always an integral type. If you look at the declaration of
SqlBulkCopyOptions, you'll see that its members have underlying values that are powers of two so that they can be combined in this way.