3

I'm using scaffolded entities with Entiy Framework Core 2.1. The 3rd party database uses some unser defined data types (that I didn't know about) that don't seem to be recognized by EF-Core.

According to The Fluent API HasColumnType Method and Reverse Enginer: Support type aliases (user-defined data types) this should work. However, I'm not sure if only for precofigured/built-in types like Name or any types.

The engine generates this

entity.Property(e => e.Status).HasColumnType("Enumeration");

for Enumeration:smallint but translating it to SQL doesn't work well so it throws a SqlException

Class         16  byte
LineNumber    1   int
Message       "Type Enumeration is not a defined system type."    string
Number        243 int
Procedure     ""  string
Server        "..."   string
Source        ".Net SqlClient Data Provider"  string
State         2   byte

Is there a way to define other user defined data types or fix this in any other way?

6
  • 1
    You may want to submit a new issue about this. Commented Jul 11, 2018 at 15:56
  • 1
    Also, type aliases (aka domains) are very different from user-defined types (UDTs). Commented Jul 11, 2018 at 15:59
  • @bricelam done Commented Jul 11, 2018 at 17:47
  • 2
    Thanks! We suspect it's a UDT too. Unfortunately, these have limited support on .NET Core... Commented Jul 11, 2018 at 21:50
  • 1
    @bricelam take a look at my answer. There is a workaround. Commented Jul 12, 2018 at 7:30

1 Answer 1

1

I've found a workaround.

At the and of the OnModelCreating method I'll just remove the generated ColumnType annotation:

  modelBuilder
    .Entity(typeof(MyEntity))
    .Property(nameof(MyEntity.Status))
    .Metadata
    .RemoveAnnotation("Relational:ColumnType");

A small helper function that goes over all entities and removes that annotation automatically from all properties that have it should be enough for now.

public static class ModelBuilderExtensions
{
    public static ModelBuilder RemoveAnnotations<TDbContext>(this ModelBuilder modelBuilder, TDbContext context, string name, IList<string> values) where TDbContext : DbContext
    {
        var bindingFlags = 
            BindingFlags.Instance | 
            BindingFlags.Public | 
            BindingFlags.DeclaredOnly;

        var entityMethod =
            typeof(ModelBuilder)
                .GetMethods()
                .Single(m =>
                    m.Name == nameof(ModelBuilder.Entity) &&
                    m.GetGenericArguments().Length == 1 &&
                    m.GetParameters().Length == 0
                )
                .GetGenericMethodDefinition();

        foreach (var contextProperty in typeof(TDbContext).GetProperties(bindingFlags))
        {
            var entity =
                contextProperty
                    .PropertyType
                    .GetGenericArguments()
                    .SingleOrDefault();

            if (entity is null)
            {
                continue;
            }

            // Only the generic overload returns properties. The non-generic one didn't work.
            var generitcEntityMethod = entityMethod.MakeGenericMethod(entity);

            foreach (var property in entity.GetProperties(bindingFlags))
            {
                var entityTypeBuilder = (EntityTypeBuilder)generitcEntityMethod.Invoke(modelBuilder, null);

                if (entityTypeBuilder.Metadata.FindProperty(property) is null)
                {
                    continue;
                }

                var annotation = 
                    entityTypeBuilder
                        .Property(property.Name)
                        .Metadata
                        .FindAnnotation(name);

                if (values.Contains(annotation?.Value))
                {
                    entityTypeBuilder
                        .Property(property.Name)
                        .Metadata
                        .RemoveAnnotation(name);
                }
            }
        }
        return modelBuilder;
    }
}

Usage:

modelBuilder.RemoveAnnotations(this, "Relational:ColumnType", new[] { "Enumeration" });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.