I'm doing a simple Entity change logging for our application.
One question that arises is that while the enumeration values for DbEntityEntry.State
property are clearly mutually exclusive (See MSDN), it is defined with Flags
attribute and the values are chosen as if they can be combined.
Is it safe to assume that the values are mutually exclusive? Why did they choose this path?
Is it safe to assume that the values are mutually exclusive?
If you are planning for future compatibility, then no. The authors might add a value which could be combined with one of the current values to cover a wider state. You are better off masking.
They might not, but being defined this way leaves that option open.
Why did they chose this path?
Perhaps, so that people wouldn't assume that the values are mutually exclusive.
Mostly, it allows one to do mask tests that cover more than one value in a single test:
if (state & (EntityState.Deleted | EntityState.Modified | EntityState.Added) != 0) …
This works because the values for the enum
uses a flag layout style where each has different bits set (or is deliberately defined in terms of another):
Detached = 1,
Unchanged = 2,
Added = 4,
Deleted = 8,
Modified = 16
Because of this, EntityState.Deleted | EntityState.Modified | EntityState.Added
has a value of 8 | 16 | 4
which is 28
. It would not work if the values where just incremented:
Detached = 1,
Unchanged = 2,
Added = 3,
Deleted = 4,
Modified = 5
Now EntityState.Deleted | EntityState.Modified | EntityState.Added
would have a value of 7
which is the same as EntityState.Detached | Entity.Unchanged | Entity.Deleted
.
The FlagsAttribute
is used to provide metadata indicating you are taking the former approach rather than the latter, so masking can work. The only effect it has directly on the type itself is in how ToString()
works, which is to provide a value more meaningful when taking this approach than not.
Internally, EntityState
is also used to include/exclude more than one state.
For example, in ObjectStateManager:
IEnumerable<IEntityStateEntry> IEntityStateManager.GetEntityStateEntries(EntityState state)
Usage in ObjectContext:
var entriesAffected = ObjectStateManager.GetObjectStateEntriesCount(EntityState.Added |
EntityState.Deleted |
EntityState.Modified);
From API-consuming-point-of-view, I think you can safely assume that the actual state of an entity can only be one of the options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With