Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping enums to tables #1038

Open
jzabroski opened this issue Jun 28, 2019 · 8 comments
Open

Mapping enums to tables #1038

jzabroski opened this issue Jun 28, 2019 · 8 comments
Labels
feature A new feature (we all like those)

Comments

@jzabroski
Copy link
Collaborator

Given an enum, map it to a look-up table.

Here is a quick code spike of the concept:

    public void AddDataFor<TEnum>(Migration migration) where TEnum : System.Enum /* TODO [jaz] Requires C# 7.3 */
    {
        var builder = migration.Insert
            .IntoTable(nameof(TEnum))
            .InSchema("dbo")
            .WithIdentityInsert();
        foreach (var item in Enum.GetNames(typeof(TEnum)))
        {
            var x = (TEnum)Enum.Parse(typeof(TEnum), item);
            builder = builder.Row(new { Id = (Convert.ChangeType(x, Enum.GetUnderlyingType(typeof(TEnum)))), Name = x.GetDisplayName(), Description = x.GetDisplayDescription(), Order = x.GetDisplayOrder() });
        }
    }

This is effectively blocked by #1016 because you have to force the correct System.ComponentModel dll to load.

Some test cases:

  1. Currently presumes the table is an identity insert table.
  2. Currently presumes the look-up table uses (Id, Name, Description) tuple for column names. It would be nice to configure this in-line.
@jzabroski jzabroski added the feature A new feature (we all like those) label Jul 10, 2019
@jzabroski
Copy link
Collaborator Author

Would be good for lookup tables to mirror how ASP.NET Core Razor extension Html.GetEnumSelectList<DocumentType>() works

@krispetkov
Copy link

krispetkov commented Jun 5, 2020

Hi @jzabroski
Any plans to merge this functionality in near future?
Can you please tell me if there is some workaround or alternatives until an official support for enums is provided?
I'm thinking to expose my enums as integer values to the database and to handle the enum mapping inside my entities. Something like this (If there is something more clever than this approach I'd be happy to hear it):

public class Item
{
    public int ItemConditionId { get; set; }

    public ConditionEnum Condition
     {
          get => (ConditionEnum)ItemConditionId;
          set => ItemConditionId = (int)value;
     }
}

@jzabroski
Copy link
Collaborator Author

Merging this requires merging #1178 which is still a work in progress The reason is that Microsoft botched how they package System.ComponentModel.DataAnnotations nuget package such that it links the wrong assembly under certain conditions. The only way to force the right assembly is to re-map all of the FluentMigrator dependencies based on which version of the framework the user targets. That's what problem #1178 seeks to solve. In other words, #1178 solves a large enough part of #1016 so as to make this issue worth addressing.

As it stands, this issue can only work using the In-Process Runner.

@jzabroski
Copy link
Collaborator Author

You're free to use the In-Process Runner and copy-paste the above code into your project if that is what you would like to do, and report back on your success here. That would be helpful as I have not actually tested my assumption that #1178 fully resolves this dll loading error. (With an In-Process Runner, you can also force it to work via a DirtyAssemblyResolveHelper pattern, which is what BenchmarkDotNet and Fody use.)

@krispetkov
Copy link

@jzabroski thank you! I will give it a try after the weekend and will let you know if I had managed to adjust the sample to our scenario and if it works

@krispetkov
Copy link

@jzabroski I have found a clever way for resolving my issue here. It is related to the implementation of the NopCommerce's MigrationManager. (I'm going to make an analogue with the NopCommerce project because the project that I'm working on is proprietary and I cannot share much code but the logic is similar to NopCommerce handling their types mapping. I don't know if this analogy will be helpful but I will share it anyway.)

The solution for me was to add an extension code that will process every "unkown" enum type and add it to the mapping table (https://github.com/nopSolutions/nopCommerce/blob/3f6e16ce6f21805423520b54c89f375c263a440a/src/Libraries/Nop.Data/Migrations/MigrationManager.cs#L49)

The simple additional code is:

if (propType.IsEnum)
{
     _typeMapping.Add(propType, c => c.AsInt32());
}

And it can be plugged in on the following line: https://github.com/nopSolutions/nopCommerce/blob/3f6e16ce6f21805423520b54c89f375c263a440a/src/Libraries/Nop.Data/Migrations/MigrationManager.cs#L88

@jzabroski
Copy link
Collaborator Author

Interesting. I did not know about NopCommerce. How did you find it? Thanks for sharing, but... just so I understand, what was wrong with using the C# 7.3 type constraint proposal above (AddDataFor)? What limitation did it have?

@krispetkov
Copy link

In my previous company we were using their open source e-shop (I think they are the biggest open source project for e-commerce) and I was quite familiar with their architecture. Until recently they were using EntityFramework as an ORM but few days ago I read that they got rid of it and migrated to linq2db and FluentMigrator. The project that I'm currently working on is using the same projects (linq2db and FluentMigrator) and I decided to take a look of their way of managing the database layer.

As of the example proposed by you: their is nothing wrong with it, I tried it and it works. We are still in developing a proof of concept for our current task and I was exploring different ways to do the task and I decided to share it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new feature (we all like those)
Projects
None yet
Development

No branches or pull requests

2 participants