我希望获得列名称,类型以及列是否是实体框架中表对象的PK的列表。
我如何在C#(4.0)(理想情况下)中执行此操作?
获胜的答案将是有效的,最重要的是一般的答案。
答案 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 测试中)。