从ospace属性名称获取列名(sspace)

时间:2015-07-04 09:53:46

标签: entity-framework entity-framework-6

我可以从以下示例中看到如何获取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。我正在寻找的特定属性是标量,如果这可以简化事情......

1 个答案:

答案 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 / NVARCHAREdmProperty.IsUnicode将是NCHAR,对于false / VARCHAR类型,CHAR将是DataSpace.OSpace而此属性在概念空间中未设置为有用的值。

随机信息

EF中的空格

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 APIColumnAttribute将模型配置为使用其他属性名称。

API混乱

EF的元数据API似乎假定该API的使用者一定程度上了解EF的内部。它不是以对消费者有帮助的非常安全的方式制成的。例如,我们必须使用Enumerable.OfType<TResult>到达ScalarPropertyMapping的事实意味着,人们必须知道期望集合中包含EntityType个实例。同样,MetadataWorkspace.GetItems<T>()方法要求我们知道在元数据中可以找到的项目种类包括numpy.dstack。因此,编写使用这些API映射部分的代码需要对EF内部或完整示例的深入了解。