在实体框架中获取属性的映射列名称

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在实体框架中获取属性的映射列名称相关的知识,希望对你有一定的参考价值。

在我的项目中,我使用Entity Framework 6。我有这些实体:

   public class Person
    {
        [Key]
        public int Id { get; set; }

        public string Name { get; set; }

        public virtual ICollection<PersonRight> PersonRights { get; set; }
    }

 public class PersonRight
    {
        [Key]
        public int Id { get; set; }

        public string Name { get; set; }
    }

当我插入带有PersonRights的人员对象时,它在数据库中看起来像这样:

人员实体表:

dbo.People with columns Id, Name

PersonRights实体表

dbo.PersonRights with columns Id, Name, Person_Id

当我从数据库中加载人时,由于虚拟关键字使惰性加载功能变得容易,它还没有填充PersonRights属性-可以。

然后我获得了person对象的PersonRights,它也可以正常工作。

事实是,由于PersonRight实体中没有导航属性,因此该实体框架必须知道数据库中的这两个属性是由哪些列限制的。在数据库中,ther是连接PersonRights和People表的外键:

FK_dbo.PersonRights_dbo.People_Person_Id

问题是:有什么方法可以通过这两个属性将列名连接起来?如何通过代码获取字符串“ Person_Id”?

有一种方法可以找出数据库中有界的实体到哪个表:

http://www.codeproject.com/Articles/350135/Entity-Framework-Get-mapped-table-name-from-an-ent

非常感谢您的回答:)

编辑:

我发现列名属性在这里:

  var items = ((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace.GetItems(DataSpace.CSSpace);

但我仍然无法达到它,问题很奇怪,当我从该收藏夹中获得第一件商品时,它表明它的类型为System.Data.Entity.Core.Mapping.StorageEntityContainerMapping但是当我突然被foreach处理时,类型是System.Data.Entity.Metadata.Edm.GlobalItem ...

如何访问System.Data.Entity.Core.Mapping.StorageEntityContainerMapping项目,在哪里我也需要获得名为-AssociationSetMappings的列的集合

答案

您可以从存储模型中获取实际的字符串“ Person_Id”,但是您不能将该属性/列标识为外键。为此,您需要Person_Id存在于概念模型中。我仍然不太明白为什么您不希望在模型中使用它,但是这是从存储元数据中获取它的方法:

using ( var context = new YourEntities() )
{
  var objectContext = ( ( IObjectContextAdapter )context ).ObjectContext;
  var storageMetadata = ( (EntityConnection)objectContext.Connection ).GetMetadataWorkspace().GetItems( DataSpace.SSpace );
  var entityProps = ( from s in storageMetadata where s.BuiltInTypeKind == BuiltInTypeKind.EntityType select s as EntityType );
  var personRightStorageMetadata = ( from m in entityProps where m.Name == "PersonRight" select m ).Single();
  foreach ( var item in personRightStorageMetadata.Properties )
  {
      Console.WriteLine( item.Name );
  }
}
另一答案

对于EF6,我只能在DataSpace.CSSpace中找到映射(EntityTypeMapping将实体映射到表,而ScalarPropertyMapping将标量属性映射到列):

using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;

// ...

using ( var db = new YourContext() )
{
  var metadataWorkspace = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db)
  .ObjectContext.MetadataWorkspace;

  var itemCollection = ((StorageMappingItemCollection)metadataWorkspace
  .GetItemCollection(DataSpace.CSSpace));

  var entityMappings = itemCollection.OfType<EntityContainerMapping>().Single()
  .EntitySetMappings.ToList();

  var entityMapping = (EntityTypeMapping)entityMappings
    .Where(e => e.EntitySet.ElementType.FullName == typeof(TEntity).FullName)
    //or .Where(e => e.EntitySet.ElementType.Name == "YourEntityName")
    .Single().EntityTypeMappings.Single();

  var fragment = entityMapping.Fragments.Single();
  var dbTable = fragment.StoreEntitySet;

  Console.WriteLine($"Entity {entityMapping.EntityType.FullName} is mapped to table [{dbTable.Schema}].[{dbTable.Name}]");

  var scalarPropsMap = entityMapping.Fragments.Single()
  .PropertyMappings.OfType<ScalarPropertyMapping>();

  foreach(var prop in scalarPropsMap)
    Console.WriteLine($"Property {prop.Property.Name} maps to Column {prop.Column.Name}");

}

出于好奇,我使用上面的代码,因为System.Data.SqlClient.SqlBulkCopy需要在实体属性和表列之间进行映射。

以上是关于在实体框架中获取属性的映射列名称的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码优先 - 为 SqlQuery 配置映射

添加新实体标量时实体框架 4 映射片段错误

实体框架将 DateTimeOffset 映射到 SQL Server DateTime

实体框架6不适用于Temporal表

EF 开始的片段时有问题 具有潜在运行时冲突

实体框架 CTP4 代码优先:映射受保护的属性