Как получить точный тип числовых столбцов, в т.ч. масштаб и точность?

Есть ли способ узнать точный тип столбца в DataTable? Прямо сейчас я делаю это:

DataTable st = dataReader.GetSchemaTable();
foreach (DataColumn col in st.Columns)
{
   var type = col.DataType;
}

Теперь с type.Name я могу найти, является ли это числом (int или decimal..) или string, но проблема в том, что мне нужен точный тип, например, если в базе данных допустим, что столбец Rate равен NUMBER(4,3), то здесь, в моем коде, я я получаю только тип «Десятичный» и никакой информации о формате 4,3.

Теперь мне нужно отформатировать значения в соответствии с их типом, например. если Rate=1.4 должно отображаться как 0001.400 (в соответствии с Форматом NUMBER(4,3)). Следовательно, поскольку у меня нет информации, я не могу дальше обрабатывать значения. Есть ли способ узнать то же самое?

Спасибо


person IFlyHigh    schedule 11.06.2014    source источник
comment
msdn.microsoft.com/en-IN/library/   -  person Bharadwaj    schedule 11.06.2014
comment
цикл через каждую строку, также известную как DataRow, и использование отражения getType отдельного..   -  person Vishal Sharma    schedule 11.06.2014
comment
Вам нужно посмотреть на дополнительные атрибуты в столбце, чтобы определить это точно. Например, просмотрите свойства NumericPrecision и NumericScale msdn.microsoft.com/en-us/library/   -  person dmarietta    schedule 11.06.2014
comment
@Tim Schmelter: не могли бы вы пролить свет на то, как его использовать .. Я мог бы найти его в DataTable или DataColumn.   -  person IFlyHigh    schedule 11.06.2014


Ответы (2)


Вы можете использовать NumericPrecision и NumericScale:

using (var con = new SqlConnection(Properties.Settings.Default.RM2ConnectionString))
using (var cmd = new SqlCommand("SELECT * FROM dbo.Test", con))
{
    con.Open();
    using (var reader = cmd.ExecuteReader())
    using (var schemaTable = reader.GetSchemaTable())
    {
        foreach (DataRow row in schemaTable.Rows)
        {
            string column = row.Field<string>("ColumnName");
            string type = row.Field<string>("DataTypeName");
            short precision = row.Field<short>("NumericPrecision");
            short scale = row.Field<short>("NumericScale");
            Console.WriteLine("Column: {0} Type: {1} Precision: {2} Scale: {3}", column, type, precision, scale);
        }
    }
}

Дополнительные сведения: GetSchemaTable

Я протестировал его со свежей таблицей с одним столбцом NumberColumn типа numeric(4, 3):

Column: NumberColumn Type: decimal Precision: 4 Scale: 3
person Tim Schmelter    schedule 11.06.2014
comment
Это именно то, что я искал. Я попробовал это в своем коде и получил желаемые значения. Большое спасибо! +1 - person IFlyHigh; 11.06.2014
comment
Просто дополнительный вопрос. Есть ли способ получить конкретную строку данных столбца из таблицы Schema. Например, только для столбца Rate, как я могу получить строку данных. Я сделал это: 1. Цикл Foreach для schemaTbale.rows 2. schemaColName = row.Field‹string›(ColumnName); 3. Если schemaColName=Rate получить все остальные данные. Однако здесь для каждого столбца я просматриваю полную таблицу схемы. Есть ли лучший способ сделать это? Заранее спасибо. - person IFlyHigh; 12.06.2014
comment
@LittleMissSunshine: почему это проблема? В любом случае у вас не должно быть десятков столбцов. Вы можете использовать LINQ (который также является скрытым циклом): var row = tbl.AsEnumerable().First(r => r.Field<string>("ColumnName")=="Rate"); - person Tim Schmelter; 12.06.2014
comment
Вы правы, в любом случае таблица Schema будет пройдена хотя бы один раз для каждого столбца. LINQ и Loop в этом случае будут делать одно и то же. А так как нет. количество столбцов ограничено, это не повлияет на производительность так плохо, как я думал изначально. Спасибо еще раз! - person IFlyHigh; 12.06.2014
comment
@LittleMissSunshine: производительность вообще не должна быть проблемой, так как весь DataTable в любом случае уже находится в памяти, и он довольно мал. Однако, для чего бы это ни стоило, вы можете создать Dictionary из DataTable для более быстрого поиска столбца по их именам. Таким образом, ключом будет имя столбца и значение DataRow. Вы можете использовать LINQ: var dict=tbl.AsEnumerable().ToDictionary(r => r.Field<string>("ColumnName"), r => r); - person Tim Schmelter; 12.06.2014
comment
Есть ли способ получить ProviderType с помощью этого решения? (Если не ошибаюсь, это поле должно содержать исходный SqlDbType, но в моем случае оно всегда пустое). - person Ishikawa; 23.10.2019

DataTable, возвращаемый dataReader.GetSchemaTable(), является схемой базового результата. Эта таблица содержит столько записей, сколько столбцов в базовой таблице. Итак, вам нужно пройтись по рядам. Каждая строка содержит метаданные одного столбца базовой таблицы. Вы можете получить метаданные столбца, как показано ниже.

DataTable st = reader.GetSchemaTable();
                    foreach (DataRow row in st.Rows)
                    {
                        Console.Write(string.Format("ColumnName:{0} DataType:{1} Ordinal:{2} Precision:{3} Size:{4} Scale:{5}", 
                            row["ColumnName"], row["DataTypeName"], row["ColumnOrdinal"], 
                            row["NumericPrecision"], row["ColumnSize"], row["NumericScale"]));
                    }
person Kiran Hegde    schedule 11.06.2014