Как использовать VFPOLEDB для получения информации DBF
Я могу использовать GetSchemaTable
а также GetXMLSchema
получить информацию о типах полей, размерах и т. д. из DBF Foxpro, открытого с помощью VFPOLEDB, но не может получить никакой информации, касающейся индексов в таблицах /CDX.
Я не хочу использовать индексы, только критерии, на которых построен индекс, чтобы помочь мне в создании команд SQL для создания таблиц на сервере SQL и импорта данных.
Я мог бы сделать DISPLAY STRUCTURE
вывод в текстовый файл на всех таблицах и анализ его в VB.NET, но я надеюсь, что есть что-то, что я упускаю из виду, так как я еще не настолько знаком с синтаксисом VB.NET/OLEDB.
2 ответа
Немного исследований дали эти результаты. Я начал с того, что посмотрел на ForeignKey.FKTableSchema
Собственность и, к сожалению, не собственность.NET. Позже все выглядело хорошо, когда я нашел поле OleDbSchemaGuid.Indexes, и все выглядело хорошо, пока я не запустил приложение и не получил метод, который не поддерживается этим провайдером. В конце концов следующая статья озарила путь,
и это открытие
Поставщики OleDb и Odbc не предоставляют встроенный метод каталога, который будет возвращать неключевые ("включенные") столбцы индекса.
Однако это было действительно интересное предложение, которое позволило написать это маленькое консольное приложение для вас, чтобы собрать индексы, доступные в таблице. Это достигается путем прямого запроса таблицы схемы из SQL. Следующий пример включен Employees
стол знаменитых Northwind
Пример базы данных. Ну вот,
//Open a connection to the SQL Server Northwind database.
var connectionString =
"Provider=SQLOLEDB;Data Source=SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;Encrypt=False;TrustServerCertificate=False";
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
var select = "SELECT " +
" T.name AS TABLE_NAME" +
" , IX.name AS INDEX_NAME" +
" , IC.index_column_id AS IX_COL_ID" +
" , C.name AS COLUMN_NAME" +
" , IC.is_included_column AS INCLUDED_NONKEY" +
" " +
"FROM " +
" sys.tables T " +
" INNER JOIN sys.indexes IX" +
" ON T.object_id = IX.object_id " +
" INNER JOIN sys.index_columns IC" +
" ON IX.object_id = IC.object_id " +
" AND IX.index_id = IC.index_id " +
" INNER JOIN sys.columns C" +
" ON IC.object_id = C.object_id " +
" AND IC.column_id = C.column_id " +
" " +
"WHERE T.name = 'Employees'" +
"ORDER BY IC.index_column_id";
OleDbCommand cmd = new OleDbCommand(@select, connection);
cmd.CommandType = CommandType.Text;
var outputTable = new DataSet("Table");
var my = new OleDbDataAdapter(cmd).Fill(outputTable);
foreach (DataTable table in outputTable.Tables)
{
foreach (DataRow myField in table.Rows)
{
//For each property of the field...
foreach (DataColumn myProperty in table.Columns)
{
//Display the field name and value.
Console.WriteLine(myProperty.ColumnName + " = " +
myField[myProperty].ToString());
}
Console.WriteLine();
}
}
}
Console.ReadLine();
и наконец результаты,
TABLE_NAME = Employees
INDEX_NAME = PK_Employees
IX_COL_ID = 1
COLUMN_NAME = EmployeeID
INCLUDED_NONKEY = False
TABLE_NAME = Employees
INDEX_NAME = LastName
IX_COL_ID = 1
COLUMN_NAME = LastName
INCLUDED_NONKEY = False
TABLE_NAME = Employees
INDEX_NAME = PostalCode
IX_COL_ID = 1
COLUMN_NAME = PostalCode
INCLUDED_NONKEY = False
Однако позже, сняв ограничения, которые мне удалось преодолеть, этот метод не поддерживается этим провайдером. ошибка и в итоге суммировать это как это более короткое решение,
//Open a connection to the SQL Server Northwind database.
var connectionString =
"Provider=SQLOLEDB;Data Source=SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;Encrypt=False;TrustServerCertificate=False";
using (OleDbConnection cnn = new OleDbConnection(connectionString))
{
cnn.Open();
DataTable schemaIndexess = cnn.GetSchema("Indexes",
new string[] {null, null, null});
DataTable schemaIndexes = cnn.GetOleDbSchemaTable(
OleDbSchemaGuid.Indexes,
new object[] {null, null, null});
foreach (DataRow myField in schemaIndexes.Rows)
{
//For each property of the field...
foreach (DataColumn myProperty in schemaIndexes.Columns)
{
//Display the field name and value.
Console.WriteLine(myProperty.ColumnName + " = " +
myField[myProperty].ToString());
}
Console.WriteLine();
}
Console.ReadLine();
}
Что приводит к более длинному выводу, чтобы разобраться, но часть его будет
TABLE_CATALOG = Northwind
TABLE_SCHEMA = dbo
TABLE_NAME = Employees
INDEX_CATALOG = Northwind
INDEX_SCHEMA = dbo
INDEX_NAME = LastName
PRIMARY_KEY = False
UNIQUE = False
CLUSTERED = False
TYPE = 1
FILL_FACTOR = 0
INITIAL_SIZE =
NULLS =
SORT_BOOKMARKS = False
AUTO_UPDATE = True
NULL_COLLATION = 4
ORDINAL_POSITION = 1
COLUMN_NAME = LastName
COLUMN_GUID =
COLUMN_PROPID =
COLLATION = 1
CARDINALITY =
PAGES = 1
FILTER_CONDITION =
INTEGRATED = False
Отлично! Все, что мне нужно было извлечь. Так как это было в разделе vb.net, я разместил свой грубый код, я отфильтровал возвращаемые поля, чтобы я мог перечислить несколько здесь. Он возвращает всю соответствующую информацию, относящуюся к индексам, даже сложные, созданные с помощью выражений. Будут возвращены все таблицы в пути, указанном в строке подключения с индексами CDX.
TABLE_NAME = schematest
INDEX_NAME = char3ascen
NULLS = 1
EXPRESSION = char3ascen
TABLE_NAME = schematest
INDEX_NAME = expressn
NULLS = 2
EXPRESSION = LEFT(char1null,4)+SUBSTR(char2,4,2)
TABLE_NAME = schematest
INDEX_NAME = multifld
NULLS = 2
EXPRESSION = char1null+char2
TABLE_NAME = customer
INDEX_NAME = zip
NULLS = 1
EXPRESSION = zip
Private Sub GetIndexInfo_Click(sender As Object, e As EventArgs) Handles GetIndexInfo.Click
Dim cnnOLEDB As New OleDbConnection
Dim SchemaTable As DataTable
Dim myField As DataRow
Dim myProperty As DataColumn
Dim ColumnNames As New List(Of String)
Dim strConnectionString = "Provider=vfpoledb;Data Source=D:\ACW\;Collating Sequence=general;DELETED=False"
cnnOLEDB.ConnectionString = strConnectionString
cnnOLEDB.Open()
ColumnNames.Add("TABLE_NAME")
columnnames.Add("INDEX_NAME")
columnnames.Add("NULLS")
columnnames.Add("TYPE")
columnnames.Add("EXPRESSION")
SchemaTable = cnnOLEDB.GetSchema("Indexes")
'For Each myProperty In SchemaTable.Columns
For Each myField In SchemaTable.Rows
For Each myProperty In SchemaTable.Columns
If ColumnNames.Contains(myProperty.ColumnName) Then
Console.WriteLine(myProperty.ColumnName & " = " & myField(myProperty).ToString)
End If
Next
Console.WriteLine()
Next
Console.ReadLine()
DGVSchema.DataSource = SchemaTable
End Sub