实体框架 - 如何获取列

本文关键字:获取 何获取 框架 实体 | 更新日期: 2023-09-27 17:57:12

我希望获得列名称,类型以及该列是否是实体框架中表对象的PK的列表。

如何在 C# (4.0) 中执行此操作(理想情况下是通用的)?

获胜的答案将是高效且最重要的是通用的答案。

实体框架 - 如何获取列

知道了 - 我使用了基于 linq 的反射查询:

IEnumerable<FieldList> properties = from p in typeof(T).GetProperties()
                                    where (from a in p.GetCustomAttributes(false)
                                    where a is EdmScalarPropertyAttribute   
                                    select true).FirstOrDefault()

排序!感谢您的建议。

仅供参考 - 我正在使用 LINQ 创建一个动态 where 子句,动态 lambda 表达式来构建例如搜索,默认情况下会自动搜索所有列。 但是我还需要列名来验证,因为我将允许它被覆盖,这些调用将通过 javascript ajax post 完成,其输入不可信 - 因此需要验证列名。

我使用上述方法将结果放入具有名为FieldName,FieldType,PrimaryKey的属性的自定义对象中。哒。

进一步定制

IEnumerable<FieldList> properties = from p in typeof(T).GetProperties()
                                    where (from a in p.GetCustomAttributes(false)
                                    where a is EdmScalarPropertyAttribute
                                    select true).FirstOrDefault()
                                    select new FieldList
                                    {
                                       FieldName = p.Name,
                                       FieldType = p.PropertyType,
                                       FieldPK = p.GetCustomAttributes(false).Where(a => a is EdmScalarPropertyAttribute && ((EdmScalarPropertyAttribute)a).EntityKeyProperty).Count() > 0
                                     };    

如果你只想要列名那么,我得到了最好的答案:
var properties = (from t in typeof(YourTableName).GetProperties() select t.Name).ToList(); var name= properties[0];

如果您不想使用反射,请参阅此处的答案。将下面的实体名称替换为您的实体名称

var cols = from meta in ctx.MetadataWorkspace.GetItems(DataSpace.CSpace)
                       .Where(m=> m.BuiltInTypeKind==BuiltInTypeKind.EntityType)
                    from p in (meta as EntityType).Properties
                       .Where(p => p.DeclaringType.Name == "EntityName")
                   select new
                      {
                       PropertyName = p.Name,
                       TypeUsageName = p.TypeUsage.EdmType.Name, //type name
                       Documentation = p.Documentation != null ?               
                                       p.Documentation.LongDescription : null //if primary key
        };

如果有人还在看,这是我是如何做到的。这是 DBContext 的扩展方法,该方法采用类型并返回物理列名及其属性。

这利用对象上下文来获取物理列列表,然后使用"PreferredName"元数据属性将每个列映射到其属性。

由于它使用对象上下文,因此它会启动数据库连接,因此第一次运行会很慢,具体取决于上下文的复杂性。

public static IDictionary<String, PropertyInfo> GetTableColumns(this DbContext ctx, Type entityType)
{
    ObjectContext octx = (ctx as IObjectContextAdapter).ObjectContext;
    EntityType storageEntityType = octx.MetadataWorkspace.GetItems(DataSpace.SSpace)
        .Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).OfType<EntityType>()
        .Single(x => x.Name == entityType.Name);
    var columnNames = storageEntityType.Properties.ToDictionary(x => x.Name,
        y => y.MetadataProperties.FirstOrDefault(x => x.Name == "PreferredName")?.Value as string ?? y.Name);
    return storageEntityType.Properties.Select((elm, index) =>
            new {elm.Name, Property = entityType.GetProperty(columnNames[elm.Name])})
        .ToDictionary(x => x.Name, x => x.Property);
}

要使用它,只需创建一个辅助静态类,并添加上面的函数;然后就像调用一样简单

var tabCols = context.GetTableColumns(typeof(EntityType));
typeof(TableName).GetProperties().Select(x => x.Name).ToList();

我没有适合您的代码示例,但为了指向正确的方向,您可能需要研究如何使用 Sql 管理对象 (SMO); 您可以使用它来获取 Sql Server 实例的对象层次结构,然后可以枚举并挑选出所需的信息。

查看这组教程,帮助您开始编程 - http://www.codeproject.com/KB/database/SMO_Tutorial_1.aspxhttp://www.codeproject.com/KB/database/SMO_Tutorial_2.aspx

如果使用 DB First 或 Model First,请打开在文本编辑器中生成的 .edmx 文件 EF。它只是一个XML文件,它包含您需要的一切。这是我的一个模型的例子。请注意,我使用的是 Oracle 的 EF 驱动程序,因此您的驱动程序看起来并不相同(但它应该非常接近)。

      <实体类型名称>
        <钥匙>
          <属性引用名称 />
          <属性类型 名称="id" 可为空="假" 精度="8" 刻度="0" />
          <属性类型 名称="创建者 ID" 可为空="假" 精度="8" 刻度="0" />
          <属性类型 名称="创建日期" 可为空="假" />
          <属性类型 名称="部门 ID" 可为空="假" 精度="4" 刻度="0" />
          <属性类型 名称="Name_E" 可为空="假" 最大长度="2000" 固定长度="假" Unicode="false" />
          <属性类型 名称="Name_F" 最大长度="2000" 固定长度="假" Unicode="false" />
          <属性类型 名称="更新的ById" 精度="8" 刻度="0" />
          <属性类型 名称="更新日期" />
          <属性类型 名称="时间戳" 可为空="假" 精度="6" />
          <导航属性名称 关系="StrategicPlanningModel.R_51213" 从角色="STRATEGIC_PLAN" 到角色="STRAT_ANNUAL_PLAN" />
          <导航属性名称 关系="StrategicPlanningModel.R_51212" 从角色="STRATEGIC_PLAN" 到角色="部门" />
          <导航属性名称 关系="StrategicPlanningModel.R_51210" 从角色="STRATEGIC_PLAN" 到角色="员工" />
          <导航属性名称 关系="StrategicPlanningModel.R_51211" 从角色="STRATEGIC_PLAN" 到角色="员工" />
          <属性类型 名称="Desc_E" 最大长度="2000" 固定长度="假" Unicode="false" />
          <属性类型 名称="Desc_F" 最大长度="2000" 固定长度="假" Unicode="false" />
          <导航属性名称 关系="StrategicPlanningModel.R_51219" 从角色="STRATEGIC_PLAN" 到角色="STRATEGIC_PLAN_GOAL" />
        
      
    

您可以使用 XML 解析器来解析文件并获取所需的内容。.edmx 文件包含实体和 SQL 表的数据,因此您需要确保获得正确的部分才能获得所需的内容。

仅获取没有表关系的列名,例如外键。

var columnNames = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && !p.GetGetMethod()!.IsVirtual)
            .Select(property => property.Name)
            .ToList();

在数据库上下文中,关系通常被标记为虚拟对象(除非在我的Postgres测试中)。