Подтвердить что ты не робот

Entity Framework - как мне получить столбцы?

Я хочу получить список имен столбцов, типов и является ли столбец PK объекта таблицы в Entity Framework.

Как это сделать в С# (4.0) (идеально в целом)?

Победителем будет тот, который делает это эффективно и, самое главное, в целом.

4b9b3361

Ответ 1

Получил это - я использовал запрос рефлексии на основе 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
                                     };    

Ответ 2

Если вы хотите только имена столбцов, я получил лучший ответ:
 var properties = (from t in typeof(YourTableName).GetProperties() select t.Name).ToList(); var name= properties[0];

Ответ 3

Если вы не хотите использовать отражение, см. ответ здесь. Замените имя сущности ниже на ваше имя объекта

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

Ответ 4

У меня нет образца кода для вас, но просто чтобы вы указали в правильном направлении, вам может понадобиться изучить 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

Ответ 5

Если вы используете 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, поэтому вам нужно убедиться, что вы получаете нужную часть, чтобы получить то, что вы хотите.

Ответ 6

Если кто-то все еще смотрит, вот как я это сделал. Это метод расширения для 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));