Как я могу получить имена полей таблицы базы данных? - PullRequest
9 голосов
/ 13 мая 2009

Как я могу получить имена полей таблицы базы данных MS Access?

Можно ли использовать SQL-запрос или для этого есть код C #?

Ответы [ 9 ]

8 голосов
/ 14 мая 2009

Использовать IDataReader.GetSchemaTable ()

Вот фактический пример, который обращается к схеме таблицы и печатает ее в простом виде и в XML (просто чтобы посмотреть, какую информацию вы получаете):

class AccessTableSchemaTest
{
    public static DbConnection GetConnection()
    {
        return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=..\\Test.mdb");
    }

    static void Main(string[] args)
    {
        using (DbConnection conn = GetConnection())
        {
            conn.Open();

            DbCommand command = conn.CreateCommand();
            // (1) we're not interested in any data
            command.CommandText = "select * from Test where 1 = 0";
            command.CommandType = CommandType.Text;

            DbDataReader reader = command.ExecuteReader();
            // (2) get the schema of the result set
            DataTable schemaTable = reader.GetSchemaTable();

            conn.Close();
        }

        PrintSchemaPlain(schemaTable);

        Console.WriteLine(new string('-', 80));

        PrintSchemaAsXml(schemaTable);

        Console.Read();
    }

    private static void PrintSchemaPlain(DataTable schemaTable)
    {
        foreach (DataRow row in schemaTable.Rows)
        {
            Console.WriteLine("{0}, {1}, {2}",
                row.Field<string>("ColumnName"),
                row.Field<Type>("DataType"),
                row.Field<int>("ColumnSize"));
        }
    }

    private static void PrintSchemaAsXml(DataTable schemaTable)
    {
        StringWriter stringWriter = new StringWriter();
        schemaTable.WriteXml(stringWriter);
        Console.WriteLine(stringWriter.ToString());
    }
}

Достопримечательности:

  1. Не возвращайте никаких данных, приводя предложение where, которое всегда оценивается как false. Конечно, это применимо, только если вы не заинтересованы в данных: -).
  2. Используйте IDataReader.GetSchemaTable (), чтобы получить DataTable с подробной информацией о фактической таблице.

Для моей тестовой таблицы результат был:

ID, System.Int32, 4
Field1, System.String, 50
Field2, System.Int32, 4
Field3, System.DateTime, 8
--------------------------------------------------------------------------------
<DocumentElement>
  <SchemaTable>
    <ColumnName>ID</ColumnName>
    <ColumnOrdinal>0</ColumnOrdinal>
    <ColumnSize>4</ColumnSize>
    <NumericPrecision>10</NumericPrecision>
    <NumericScale>255</NumericScale>
    <DataType>System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</DataType>
    <ProviderType>3</ProviderType>
    <IsLong>false</IsLong>
    <AllowDBNull>true</AllowDBNull>
    <IsReadOnly>false</IsReadOnly>
    <IsRowVersion>false</IsRowVersion>
    <IsUnique>false</IsUnique>
    <IsKey>false</IsKey>
    <IsAutoIncrement>false</IsAutoIncrement>
  </SchemaTable>
  [...]
</DocumentElement>
6 голосов
/ 13 мая 2009

это будет работать на SQL Server 2005 и выше:

select * from INFORMATION_SCHEMA.COLUMNS 
where TABLE_Name='YourTableName'
order by ORDINAL_POSITION
4 голосов
/ 13 мая 2009

Запустите этот запрос:

select top 1 *
From foo

, а затем обойдите поля списка (и возвращенные значения) в наборе результатов, чтобы получить имена полей.

2 голосов
/ 13 мая 2009

Вы спрашиваете, как вы можете получить имена столбцов таблицы в базе данных?

Если это так, это полностью зависит от сервера базы данных, который вы используете.

В SQL 2005 вы можете выбрать из представления INFORMATION_SCHEMA.Columns

SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable'

В SQL 2000 вы можете присоединить SysObjects к SysColumns для получения информации

SELECT     
    dbo.sysobjects.name As TableName
    , dbo.syscolumns.name AS FieldName
FROM
    dbo.sysobjects 
    INNER JOIN dbo.syscolumns 
         ON dbo.sysobjects.id = dbo.syscolumns.id
WHERE
    dbo.sysobjects.name = 'MyTable'
1 голос
/ 08 мая 2016

Этот код будет печатать все имена столбцов таблицы как класс со свойством getter всех имен столбцов, которые затем могут быть использованы в c# код

    declare @TableName sysname = '<EnterTableName>'
    declare @Result varchar(max) = 'public class ' + @TableName + '
    {'

    select @Result = @Result + '
        public static string ' + ColumnName + ' { get { return "'+ColumnName+'"; } }
    '
    from
    (
        select
            replace(col.name, ' ', '_') ColumnName,
            column_id ColumnId
        from sys.columns col
            join sys.types typ on
                col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
        where object_id = object_id(@TableName)
    ) t
    order by ColumnId

    set @Result = @Result  + '
    }'

    print @Result

