实体框架 - 如何获取列?

时间:2011-05-19 09:33:15

标签: c# entity-framework generics asp.net-mvc-3

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

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

获胜的答案将是有效的,最重要的是一般的答案。

8 个答案:

答案 0 :(得分:10)

知道了 - 我使用了基于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属性的自定义对象中。 Ta daaa。

使用

进一步自定义
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
                                     };    

答案 1 :(得分:7)

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

答案 2 :(得分:5)

如果您不想使用反射,请参阅回答here。将实体名称替换为您的实体名称

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
        };

答案 3 :(得分:1)

如果还有人在看,我就是这样做的。 这是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));

答案 4 :(得分:1)

typeof(TableName).GetProperties().Select(x => x.Name).ToList();

答案 5 :(得分:0)

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

看一下这套教程,让您开始编程 - http://www.codeproject.com/KB/database/SMO_Tutorial_1.aspx http://www.codeproject.com/KB/database/SMO_Tutorial_2.aspx

答案 6 :(得分:0)

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

        <EntityType Name="STRATEGIC_PLAN">
          <Key>
            <PropertyRef Name="Id" />
          </Key>
          <Property Type="Decimal" Name="Id" Nullable="false" Precision="8" Scale="0" annotation:StoreGeneratedPattern="None" />
          <Property Type="Decimal" Name="CreatedById" Nullable="false" Precision="8" Scale="0" />
          <Property Type="DateTime" Name="CreatedDate" Nullable="false" />
          <Property Type="Decimal" Name="DepartmentId" Nullable="false" Precision="4" Scale="0" />
          <Property Type="String" Name="Name_E" Nullable="false" MaxLength="2000" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="Name_F" MaxLength="2000" FixedLength="false" Unicode="false" />
          <Property Type="Decimal" Name="UpdatedById" Precision="8" Scale="0" />
          <Property Type="DateTime" Name="UpdatedDate" />
          <Property Type="DateTime" Name="Timestamp" Nullable="false" Precision="6" annotation:StoreGeneratedPattern="Computed" />
          <NavigationProperty Name="AnnualPlans" Relationship="StrategicPlanningModel.R_51213" FromRole="STRATEGIC_PLAN" ToRole="STRAT_ANNUAL_PLAN" />
          <NavigationProperty Name="Department" Relationship="StrategicPlanningModel.R_51212" FromRole="STRATEGIC_PLAN" ToRole="DEPARTMENT" />
          <NavigationProperty Name="CreatedBy" Relationship="StrategicPlanningModel.R_51210" FromRole="STRATEGIC_PLAN" ToRole="STAFF" />
          <NavigationProperty Name="UpdatedBy" Relationship="StrategicPlanningModel.R_51211" FromRole="STRATEGIC_PLAN" ToRole="STAFF" />
          <Property Type="String" Name="Desc_E" MaxLength="2000" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="Desc_F" MaxLength="2000" FixedLength="false" Unicode="false" />
          <NavigationProperty Name="Goals" Relationship="StrategicPlanningModel.R_51219" FromRole="STRATEGIC_PLAN" ToRole="STRATEGIC_PLAN_GOAL" />
        </EntityType>

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

答案 7 :(得分:-1)

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

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

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