Я работал над программой, чтобы читать файл dbf, возиться с данными и сохранять их обратно в dbf. Проблема, с которой я столкнулся, связана именно с написанием.
private const string constring = "Driver = {Microsoft dBASE Driver (*.dbf)};"
+ "SourceType=DBF;"
+ "DriverID=277;"
+ "Data Source=¿;"
+ "Extended Properties=dBASE IV;";
private const string qrystring = "SELECT * FROM [¿]";
public static DataTable loadDBF(string location)
{
string filename = ConvertLongPathToShort(Path.GetFileName(location));
DataTable table = new DataTable();
using(OdbcConnection conn = new OdbcConnection(RTN(constring, filename)))
{
conn.Open();
table.Load(new OdbcCommand(RTN(qrystring, filename), conn).ExecuteReader());
conn.Close();
}
return table;
}
private static string RTN(string stmt, string tablename)
{ return stmt.Replace("¿", tablename); }
[DllImport("Kernel32", CharSet = CharSet.Auto)]
static extern Int32 GetShortPathName(
String path, // input string
StringBuilder shortPath, // output string
Int32 shortPathLength); // StringBuilder.Capacity
public static string ConvertLongPathToShort(string longPathName)
{
StringBuilder shortNameBuffer;
int size;
shortNameBuffer = new StringBuilder();
size = GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
if (size >= shortNameBuffer.Capacity)
{
shortNameBuffer.Capacity = size + 1;
GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
}
return shortNameBuffer.ToString();
}
Это то, с чем я работаю. Я пробовал несколько способов записать новый файл, но ни один из них не был продуктивным. Честно говоря, хотя обычно я был бы сторонником формы и функции, я просто хочу, чтобы эта чертова штука работала, это приложение должно делать одну очень конкретную вещь, оно не будет имитировать погоду.
- = # Редактировать # = -
С тех пор я прекратил выпуск приложения из-за нехватки времени, но прежде чем отказаться от него, я понял, что конкретный формат dbf, с которым я работал, не имел информации о первичном ключе. Это, конечно, означало, что мне пришлось по существу прочитать данные в DataTable, возиться с ними, затем стереть все записи в dbf и вставить все с нуля. К черту это для забавы.





С каким файлом dbf вы работаете? (Есть несколько, например, dBase, FoxPro и т. д., Которые не совместимы на 100%.) Я получил это для работы с Microsoft Visual FoxPro OleDB Provider из C#, вы можете попробовать это вместо использования драйвера ODBC dBase.
Использование ADO.Net для чтения и записи файлов dbf оказывается очень медленным, поэтому я предлагаю вам использовать альтернативный подход.
Один из вариантов - использовать старую библиотеку DAO 3.6. Это намного быстрее и так же совместимо, но зависит от работы com-объекта.
Лучшим подходом было бы использование Компонент DBFExporter с открытым исходным кодом. Для настройки может потребоваться некоторый код (вам нужен класс со свойствами, описывающими ваш набор записей, и свойства должны иметь определенные атрибуты), но после этого он работает очень хорошо. Он быстр в использовании, но не читает файлы dbf. Компонент имеет лицензию LGPL, поэтому вы сможете использовать его в коммерческом коде.
Для людей, которые придут сюда в будущем: я написал это сегодня, и это хорошо работает. Имя файла без расширения (.dbf). Путь (используемый для подключения) - это только путь к каталогу (без файла). Вы можете добавить свою таблицу данных в набор данных и передать ее. Кроме того, некоторые из моих типов данных являются типами данных foxpro и могут быть несовместимы со всеми файлами DBF. Надеюсь это поможет.
public static void DataSetIntoDBF(string fileName, DataSet dataSet)
{
ArrayList list = new ArrayList();
if (File.Exists(Path + fileName + ".dbf"))
{
File.Delete(Path + fileName + ".dbf");
}
string createSql = "create table " + fileName + " (";
foreach (DataColumn dc in dataSet.Tables[0].Columns)
{
string fieldName = dc.ColumnName;
string type = dc.DataType.ToString();
switch (type)
{
case "System.String":
type = "varchar(100)";
break;
case "System.Boolean":
type = "varchar(10)";
break;
case "System.Int32":
type = "int";
break;
case "System.Double":
type = "Double";
break;
case "System.DateTime":
type = "TimeStamp";
break;
}
createSql = createSql + "[" + fieldName + "]" + " " + type + ",";
list.Add(fieldName);
}
createSql = createSql.Substring(0, createSql.Length - 1) + ")";
OleDbConnection con = new OleDbConnection(GetConnection(Path));
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = createSql;
cmd.ExecuteNonQuery();
foreach (DataRow row in dataSet.Tables[0].Rows)
{
string insertSql = "insert into " + fileName + " values(";
for (int i = 0; i < list.Count; i++)
{
insertSql = insertSql + "'" + ReplaceEscape(row[list[i].ToString()].ToString()) + "',";
}
insertSql = insertSql.Substring(0, insertSql.Length - 1) + ")";
cmd.CommandText = insertSql;
cmd.ExecuteNonQuery();
}
con.Close();
}
private static string GetConnection(string path)
{
return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = " + path + ";Extended Properties=dBASE IV;";
}
public static string ReplaceEscape(string str)
{
str = str.Replace("'", "''");
return str;
}
Я получаю исключение Data type mismatch in criteria expression. при выполнении инструкции вставки. Есть идеи, что могло бы вызвать это?
Я понял. Ваш код не проверяет значения DBNull в DataSet и вставляет пустую строку '' в столбцы, в которые следует вставить NULL.
Я добавил регистр с System.Decimal, но он помог мне с вашими кодами. Спасибо