question

YitongPhou-7639 avatar image
0 Votes"
YitongPhou-7639 asked YitongPhou-7639 edited

Hasconversin Enum

I am trying to do Enum conversion in my dataContext. However, it always give me

System.InvalidCastException: 'Unable to cast object of type 'System.Int32' to type 'System.String'.'


  var converter = new EnumToStringConverter<Role>();
    
             modelBuilder.Entity<Account>()
                 .Property(e => e.Role)
                 .HasConversion(converter);
    
 or
  var converter = new EnumToStringConverter<Role>();
    
             modelBuilder.Entity<Account>()
                 .HasConversion(
                     v => v.ToString(),
                     v => (Role)Enum.Parse(typeof(Role), v));

.........
Enum field in models
........
public Role Role { get; set; }

 namespace Project1.Models
 {
     public enum Role
     {
          Admin = 0,
          User = 1
     }
 }


dotnet-entity-framework-core
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

In models for the Account entity:
public Role Role { get; set; }


I am using VS2022, dotnet core 6.

Any one?

Thank you.

0 Votes 0 ·

@YitongPhou-7639, Welcome to Microsoft Q&A, I noted that you almost used the same code with the Microsoft doc value-conversions. However, I noted that you missed property.

Maybe you could try to state your property like following:

 modelBuilder.Entity<Account>()
                  .Property(e => e.yourproperty)
                  .HasConversion(
                      v => v.ToString(),
                      v => (Role)Enum.Parse(typeof(Role), v));




0 Votes 0 ·

Thanks for your input. I already tried it bebore I reached out... It doesn't work

Thanks.

0 Votes 0 ·

1 Answer

karenpayneoregon avatar image
0 Votes"
karenpayneoregon answered YitongPhou-7639 edited

I have a code sample.

  • Class project

  • Console project

  • T4 template, not part of the question but is useful for new enum members stored in a database

Model

 public partial class Book
 {
     public int BookId { get; set; }
     public string Title { get; set; }
     public int BookCategory { get; set; }
 }


BookCategory

 public enum BookCategory
 {
     SpaceTravel = 1,
     Adventure = 2,
     Romance = 3,
     Sports = 4,
     Automobile = 5
 }

HasConversion

 protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
     modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
    
     // Value converter for enum
     modelBuilder
         .Entity<Book>()
         .Property(e => e.BookCategory)
         .HasConversion(item => item, 
             item => (int)Enum.Parse(typeof(BookCategory), 
                 item.ToString()));
    
     modelBuilder.HasSequence<int>("seq_test").HasMin(1);
    
     OnModelCreatingPartial(modelBuilder);
 }

Console app

 namespace EntityFrameworkEnumSimpleApp
 {
     class Program
     {
         static void Main(string[] args)
         {
             using (var context = new BookContext())
             {
                 AddRecords(context);
                 ShowRecords(context);
             }
                
             Console.ReadLine();
         }
    
         private static void ShowRecords(BookContext context)
         {
             var table = new Table()
                 .RoundedBorder()
                 .AddColumn("[b]Id[/]")
                 .AddColumn("[b]Title[/]")
                 .AddColumn("[b]Category[/]")
                 .Alignment(Justify.Center)
                 .BorderColor(Color.LightSlateGrey)
                 .Title("[yellow]Books[/]");
    
             var books = context.Book.ToList();
    
             foreach (var book in books)
             {
                 table.AddRow(book.BookId.ToString(), book.Title, Enum.GetName(typeof(BookCategory), book.BookCategory)!);
             }
    
             AnsiConsole.Write(table);
         }
    
         private static void AddRecords(BookContext context)
         {
             if (context.Book.ToList().Count == 0)
             {
                 List<Book> list = new()
                 {
                     new() { BookCategory = 5, Title = "First book" },
                     new() { BookCategory = 3, Title = "Second book" },
                     new() { BookCategory = 1, Title = "Third book" }
                 };
    
                 context.AddRange(list);
                 Console.WriteLine($"Books saved {context.SaveChanges()}");
             }
         }
    
         [ModuleInitializer]
         public static void Init()
         {
             Console.Title = $"EF Core enums simple";
         }
     }
 }

Results

204392-bookcategory.png





bookcategory.png (8.5 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sorry about my previous comments (which have been deleted).
You app works on older version (I guessed). With c#10 and netCORE 6 in VS2022, it is still not working.

The only way I can make it to work is to add
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
public Role Role { get; set; }

To Account models
and

builder.Services.AddControllers().AddNewtonsoftJson(
options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.TypeNameHandling = TypeNameHandling.None;
options.SerializerSettings.Formatting = Formatting.Indented;
}
)
.AddXmlSerializerFormatters()
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
})
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()
);


to program.cs



Thanks.

0 Votes 0 ·