c# - 如何使用 Entity Framework Core 配置其他用户定义的数据类型?
问题描述
我正在使用带有 Entiy Framework Core 2.1 的脚手架实体。第 3 方数据库使用了一些未定义的数据类型(我不知道),这些数据类型似乎无法被 EF-Core 识别。
根据Fluent API HasColumnType Method和Reverse Enginer: Support type aliases (user-defined data types)这应该可以工作。但是,我不确定是否仅适用于预配置/内置类型Name
或任何类型。
引擎生成这个
entity.Property(e => e.Status).HasColumnType("Enumeration");
forEnumeration:smallint
但将其翻译为 SQL 效果不佳,因此它会抛出一个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
有没有办法定义其他用户定义的数据类型或以任何其他方式解决这个问题?
解决方案
我找到了解决方法。
在OnModelCreating
方法的 and 中,我将删除生成的ColumnType
注释:
modelBuilder
.Entity(typeof(MyEntity))
.Property(nameof(MyEntity.Status))
.Metadata
.RemoveAnnotation("Relational:ColumnType");
一个小的帮助函数,它遍历所有实体并自动从所有具有它的属性中删除该注释,现在应该足够了。
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" });
推荐阅读
- r - 如何使用 R 在散点图中的线之间添加不同的背景颜色?
- swift - 带 URLSession 的 PromiseKit
- javascript - 未捕获的类型错误:$(...)[0].reset 不是函数
- android - 膨胀类 TextView 的错误导致活动无法启动
- java - 通过 JNI 从 Java 代码调用 .net DLL 不返回
- java - 在 Android 的 ArrayList 中添加项目时出错
- c++ - 在 Windows 中配置 CMake 以从命令行使用 clang 以获得现代 OpenMP 支持
- regex - Nginx:通配符 server_name
- java - 模拟外部 Web 服务进行集成测试
- gatsby - 使用 gatsby 和 netlify 在构建时获取后在客户端上保留 api 数据