2011-05-19 52 views
16

我希望得到列名称,类型列表以及该列是否是实体框架中表格对象的PK。实体框架 - 如何获取列?

如何在C#(4.0)(理想情况下一般)中做到这一点?

获胜的答案将是一个能够有效并且最重要的一个方法。

+0

有什么用处,以及在哪种情况下?我的意思是,用EF你有实体,那么为什么不举例来简单地反映你的模型实体,并通过命名可能存在的约定来找出PK呢? – 2011-05-19 09:51:42

+0

为什么我的帖子被拒绝?如果你认为这是一个糟糕的问题 - 请评论,我会解释更多,而不是只是污蔑我的帖子。 – 2011-05-19 11:12:09

+0

@johnny是的 - 我正在尝试使用表达式构建where子句。我有一个动态构建的where子句,动态构建的lambda表达式为每列添加一个.contains - 但我需要表属性来构建属性名称的默认集合并验证字段名称的自定义传递。其他一切正常工作到目前为止 - 只是错过了EF表列 – 2011-05-19 11:13:54

回答

9

得到它 - 我用了LINQ基于反射查询:

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

排序! 感谢您的建议。

仅供参考 - 我创建一个动态where子句使用LINQ,动态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 
            };  
+2

任何非反射方式? – 2012-11-19 22:09:17

+0

@boomhauer在非反射方法下看到下面的答案 – 2013-06-26 04:51:46

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

+0

否否 - 我想检查代码中的ef表对象而不是sql表。即我需要在向ef图添加表时生成的ef类的属性名称 – 2011-05-19 11:07:41

+0

@Dan B - “admin”删除了文本'Ready,steady .... GO!谢谢,丹。“这篇文章如何失去了它的部分意义? – Yakimych 2011-05-19 11:51:04

+0

@Yakimych - 我的错误 - 我推测还有更多。我觉得我有一种感觉,然后我把它移开了,但我认为它已经进入了。你是怎么发现的?我会热衷于了解我们不应该写的东西,因为这似乎不会对这个非常短的帖子造成任何不利影响。我现在删除了我的不准确的评论。你能否告诉我投票的人是谁? – 2011-05-19 12:10:31

0

如果您使用DB头或模型首先,打开一个文本编辑器生成的.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表的数据,因此您需要确保获得正确的部分才能获得所需的内容。

+0

这很酷 - 我一定会回来,但我仍然在4.0,我没有看第一代(还),只是正常的EF 4.0。 – 2011-05-19 11:50:51

+0

然后它会工作。 :)代码第一种情况下,它不会工作,因为代码中没有edmx文件。 – Tridus 2011-05-19 11:55:45

+0

酷!对不起 - 午饭后困了LOL我会看看,让你知道我是如何得到一个 - 胆小鬼! – 2011-05-19 12:08:28

4

进一步自定义它,如果你不想使用反射,看到答案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 
     }; 
+0

什么是ctx,我如何得到它的处理?这是模型或数据库的第一个,因为我在其3.5版本的ObjectContext实例中使​​用Code First – 2013-10-16 13:50:37

+0

,在以后的EF版本中,它使用的是您正在使用的dbcontext的实例。例如使用var ctx = new MyEntities .... – 2013-10-16 14:07:57

+0

我在.NET 4.5 EF Code FIrst和我的DBContext没有MetadataWorkspace属性 – 2013-10-16 14:27:33

6

更换实体名称,我得到了最好的回答:
var properties = (from t in typeof(YourTableName).GetProperties() select t.Name).ToList(); var name= properties[0];

+0

我没有能力或我会给你100。 – 2016-03-13 15:27:58

0

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