我可以从以下示例中看到如何获取OSpace类型的表名:
https://lowrymedia.com/2014/06/10/ef6-1-mapping-between-types-tables-including-derived-types/
但是如何从OSpace属性名称(即CLR类型属性)获取SSpace列名?
通过从相应的CSpace属性浏览MetadataProperties,我可以看到如果使用Fluid API或ColumnAttribute更改了包含列名的“Configuration”条目,但条目的值是EF的内部类。它有可能吗?
我已经浏览了一些关于此主题的答案,但没有一个考虑到Fluid API配置。
P.S。我正在寻找的特定属性是标量,如果这可以简化事情......
答案 0 :(得分:0)
要获取列名,必须首先在“结构空间”(EdmProperty
)中获取与该列关联的SSpace
。我在下面提供了执行此操作的代码。拥有EdmProperty
后,该列的名称就是EdmProperty.Name
:
string GetColumnName(DbContext context, PropertyInfo property) {
return GetStructuralSpaceEdmProperty(context, property).Name;
}
这基于an article。该文章为您提供了足够的信息,可以将其一直映射到结构EntityType
。我在末尾添加了一些内容来进行实际的属性映射,以获得代表列的EdmProperty
。如文章所述,这些API要求≥EntityFramework-6.1。
EdmProperty GetStructuralSpaceEdmProperty(DbContext context, PropertyInfo property) {
IObjectContextAdapter adapter = context;
var metadata = adapter.ObjectContext.MetadataWorkspace;
// First, you map the Object Space to the Conceptual Space.
var objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace);
var objectEntityType = metadata.GetItems<EntityType>(DataSpace.OSpace)
.Single(oet => objectItemCollection.GetClrType(oet) == property.DeclaringType);
// Note: we are assuming that CSpace and OSpace name their properties the
// same instead of trying to use EF’s own OSSpace mappings here.
var conceptualEntityType = metadata.GetItems<EntityType>(DataSpace.CSpace)
.Single(cet => objectEntityType.Name == cet.Name);
var conceptualEdmProperty = conceptualEntityType.Properties
.Single(ep => ep.Name == property.Name);
// Then you map the conceptual space onto the structural space.
var entitySet = metadata.GetItems<EntityContainer>(DataSpace.CSpace)
.Single().EntitySets
.Single(es => es.ElementType.Name == conceptualEntityType.Name);
var entityMapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single().EntitySetMappings
.Single(esm => esm.EntitySet == entitySet);
// The entity may be split to different tables or fragments.
var fragments = entityMapping.EntityTypeMappings
.SelectMany(etm => etm.Fragments);
var propertyMappings = fragments.SelectMany(f => f.PropertyMappings);
// Normal properties will be “ScalarPropertyMapping”.
// Depending on what information you are seeking or your
// model, you may be interested in other PropertyMapping.
var structuralSpaceProperty = propertyMappings
.OfType<ScalarPropertyMapping>()
.Single(pm => pm.Property == conceptualEdmProperty).Column;
return structuralSpaceProperty;
}
请注意,一旦您在结构空间中拥有EdmProperty
,就可以从中读取很多其他有用的属性。例如,对于SQL Server,对于true
/ NVARCHAR
,EdmProperty.IsUnicode
将是NCHAR
,对于false
/ VARCHAR
类型,CHAR
将是DataSpace.OSpace
而此属性在概念空间中未设置为有用的值。
Alex D. James的博客文章“Tip 10 — How to understand Entity Framework jargon”解释了API的某些术语,这些术语本身并不合理。 DataSpace.SSpace
代表“对象空间”,即.net POD类。 DataSpace.CSpace
代表“结构空间”,可能用术语“ SQL”中的“结构化”来命名,因此意味着它最直接地描述了后端数据库。 DataSpace.OCSpace
代表“概念空间”,似乎旨在成为“对象空间”和“结构空间”都可以映射到的中性空间。 DataSpace.CSSpace
代表从对象空间到概念空间的映射。我们绕过此映射,因为我们假设对象空间中的属性名称与.net类型中的属性名称相同。 ScalarPropertyMapping
代表将概念空间映射到结构空间。我们使用此映射是因为可以通过fluent API或ColumnAttribute
将模型配置为使用其他属性名称。
EF的元数据API似乎假定该API的使用者一定程度上了解EF的内部。它不是以对消费者有帮助的非常安全的方式制成的。例如,我们必须使用Enumerable.OfType<TResult>
到达ScalarPropertyMapping
的事实意味着,人们必须知道期望集合中包含EntityType
个实例。同样,MetadataWorkspace.GetItems<T>()
方法要求我们知道在元数据中可以找到的项目种类包括numpy.dstack
。因此,编写使用这些API映射部分的代码需要对EF内部或完整示例的深入了解。