实体框架 - 如何获取列
本文关键字:获取 何获取 框架 实体 | 更新日期: 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测试中)。