We recently had a problem that involved writing to an Alpha DBF file with around 300 fields from a Microsoft C# Program. Our first thought was to use an ODBC Visual Foxpro driver, which would have worked except that the ODBC driver does not support tables with over 255 fields. After mulling over the problem for a while, we stumbled upon the following link:
http://www.c-sharpcorner.com/UploadF...EngineRFV.aspx
This DLL uses a wrapper for an xBase dll that allows direct writing to a DBF from C# or any of the .Net languages. After a bit of trial and error, we found that this solution worked very well with Alpha DBFs.
We found and solved several problems with implementation:
� The Alpha fieldname structure can allow DBFs with the same field name, and this DLL only supports calling fields by name. We changed the function to allow calling fields by index.
� The DLL wants to open DBFs in exclusive read write mode, which can present a problem when Alpha is open. We changed the functions to allow writing to a DBF while Alpha has the table open in Browse mode.
Limitations:
� Memo fields. There is no existing code in the DLL for memo fields, and the VFP memo field is different from the Alpha memo field.
� With an autoincrement field rule on a field that starts with 0, the first record in starting with 0 must have been placed in the table by Alpha. Otherwise the autoincrement is destroyed. If the autoincrement starts with 1, there is no problem.
So far, we only needed to use this DLL to write a line to a table. We have several situations where this could prove quite useful, and would like to take it further, getting more parts of the DLL to work with Alpha DBFs. If anyone also feels this could be useful, feel free to contact me about it. We would love to see this taken further for the good of the Alpha community.
Below is some C# Code that we have been using to test the DLL:
//
// Program for test db classes.
//
using System;
using db;
using System.Xml;
namespace cs_test
{
// Test class for dbf support.
class MainTestClass
{
static xdbf myDb;
static void Main(string[] args)
{
myDb = new xdbf();
myDb.Use(@"C:\test_tabel.dbf");
Console.WriteLine("Locked: {0}", myDb.Opened);
Console.WriteLine("RecCount: {0}", myDb.RecCount);
Console.WriteLine("RecNo: {0}", myDb.Recno);
Console.WriteLine();
int testRec = (int)myDb.RecCount - 1;
myDb.Go(myDb.RecCount);
//Console.WriteLine("Rec: {0}", myDb.Get("2").Trim());
//Console.WriteLine("Rec: {0}", myDb.Get("1"));
// AddTestData(testRec);
TestXMLData();
}
�Write Data to the DBF
public static void AddTestData(int testRec)
{
myDb.AppendBlank();
myDb.Replace("1", testRec.ToString());
myDb.Replace("2", "Test " + testRec.ToString());
myDb.Replace("3", "Test " + testRec.ToString());
}
�Test Reading XML Data and writing it to a DBF
public static void TestXMLData()
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(@"C:\testfile.xml");
int index = 0;
int column = 2;
XmlNode rootnode = xdoc.DocumentElement;
�Autoincrement Function
string currentRecordID;
int nextRecordID;
myDb.Go(myDb.RecCount);
Console.Write(myDb.Get("1").Trim());
if (myDb.Get("1").Trim() == "0")
throw new System.NotFiniteNumberException();
currentRecordID = myDb.Get("1").Trim();
nextRecordID = int.Parse(currentRecordID)+1;
myDb.AppendBlank();
myDb.Replace("1", nextRecordID.ToString());
while (index < rootnode.ChildNodes.Count)
{
string currentnodevalue;
currentnodevalue = rootnode.ChildNodes[index].InnerText.Trim().ToString();
index++;
myDb.Replace(column.ToString(), currentnodevalue);
Console.WriteLine("Node {0}: {1}", index, currentnodevalue);
column++;
}
}
}
}
Attached is our (compiled) edited DLL file that works with the above code.
http://www.c-sharpcorner.com/UploadF...EngineRFV.aspx
This DLL uses a wrapper for an xBase dll that allows direct writing to a DBF from C# or any of the .Net languages. After a bit of trial and error, we found that this solution worked very well with Alpha DBFs.
We found and solved several problems with implementation:
� The Alpha fieldname structure can allow DBFs with the same field name, and this DLL only supports calling fields by name. We changed the function to allow calling fields by index.
� The DLL wants to open DBFs in exclusive read write mode, which can present a problem when Alpha is open. We changed the functions to allow writing to a DBF while Alpha has the table open in Browse mode.
Limitations:
� Memo fields. There is no existing code in the DLL for memo fields, and the VFP memo field is different from the Alpha memo field.
� With an autoincrement field rule on a field that starts with 0, the first record in starting with 0 must have been placed in the table by Alpha. Otherwise the autoincrement is destroyed. If the autoincrement starts with 1, there is no problem.
So far, we only needed to use this DLL to write a line to a table. We have several situations where this could prove quite useful, and would like to take it further, getting more parts of the DLL to work with Alpha DBFs. If anyone also feels this could be useful, feel free to contact me about it. We would love to see this taken further for the good of the Alpha community.
Below is some C# Code that we have been using to test the DLL:
//
// Program for test db classes.
//
using System;
using db;
using System.Xml;
namespace cs_test
{
// Test class for dbf support.
class MainTestClass
{
static xdbf myDb;
static void Main(string[] args)
{
myDb = new xdbf();
myDb.Use(@"C:\test_tabel.dbf");
Console.WriteLine("Locked: {0}", myDb.Opened);
Console.WriteLine("RecCount: {0}", myDb.RecCount);
Console.WriteLine("RecNo: {0}", myDb.Recno);
Console.WriteLine();
int testRec = (int)myDb.RecCount - 1;
myDb.Go(myDb.RecCount);
//Console.WriteLine("Rec: {0}", myDb.Get("2").Trim());
//Console.WriteLine("Rec: {0}", myDb.Get("1"));
// AddTestData(testRec);
TestXMLData();
}
�Write Data to the DBF
public static void AddTestData(int testRec)
{
myDb.AppendBlank();
myDb.Replace("1", testRec.ToString());
myDb.Replace("2", "Test " + testRec.ToString());
myDb.Replace("3", "Test " + testRec.ToString());
}
�Test Reading XML Data and writing it to a DBF
public static void TestXMLData()
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(@"C:\testfile.xml");
int index = 0;
int column = 2;
XmlNode rootnode = xdoc.DocumentElement;
�Autoincrement Function
string currentRecordID;
int nextRecordID;
myDb.Go(myDb.RecCount);
Console.Write(myDb.Get("1").Trim());
if (myDb.Get("1").Trim() == "0")
throw new System.NotFiniteNumberException();
currentRecordID = myDb.Get("1").Trim();
nextRecordID = int.Parse(currentRecordID)+1;
myDb.AppendBlank();
myDb.Replace("1", nextRecordID.ToString());
while (index < rootnode.ChildNodes.Count)
{
string currentnodevalue;
currentnodevalue = rootnode.ChildNodes[index].InnerText.Trim().ToString();
index++;
myDb.Replace(column.ToString(), currentnodevalue);
Console.WriteLine("Node {0}: {1}", index, currentnodevalue);
column++;
}
}
}
}
Attached is our (compiled) edited DLL file that works with the above code.
Comment