我有一堆模型都使用了我创建的类。它们具有 Measurement
类型的属性。此 Measurement
类本身不是我想要映射到数据库表的实体或模型。它只是一种用于成对传递值和单位的类型,以及一组用于管理对这些值和单位的操作的方法和运算符。
我创建了一个 ValueConverter
,这样我就可以在我的模型中将这种类型的属性表示为数据库中的字符串。
ValueConverter<Measurement, string> measurementConverter = new ValueConverter<Measurement, string>
(
v => v.ToString(),
v => new Measurement(v)
);
然后,我的计划是,在 DbContext
的 OnModelCreating()
方法中,循环遍历我的所有实体及其属性,并使用 property。 SetValueConverter(measurementConverter);
如果它们是 Measurement
类型。这样,我模型中的所有测量值都可以自动保存到数据库并从数据库中加载,而且我不必在模型中保留额外的字符串表示字段。
这是我正在谈论的循环:
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entity.GetProperties())
{
if(property.ClrType == typeof(Measurement)) { property.SetValueConverter(measurementConverter); }
}
}
问题在于 GetProperties()
方法。它的文档摘要是这样说的:
This API only returns scalar properties and does not return navigation properties
结果是它根本没有返回我的任何 Measurement
属性。我相信 Entity Framework 认为 Measurement
类实际上是它自己的模型,因此它不会将其视为普通属性。当然,这意味着 ValueConverter
从未在其上设置,并且整个解决方案无法按我希望的方式工作。
我的第一个想法是将 Measurement
类改为一个结构,因为它已经是不可变的,并且没有真正的理由说明为什么它一开始就不能成为一个结构。这难道不会让 Entity Framework 清楚地知道这是一个标量属性并且应该包含在 GetProperties()
返回中吗?我是这么想的,但显然不是。更改后我仍然得到相同的行为。
我想避免在每个模型中的每个 Measurement
属性上放置一个属性,所以如果有任何方法可以告诉 Entity Framework 所有这些属性实际上都是可绑定(bind)的,那就太棒了.如果不是,那我该如何标记它们呢?
谢谢。
最佳答案
令人恼火的是,EF Core 目前没有提供映射用户定义类型的好方法。 NET Topology 套件使用了一种插件机制,但它需要太多管道代码。
因此,GetProperties
问题:
This API only returns scalar properties and does not return navigation properties
好吧,一旦您知道 EF Core 将您的类型视为实体,因此将该类型的属性视为导航属性,您就可以使用 GetNavigations
而不是 GetProperties
:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var navigation in entityType.GetNavigations().ToList())
{
if (navigation.ClrType == typeof(Measurement))
{
var entityTypeBuilder = modelBuilder.Entity(entityType.ClrType);
entityTypeBuilder
.Property<Measurement>(navigation.Name)
.HasConversion(measurementConverter);
}
}
}
唯一的问题是这个
var entityTypeBuilder = modelBuilder.Entity(entityType.ClrType);
正如我们在这里看到的EF Core configuration problem with owned type used in 2 different classes ,这对于拥有的实体类型来说是有问题的(不起作用)。让它工作需要使用内部 API:
var entityTypeBuilder = new EntityTypeBuilder(entityType.AsEntityType().Builder);
在您自己的回答中,您说使用内部 API 是“不好的”。恕我直言,唯一不好的是图书馆没有为此提供“好的”公共(public) API。另一方面,幸运的是,所有“内部”EF Core API 都是公开可用的,并且可以在公共(public) API 不够用的情况下用于此类场景。唯一的区别是升级新版本时必须观察 API 变化并进行相应更新。考虑到他们多次破坏公共(public) API,这应该不是什么大问题。
关于c# - IMutableEntityType.GetProperties() 不包含我想要的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57697901/