如何使用Entity Framework Core配置其他用户定义的数据类型? [英] How do I configure other user defined data-type with Entity Framework Core?

查看:177
本文介绍了如何使用Entity Framework Core配置其他用户定义的数据类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Entiy Framework Core 2.1中使用了支架式实体。第三方数据库使用一些未定义的数据类型()似乎没有被EF-Core识别。

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.

根据到 Fluent API HasColumnType方法反向引擎:支持类型别名(用户定义的数据类型),这应该可以工作。但是,我不确定是否仅适用于预先修饰的/内置的类型,例如 Name 或任何类型。

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.

引擎会生成该

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

用于 Enumeration:smallint ,但将其翻译为SQL无法正常运行,因此会引发 SqlException

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?

推荐答案

我找到了一种解决方法。

I've found a workaround.

OnModelCreating 方法的和,我将删除生成的 ColumnType 注释:

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;
    }
}

用法:

modelBuilder.RemoveAnnotations(this, "Relational:ColumnType", new[] { "Enumeration" });

这篇关于如何使用Entity Framework Core配置其他用户定义的数据类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