Выход:

 public class tblPracticeTestSections
 {
   public static string column1 { get { return "column1"; } }

   public static string column2{ get { return "column2"; } }

   public static string column3{ get { return "column3"; } }

   public static string column4{ get { return "column4"; } }

 }
1 голос
/ 13 мая 2009

Используйте классы автоматизации DAO. Возможно, у вас уже есть библиотека взаимодействия для нее в вашей установке Visual Studio. Если нет, его достаточно легко создать; просто добавьте ссылку на библиотеку DAO COM.

using dao;
...
DBEngineClass dbengine = new DBEngineClass();
dbengine.OpenDatabase(path, null, null, null);
Database database = dbengine.Workspaces[0].Databases[0];
List<string> fieldnames = new List<string>();
TableDef tdf = database.TableDefs[tableName];
for (int i = 0; i < tdf.Fields.Count; i++)
{
    fieldnames.Add(tdf.Fields[i].Name);
}
database.Close();
dbengine.Workspaces[0].Close();

Это так же просто, как запросить системную таблицу (что я считаю проблематичным в Access), и таким образом вы можете получить много дополнительной информации.

EDIT: Я изменил код из того, что я опубликовал вчера, который я только что перевел из VB.NET, и в котором отсутствовала пара частей. Я переписал его и протестировал на C # в VS2008.

0 голосов
/ 02 ноября 2011

Мне повезло со свойством GetSchema в OleDb.Connection:

Класс для предоставления данных столбца. Это возвращает ВСЕ столбцы в базе данных. Результирующий DataTable затем может быть отфильтрован по именам столбцов, которые (в основном) соответствуют тем, которые встречаются в стандарте INFORMATION_SCHEMA (который MS Access НЕ предоставляет для нас):

    class JetMetaData
    {
        /// <summary>
        /// Returns a datatable containing MetaData for all user-columns
        /// in the current JET Database. 
        /// </summary>
        /// <returns></returns>
        public static DataTable AllColumns(String ConnectionString)
        {
            DataTable dt;

            using (OleDbConnection cn = new OleDbConnection(ConnectionString))
            {
                cn.Open();
                dt = cn.GetSchema("Columns");
                cn.Close();
            }
            return dt;
        }

    }

Затем, использование класса в довольно грубом и не очень элегантном примере и фильтрация по TABLE_NAME:

    private void Form1_Load(object sender, EventArgs e)
    {
        DataTable dt = JetMetaData.AllColumns("", Properties.Settings.Default.JetConnection);
        String RowFilter = "TABLE_NAME = 'YourTableName'";
        DataView drv = dt.DefaultView;
        drv.RowFilter = RowFilter;

        DataGridView dgv = this.dataGridView1;

        dgv.DataSource = drv;

    }

Обратите внимание, что я не претендую на то, что это хорошо продуманный код. Это только пример. Но я несколько раз использовал что-то подобное и даже создал приложение для создания сценария для всей базы данных MS Access (ограничения и все), используя похожие методы.

Хотя я видел, как другие в этой теме упоминали схему get, похоже, что некоторые реализации были слишком сложными. , .

Надеюсь, это поможет!

0 голосов
/ 01 ноября 2011

для Microsoft SQL в C # вы можете сделать следующее:

Dictionary<string, int> map = 
(from DataRow row in Schema.Rows
 let columnName = (string)row["ColumnName"]
  select columnName)
 .Distinct(StringComparer.InvariantCulture)
 .Select((columnName, index) => new { Key = columnName, Value = index })
 .ToDictionary(pair => pair.Key, pair => pair.Value);

, таким образом, создает карту имени столбца в его индекс, который можно использовать следующим образом:

internal sealed class ColumnToIndexMap
{
    private const string NameOfColumn = "ColumnName";
    private DataTable Schema { get; set; }
    private Dictionary<string, int> Map { get; set; }

    public ColumnToIndexMap(DataTable schema)
    {
        if (schema == null) throw new ArgumentNullException("schema");
        Schema = schema;

        Map = (from DataRow row in Schema.Rows
               let columnName = (string)row[NameOfColumn]
               select columnName)
              .Distinct(StringComparer.InvariantCulture)
              .Select((columnName, index) => new { Key = columnName, Value = index })
              .ToDictionary(pair => pair.Key, pair => pair.Value);
    }

    int this[string name]
    {
        get { return Map[name]; }
    }

    string this[int index]
    {
        get { return Schema.Rows[index][NameOfColumn].ToString(); }
    }
}
0 голосов
/ 13 мая 2009

В зависимости от используемого вами механизма БД, вы можете легко запросить эту информацию в системных таблицах БД

Для доступа я не могу найти ответ, я знаю, что вы можете видеть таблицы sys в доступе, и оттуда вы можете попытаться определить, где находится эта информация, но я не совсем уверен, как выполнить эту часть. , попытался использовать пример, но получил в настоящее время

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...