EF Core : Conversion d'un enum à 3 état en bool?
Bonjour,
Je suis à la recherche d'un convertisseur générique d'un enum à 3 entrées en bool? (et pourquoi pas 2 en bool).
Dans un premier temps, j'ai trouvé une façon assez simple de le faire avec HasConvertion<MonEnum> :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var values = Enum.GetValues(typeof(MonEnum))
.Cast<MonEnum>()
.ToList();
modelBuilder.Entity<MonObjet>()
.Property(o => o.MaPropriete)
.HasColumnType(typeof(bool?).Name)
.HasConversion<MonEnum>(o => o == values.Min() ? null : o == values.Max(),
o => o == MonEnum.Value1 ? values.Min() : o == MonEnum.Value3 ? values.Max() : values[1]);
} |
Le <MonEnum> souligné n'est pas obligatoire, C# reconnaissant le type.
Le problème de cette méthode est que je dois faire cela pour chaque propriété de chaque champ ayant un enum à 3 entrées et j'aimerais que ce soit automatique et générique sans avoir <MonEnum> alors j'ai préparé ce code pour tenter d'y répondre :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| modelBuilder.Model
.GetEntityTypes()
.ForEach(o => o.GetProperties()?
.Where(p => o.ClrType.GetProperty(p.Name)?.PropertyType.IsEnum == true)
.ForEach(
p =>
{
var propertyType = o.ClrType.GetProperty(p.Name)?.PropertyType;
if (!propertyType.IsEnum)
propertyType = propertyType?.GenericTypeArguments[0];
var dico = new SortedDictionary<int, string>();
foreach (int item in propertyType.GetEnumValues())
dico[item] = propertyType.GetEnumName(item);
var property = builder.Entity(o.Name)
.Property(p.Name);
if (dico.Count == 3)
{
property.HasColumnType(typeof(bool?).Name);
var converter = new BoolNullableConverter(propertyType, dico);
property.HasConversion(converter);
}
})); |
Avec le convertisseur suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class BoolNullableConverter : ValueConverter<Enum, bool?>
{
public BoolNullableConverter(
Type propertyType,
SortedDictionary<int, string> keyValuePairs,
ConverterMappingHints? mappingHints = null)
: base(o => o == (Enum)Enum.ToObject(propertyType, keyValuePairs.First().Key) ?
null :
o == (Enum)Enum.ToObject(propertyType, keyValuePairs.Last().Key),
o => o == null ?
(Enum)Enum.ToObject(propertyType, keyValuePairs.First().Key) :
o == true ?
(Enum)Enum.ToObject(propertyType, keyValuePairs.Last().Key) :
(Enum)Enum.ToObject(propertyType, keyValuePairs.Take(2).Last()),
mappingHints)
{
}
} |
Heureux que visual studio ne râle pas sur mon code, je lance le truc, et là :aie:
"Converter for model type 'Enum' cannot be used for 'MonObjet.MaPropriete' because its type is 'MonEnum'."
Quelle est mon erreur ? Auriez-vous le petit bout de code me permettant de faire ce que je cherche à faire ?
Et si vous voyez quelques maladresse ou améliorations dans mon code, je prends :ccool:
Merci d'avance et bonne Ascension...
Infos techniques : Framework 4.8 + EF Core 3.14
Pour ceux que cela peut intéresser
Bonsoir,
Voilà, j'ai trouvé ma réponse, je ne sais plus où, si utilisation d'un convertisseur alors le champ n'accepte pas de valeur null.
Du coup, je ne peux pas faire ça directement mais j'ai une autre solution :
Code:
1 2 3 4 5 6 7 8 9
| public enum MyEnum { V1, V2, V3 }
public class MyClass
{
[NotMapped]
public MyEnum MaPropriete{ get; set; }
public bool? MaProprieteTripleState { get => MaPropriete.TriState(); set => MaPropriete= value.TriState<MonEnum>(); }
} |
Et dans une class static, pour une extension :
Code:
1 2 3 4 5 6 7 8 9 10 11
| public static bool? TriState<T>(this T This) where T : Enum
{
var values = Enum.GetValues(typeof(T))
.Cast<T>()
.ToList();
return This.Equals(values.Min()) ? null : This.Equals(values.Max());
}
public static T TriState<T>(this bool? This) where T : Enum
=> ((bool?)This).TriState<T, bool?>(true, false, true); |
Qu'en pensez-vous ?
De plus, j'ai appris la raison pour laquelle on utilise un virtual pour les collections, d'après ce lien, https://stackoverflow.com/questions/...active#tab-top :
Chaque ICollection est chargée sans mettre de Include...