Я хочу получить список имен столбцов, типов и является ли столбец PK объекта таблицы в Entity Framework.
Как это сделать в С# (4.0) (идеально в целом)?
Победителем будет тот, который делает это эффективно и, самое главное, в целом.
Я хочу получить список имен столбцов, типов и является ли столбец PK объекта таблицы в Entity Framework.
Как это сделать в С# (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()
Сортировано! Спасибо за все предложения.
FYI. Я создаю динамическое предложение where, использующее LINQ, динамические лямбда-выражения для сборки, например. поиск, который будет автоматически искать по всем столбцам по умолчанию. Но мне также нужны имена столбцов для проверки, потому что я разрешу это переопределить, и эти вызовы будут выполняться через 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
};
Если вы хотите только имена столбцов, я получил лучший ответ:
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
};
У меня нет образца кода для вас, но просто чтобы вы указали в правильном направлении, вам может понадобиться изучить Sql Management Objects (SMO); вы можете использовать это, чтобы получить иерархию объектов для экземпляра сервера Sql, который затем вы можете перечислить и выбрать необходимую информацию.
Взгляните на этот набор учебников, чтобы вы начали с программирования - http://www.codeproject.com/KB/database/SMO_Tutorial_1.aspx http://www.codeproject.com/KB/database/SMO_Tutorial_2.aspx
Если вы используете 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, поэтому вам нужно убедиться, что вы получаете нужную часть, чтобы получить то, что вы хотите.
Если кто-то все еще смотрит, вот как я это сделал. Это метод расширения для 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));