2015-10-01 9 views
7

Robię proste rejestrowanie zmian jednostki dla naszej aplikacji. Pojawia się pytanie, że podczas gdy wartości wyliczeniowe dla właściwości DbEntityEntry.State są wyraźnie wykluczające się nawzajem (See MSDN), są zdefiniowane z atrybutem Flags, a wartości są wybierane tak, jakby można je łączyć.Dlaczego wyliczenie EntityState zdefiniowane przy użyciu FlagsAttribute

Czy można bezpiecznie założyć, że wartości wzajemnie się wykluczają? Dlaczego wybrali tę ścieżkę?

Odpowiedz

4

Czy można bezpiecznie założyć, że wartości wzajemnie się wykluczają?

Jeśli planujesz przyszłą kompatybilność, to nie. Autorzy mogą dodać wartość, którą można połączyć z jedną z bieżących wartości, aby objąć szerszy stan. Lepiej się maskować.

Mogą nie, ale zdefiniowanie w ten sposób pozostawia tę opcję otwartą.

Dlaczego wybrali tę ścieżkę?

Być może, aby ludzie nie zakładali, że wartości wzajemnie się wykluczają.

Głównie to pozwala zrobić testy maski, które obejmują więcej niż jedną wartość w jednym teście:

if (state & (EntityState.Deleted | EntityState.Modified | EntityState.Added) != 0) … 

To działa, ponieważ wartości dla enum wykorzystuje styl układu flag gdzie każdy ma różne bity ustawione (lub celowo określone w stosunku do innej)

Detached = 1, 
Unchanged = 2, 
Added = 4, 
Deleted = 8, 
Modified = 16 

Dlatego EntityState.Deleted | EntityState.Modified | EntityState.Added ma wartość 8 | 16 | 4 który 28. To nie będzie działać, jeśli wartości gdzie tylko inkrementacji:

Detached = 1, 
Unchanged = 2, 
Added = 3, 
Deleted = 4, 
Modified = 5 

Teraz EntityState.Deleted | EntityState.Modified | EntityState.Added miałoby wartość 7 która jest taka sama jak EntityState.Detached | Entity.Unchanged | Entity.Deleted.

Opcja FlagsAttribute służy do podawania metadanych wskazujących, że stosuje się pierwsze podejście, a nie drugie, więc maskowanie może działać. Jedynym efektem, jaki ma bezpośredni wpływ na sam typ, jest to, jak działa ToString(), co ma na celu zapewnienie wartości bardziej znaczącej przy podejmowaniu takiego podejścia, niż nie.

+1

Zgodnie z @CodeCaster, nie jest to atrybut "[Flags]", który "pozwala na wykonywanie testów maskowania" (http: // stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c). – haim770

+0

@ haim770 to nie jest. To pozwala na flagowy styl. '[Flagi]' oznacza wyliczenie jako wykorzystujące układ w stylu flagi. –

+1

@ JonHanna Czy możesz rozwinąć układ w stylu flagi? Lub link zostanie doceniony. – Alireza

1

Wewnętrznie, EntityState służy również do włączania/wyłączania więcej niż jednego stanu.

Na przykład w ObjectStateManager:

IEnumerable<IEntityStateEntry> IEntityStateManager.GetEntityStateEntries(EntityState state) 

Wykorzystanie w ObjectContext:

var entriesAffected = ObjectStateManager.GetObjectStateEntriesCount(EntityState.Added |     
                    EntityState.Deleted | 
                    EntityState.Modified); 

Od API czasochłonne-point-of-view, myślę, że można bezpiecznie założyć, że rzeczywisty stan podmiot może być tylko jedną z opcji.

+1

_ "Do tego wymagane są flagi." _ - nie, [używaj tylko dla '[Flagi]' służy do drukowania wartości wyliczenia] (http://stackoverflow.com/questions/8447/what-does- the-flags-enum-attribute-mean-in-c). To czysto metadane. – CodeCaster

+1

@CodeCaster, Cóż, nie jest * wymagane * prawie wszędzie, gdzie używasz maski z Enum. Ale w tym przypadku (i prawie we wszystkich innych przypadkach) jest tam z tego powodu. – haim770

+0

@CodeCaster Zaskoczyło mnie, że Flagi nie są do tego wymagane, a szybka przykładowa aplikacja weryfikuje Twój punkt widzenia. Właśnie w VS2015 dostaję ostrzeżenia intellisense dla robienia "operacji bitowych w enum nie oznaczonym atrybutem Flags". Dzięki – Alireza

Powiązane problemy