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

Custom type mapping #16

Closed
ErikEJ opened this issue May 19, 2018 · 17 comments
Closed

Custom type mapping #16

ErikEJ opened this issue May 19, 2018 · 17 comments
Labels
enhancement New feature or request reveng

Comments

@ErikEJ
Copy link
Owner

ErikEJ commented May 19, 2018

From @mbeckenbach on February 3, 2018 9:40

This project is awesome! It feels just like the db first workflow is coming back. But there is one feature that I am really missing.

In EF6 DB First, there is this amazing feature of mapping external types to properties.
This can be perfectly be used for transforming an integer culumn into a C# enum.

EF Core supports enum properties and maps those to integer columns in the database.

When doing a reverse engineer, all integer columns get generated as integer properties as it should be. Then one can simply change a properties type to some enum type, which exists in the project. Works great.

But when repeating the reverse engineer process to update the generated model from database, the file will be overwritten, which removes the modification of the properties type.

So I was thinking about how it would be possible to preserve this modification.

One way of doing this could be to create a code template for a specific class file. I had a look at EntityFrameworkCore.Scaffolding.Handlebars by @tonysneed but I dont see a way for doing this.

Another idea was to extend the efpt.config.json with an array of type mappings, that could be applied after code generation. Could something like that be implemented in your tool?

{
  "ContextClassName": "EfcoretestContext",
  "DatabaseType": 2,
  "IdReplace": false,
  "IncludeConnectionString": true,
  "OutputPath": "Models",
  "ProjectRootNamespace": "EFCoreTest",
  "SelectedToBeGenerated": 0,
  "Tables": [ "dbo.Posts", "dbo.Users" ],
  "UseDatabaseNames": false,
  "UseFluentApiOnly": true,
  "UseHandleBars": true,
  "UseInflector": true,
  "TypeMappings": [
    { "Column": "dbo.Posts.Category", "Type": "Enums.Categories" }
  ]
}

Copied from original issue: ErikEJ/SqlCeToolbox#621

@ErikEJ ErikEJ added ef-core-power-tools help wanted Extra attention is needed labels May 19, 2018
@ErikEJ
Copy link
Owner Author

ErikEJ commented May 19, 2018

Anything goes, and the tool is open source and welcomes contributions!

Could you show an example of what a class with a Enum would look like before and after this?

@ErikEJ
Copy link
Owner Author

ErikEJ commented May 19, 2018

From @mbeckenbach on February 4, 2018 7:57

Hi @ErikEJ, good to hear that.

A typical example for my use case would be like this. You have a custom enum in some folder/namespace and a generated class like the ones below.

namespace EFCoreTest.Enums
{
    public enum Categories
    {
        SomeCategory = 0,
        AnotherCategory = 1,
        MoreCategories = 2
    }
}
namespace EFCoreTest.Models
{
    public partial class Post
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public int Category { get; set; }
    }
}

After transformation the class would simply look like this:

public partial class Post
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public Enums.Categories Category { get; set; }
    }

@ErikEJ
Copy link
Owner Author

ErikEJ commented May 19, 2018

OK. since I just get the generated files, maybe it would be better with

 "TypeMappings": [
    { "Class:"Post", "Property":"Category", "Type": "Enums.Categories" }
  ]

Do a PR, perhaps?

https://github.com/ErikEJ/SqlCeToolbox/blob/master/src/GUI/ReverseEngineer20/EFCoreReverseEngineer.cs#L130

@ErikEJ
Copy link
Owner Author

ErikEJ commented May 19, 2018

From @mbeckenbach on February 6, 2018 6:54

I have never edited a vs extension. But i'll try at weekend. :-)
Thanks for the hint on the line.

@ErikEJ
Copy link
Owner Author

ErikEJ commented May 19, 2018

Great, let me know if you hit any stumbling blocks! (It is a bit more involved than a standard Nuget library)

@tonysneed
Copy link
Contributor

My Handlebars library handles this scenario now. See the project ReadMe for an example of adding an enum transformation and mapping it with a partial method.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Jan 15, 2019

@tonysneed Thanks. I assume that this will require changes to the users product code, and does not apply to EF Core Power Tools??

@tonysneed
Copy link
Contributor

tonysneed commented Jan 15, 2019 via email

@ErikEJ ErikEJ added enhancement New feature or request and removed help wanted Extra attention is needed labels Oct 8, 2019
@ErikEJ
Copy link
Owner Author

ErikEJ commented Oct 27, 2019

There are many options to do this, while preserving the modifications when reverse engineering is run a second time:

For the Enum, create at MyTypeEnum property in the partial entity class.

For special translations, use the OnModelCreating partial method to modify the model with Value Conversions https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions

@ErikEJ ErikEJ closed this as completed Oct 27, 2019
@AlexVPerl
Copy link

Thank you for creating this tool. I was looking for Enum mapping as well and came across this post.

I tried adding the following to efpt.renaming.json but it didn't have any effect:
"TypeMappings": [
{ "Class:"Post", "Property":"Category", "Type": "Enums.Categories" }
]

Could you please clarify what's the recommended way of mapping Enums with EF Core Power Tools? Thanks!

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 11, 2020

@AlexVPerl create a NonMapped enum property in a partial class

@AlexVPerl
Copy link

@ErikEJ thank you for prompt reply. Do you mean an Enum wrapper property that would set/get persisted numeric value?

If so, I was trying to avoid that since then EF will do in memory filtering when Enum is mentioned in the LINQ query.

Above, there is a mention of using OnModelCreating partial method with Value Conversions - this would be ideal. But it doesn't seem possible since all columns will be mapped in the auto generated class, and EF won't allow mapping 2 properties to single column. Having a way to ignore a column when using Rev. Eng. auto generation would make it possible to manually do Value Conversions for it. Or is there another way?

Thanks.

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 11, 2020

At the moment this is not supported. Happy to receive ideas or a PR for implementation.

@jamshally
Copy link

@ErikEJ thank you for prompt reply. Do you mean an Enum wrapper property that would set/get persisted numeric value?

If so, I was trying to avoid that since then EF will do in memory filtering when Enum is mentioned in the LINQ query.

Above, there is a mention of using OnModelCreating partial method with Value Conversions - this would be ideal. But it doesn't seem possible since all columns will be mapped in the auto generated class, and EF won't allow mapping 2 properties to single column. Having a way to ignore a column when using Rev. Eng. auto generation would make it possible to manually do Value Conversions for it. Or is there another way?

Thanks.

@AlexVPerl , @ErikEJ - I am also looking for a way to Map an enum value to a string. If I understand correctly, the one thing blocking @AlexVPerl's suggested solution was the ability to ignore a column. Well, it seems that this feature was recently added via a pull request: #572

I'm going to give that a go, but leaving this train of thought here for others to help save them some time. I'll make another note if I have anything interesting to report

@jamshally
Copy link

I'm going to give that a go, but leaving this train of thought here for others to help save them some time. I'll make another note if I have anything interesting to report

  • Well, for me, good news and bad news... it looks like ignoring a column is new baked right into the UI! (Nice feature@ErikEJ)
  • In my case, it seems I can not ignore the column I want to transform into an Enum because it part of the primary key... so, I will find a different approach

@ErikEJ
Copy link
Owner Author

ErikEJ commented Feb 22, 2021

Create a proper, surrogate primary key?

@ErikEJ
Copy link
Owner Author

ErikEJ commented Aug 19, 2022

Custom enum mapping is now available with EF Core 7 and T4 templates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request reveng
Projects
None yet
Development

No branches or pull requests

4 participants