Reputation: 12002
I am trying to use EntityFrameworkCore
ORM to interact with my databases. By default, EntityFrameworkCore
seems to store enum as int instead of string.
However, I would like to store the value in the database as a string. I can see that EntityFrameworkCore
ships with a converter called EnumToStringConverter.
I am trying to use reflection to setup the model builder so I don't have to manually build each model.
The issue that I am running into is that EnumToStringConverter
accepts a generic type which must be an enum
. But since I am trying to use reflection here I am unable to pass the enum type when creating the converter
Here is what my code look like so far
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Get all DbSet<> properties that are defined in the DbContext
var modelTypes = typeof(DataContext).GetProperties()
.Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
.Select(x => x.PropertyType.GetGenericArguments().First())
.ToList();
foreach (Type modelType in modelTypes)
{
var properties = modelType.GetProperties();
foreach (var property in properties)
{
if (IsPrimaryKey(property))
{
// At this point we know that the property is a primary key
modelBuilder.Entity(modelType)
.Property(property.Name)
.UseSqlServerIdentityColumn()
.Metadata.BeforeSaveBehavior = PropertySaveBehavior.Ignore;
continue;
}
if (property.PropertyType.IsEnum)
{
// At this point we know that the property is an enum.
// Add the EnumToStringConverter converter to the property so that
// the value is stored in the database as a string instead of number
var converter = new EnumToStringConverter(); // if somehow I can change this code to something like var `new EnumToStringConverter(property.PropertyType);` the code would work
modelBuilder.Entity(modelType)
.Property(property.Name)
.HasConversion(converter);
continue;
}
}
}
}
The only issue with the above code is how EnumToStringConverter is constructed. If somehow I can provide a Type
to the constructor of the EnumToStringConverter
instead of passing it as a generic argument that would solve the problem.
Upvotes: 5
Views: 6499
Reputation: 6814
As of EF core v6.0.0-preview6
, there is a more elegant solution to register a ValueConverter globally. Since EFcore already ships with a EnumToStringConverter
, just add these lines to your DbContext
class:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
// Instead of numeric conversion that EFcore uses by default
configurationBuilder.Properties<Enum>().HaveConversion<string>();
}
and all properties of type Enum
will be serialized as string, rather than numbers.
Upvotes: 5
Reputation: 2867
was searching for the same, but didn't want to use the fluent approach.
plase the following to your enum property.
[Column(TypeName = "nvarchar(32)")]
this will automatically save it as a string. if placed in a base class this applies for all derived entities.
you could also register a type configuration
public class BaseEntityTypeConfiguration : IEntityTypeConfiguration<BaseEntity>
{
public void Configure(EntityTypeBuilder<BaseEntity> builder)
{
builder.Property(p => p.YourEnumProp).HasConversion<string>();
}
}
then you register it on the modelBuilder
mb.ApplyConfiguration(new BaseEntityTypeConfiguration());
Upvotes: 1
Reputation: 205779
As explained in the Pre-defined conversions documentation section:
For common conversions for which a built-in converter exists there is no need to specify the converter explicitly. Instead, just configure which provider type should be used and EF will automatically use the appropriate build-in converter. Enum to string conversions are used as an example above, but EF will actually do this automatically if the provider type is configured:
followed by an example.
Following that, you could simply use:
if (property.PropertyType.IsEnum)
{
// At this point we know that the property is an enum.
// Add the EnumToStringConverter converter to the property so that
// the value is stored in the database as a string instead of number
modelBuilder.Entity(modelType)
.Property(property.Name)
.HasConversion<string>(); // <--
continue;
}
Upvotes: 7