I have this enum :
[Flags]
public enum Actions
{
None = 0,
MoveUp = 1,
MoveDown = 2,
MoveRight = 3,
MoveLeft = 4
}
and I would like have the columns of a table like this:
Id | UserId | Actions
.. | .. | ..
I'm confused as to how I can store the enum since the user can have more than one action, and I don't want to use another table to store actions. I have more than 50 actions, which is why I used the Flags attribute.
actionssUser = Actions.MoveUp | Actions.MoveRight | .......
First off, it's important to note that your flags enum is not properly configured, and is almost certainly not behaving the way you expect. As stated in the documentation:
The last sentence is of particular importance here, as you'll see in a moment.
Example
Let's put that into practice using your example. Your enum should instead look like:
Now, let's say, you set your enum value to include the
MoveUpandMoveRightflags:You can now convert it to an integer using a simple cast:
In this example, that will return 5. At this point, you can simply store that value in SQL Server as a standard e.g.
TINYINTcolumn (assuming you have eight or fewer options), as @Charlieface noted in the comments.Or, even better yet, you can cast it as a
byte, and store it as aBINARY(4)column—or aBINARY(50)with your full enum—as @meysam-asadi suggests:Explanation
If you look at the above values, the only possible combination that can ever return 5 when you are using the powers of 2 is 1 (
MoveUp) and 4 (MoveRight).If you understand binary, this is even more intuitive as your bit array will look like the following:
Or, from right to left:
Basically, each subsequent power of two will flip the next digit from 0 to 1, marking that option as flagged.
Resurrecting your flags
On the return trip, the process looks much the same, just in reverse. So when you retrieve the value from the database, you can simply cast it back to an enum:
(Where
actionsValueis whatever value you retrieve from the database.)Limitations
There are limitations here! If you use this approach, you need to be certain that your values are stable. If you attempt to inject a value into your existing enum, you'll need to recalculate all of your previous records accordingly. To avoid this, you'll need to add any new values to the end of your enum. If this isn't an acceptable limitation, you're probably better off storing these values in individual columns.
Shorthand
This is an aside, but as you have over fifty enum values, a shorthand for assigning powers of two that’s easier to count:
This is easier than trying to write out e.g., 2^50 as 1125899906842624