string data from dbf to c# program - c#

I've got a c# program, which is connected to dbf file:
OdbcConnection oconn = new OdbcConnection();
oconn.ConnectionString =
"Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + pelna_sciezka + ";Exclusive=No; Collate=Machine;NULL=NO;DELETED=NO;BACKGROUNDFETCH=NO;";
oconn.Open();
OdbcCommand ocmd = oconn.CreateCommand();
ocmd.CommandText = #"SELECT * FROM " + pelna_sciezka + " where Kod_kontr = '" + row.KNH_KOD + "'";
// ocmd.ExecuteNonQuery();
OdbcDataReader odr = ocmd.ExecuteReader();
while (odr.Read())
{
kod_kontr = odr["Kod_kontr"].ToString();
Nzwakontr1 = odr["Nzwakontr1"];
Nzwakontr2 = odr["Nzwakontr2"];
}
connection is working very well, but when I want to assemble data to local string variables (kod_kontr, nzwakontr1), all i get for a value is System.Byte[]. When I want to get the other types of data (f.ex. date, numeric, etc)from this dbf, everything is working well. The problem is only for varchar data . How could I solve my problem?
Thanx for any help
According to Antonio Bakula help i've read the answer:
I must change from ODBC to OLE, and:
- change connectionstring to:
oconn.ConnectionString = "Provider=vfpoledb.1;Data Source="+pelna_sciezka+";Collating Sequence=machine";
change code for that:
OleDbDataReader odr = ocmd.ExecuteReader();
while (odr.Read())
{
// byte[] A = Encoding.GetEncoding(Encoding.Default.CodePage).GetBytes(odr.GetString(0));
// string p = Encoding.Unicode.GetString((Encoding.Convert(Encoding.GetEncoding(850), Encoding.Unicode, A)));
kod_kontr = OdczytajTabliceBajtow(odr["Kod_kontr"]);
Nzwakontr1 = OdczytajTabliceBajtow(odr["Nzwakontr1"]);
Nzwakontr2 = OdczytajTabliceBajtow(odr["Nzwakontr2"]);
}
where OdczytajTabliceBajtow:
private string OdczytajTabliceBajtow(object p)
{
Encoding enc8 = Encoding.ASCII;
string wynik = "";
Byte[] bytes = (Byte[])p;
StringBuilder sb = new StringBuilder();
sb.Append(Encoding.ASCII.GetChars(bytes));
wynik = sb.ToString();
return wynik;
}
This is the solution of my problem. Thank you all for help.

I reccomend that you use OleDB driver for FoxPro and you will not have these problems, and there will be noticable gain in speed, here is the link
http://www.microsoft.com/en-us/download/details.aspx?id=14839
And then you will get value from DataReader as string for Character fields

Related

System.Data.OleDb.OleDbException: 'Cannot open any more tables'

While my program was normally running in Visual Studio 2017 I closed it and reopened it and from that moment I am getting the error message "System.Data.OleDb.OleDbException: 'Cannot open any more tables.'" in the line with bold letters. My code is connected to a Microsoft Access database. Can you help me, please? It is for my thesis and I am in a real need for your help.
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
label.Content = "Ερώτηση " + Question;
var DBPath = System.AppDomain.CurrentDomain.BaseDirectory + "\\Database\\Users.mdb";
conn = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + DBPath);
conn.Open();
id = MainWindow.id;
OleDbDataReader dr1 = null;
do
{
rInt = r.Next(1, 20);
cmd = new OleDbCommand("SELECT * FROM TestQuestions WHERE Chapter='Eisagogi' AND ID="+rInt+"; ");
cmd.Connection = conn;
**dr1 = cmd.ExecuteReader();**
Based on your code, I think you are filtering the data from the database by using the radom number.
If you want to use OleDbDataReader to get data from database, I suggest that you use the while(dr1.read()) instead of do.. while.
I modify some code and here is a code example you can refer to.
Code:
var conn = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + DBPath);
conn.Open();
int rInt = 0;
Random random = new Random();
rInt = random.Next(1, 20);
OleDbCommand cmd = new OleDbCommand("SELECT * FROM TestQuestions WHERE Chapter='Eisagogi' AND ID=" + rInt + "; ",conn);
OleDbDataReader dr1 = cmd.ExecuteReader();
string result = string.Empty;
while(dr1.Read())
{
result = dr1["Question"].ToString();
MessageBox.Show(result);
}
conn.Close();
I want to thank you all for your solutions but the problem was here
OleDbCommand cmd = new OleDbCommand("SELECT * FROM TestQuestions WHERE Chapter='Eisagogi' AND ID=" + rInt + "; ",conn);
I had changed the name Eisagogi in the database so as a result, the 'do...while' command was never finishing.

Reading Excel file with OleDB returns UPC numbers in wrong format

I have to read an Excel file with OleDB in a web application and save the data in a Database.
Accessing the file and reading it with DataAdapter or OleDbDataReader works. I needed to specify IMEX=1 and TypeGuessRows=0 because the data in the file has headers that I need to parse, but they are not on the first row. So basically, I need to read the lines until I hit a known header and then start parsing all the data after it.
In the first column there are UPC numbers with values like this: 5053366261702
But even though the fields are read as text, the OleDbDataReader returns the numbers in a scientific way like this: 5.05337E+12
If I don't read the lines as text, the numbers are returned correctly but the header will disappear.
I added the important part of the code. Thanks in advance for any help.
string conn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + fileName + "';Extended Properties='Excel 12.0;HDR=No;IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0'";
using (OleDbConnection objConn = new OleDbConnection(conn))
{
objConn.Open();
var exceltables = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
var tablename = exceltables.Rows[0]["TABLE_NAME"];
using (OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + tablename + "]", objConn))
{
using (OleDbDataReader reader = objCmdSelect.ExecuteReader())
{
while (reader.Read())
{
string abc = reader[0].ToString(); //do some parsing
}
}
}
}
I found a solution that works for me. I open the file with two different connection strings now.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source='filename.xlsx';Extended Properties='Excel 12.0;HDR=No;IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0'
First one to get the headers and when I found them I save the line number and open the file again with IMEX=0.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source='filename.xlsx';Extended Properties='Excel 12.0;HDR=No;IMEX=0;ImportMixedTypes=Text;TypeGuessRows=0'
string connHeaders = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + fileName + "';Extended Properties='Excel 12.0;HDR=No;IMEX=1;ImportMixedTypes=Text;TypeGuessRows=0'";
string connData = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + fileName + "';Extended Properties='Excel 12.0;HDR=No;IMEX=0;ImportMixedTypes=Text;TypeGuessRows=0'";
int dataStartRow = 0;
string tablename = "";
#region Open file to find headers
using (OleDbConnection objConn = new OleDbConnection(connHeaders))
{
objConn.Open();
var exceltables = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
tablename = exceltables.Rows[0]["TABLE_NAME"].ToString();
using (OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + tablename + "] ", objConn))
{
using (OleDbDataReader reader = objCmdSelect.ExecuteReader())
{
while (reader.Read())
{
if (reader[0].ToString().ToLower() == "upc")
{
for (int i = 0; i < reader.FieldCount; i++)
{
//find all necessary headers
}
break;
}
dataStartRow++;
}
}
}
}
#endregion
#region Open file again to read data
using (OleDbConnection objConn = new OleDbConnection(connData))
{
objConn.Open();
using (OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + tablename + "] ", objConn))
{
using (OleDbDataReader reader = objCmdSelect.ExecuteReader())
{
for (int i = 0; i < dataStartRow; i++) reader.Read();
while (reader.Read())
{
//read the line to save it in Database
}
}
}
}
I have a simple answer that works for me.
File.WriteAllText(file, Regex.Replace( File.ReadAllText(file), "(?<=,)([0-9]{12,})(?=,)", "\"$1\""));
This works because it puts double quotes around any field with 12 or more digits which is when the scientific notation comes in.

My code gives me and error called "There is already an open DataReader associated with this Command which must be closed first"

SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=PROMOD-PC;Initial Catalog=travel_Directions;Integrated Security=True";
String Strt_Address = TextBox1.Text;
String End_Address = TextBox2.Text;
String filePath = FileUpload1.PostedFile.FileName;
String filename = Path.GetFileName(filePath);
String ExtStr = Path.GetExtension(filename);
String contenttype = String.Empty;
switch (ExtStr)
{
case ".png":
contenttype = "image/png";
break;
case ".jpg":
contenttype = "image/jpg";
break;
case ".gif":
contenttype = "image/gif";
break;
}
if (contenttype != string.Empty)
{
Stream Strmf = FileUpload1.PostedFile.InputStream;
BinaryReader br = new BinaryReader(Strmf);
Byte[] imgbytes = br.ReadBytes((Int32)Strmf.Length);
//SqlDataReader sqldread = new SqlDataReader();
String selQuery = "SELECT Id FROM MapDataImage WHERE Source='" + TextBox1.Text + "';";
{
SqlCommand scmd = new SqlCommand(selQuery, conn);
conn.Open();
SqlDataReader sqldread = scmd.ExecuteReader();
while (sqldread.Read())
{
int Dbid = (int)sqldread["Id"];
//string DbId = sqldread.GetInt32("Id").ToString();
Label4.Text = Convert.ToString(Dbid);
String QueryStr = "INSERT INTO User_Images(Id,Image) VALUES ('" + Dbid + "',#Image)";
SqlCommand scmd1 = new SqlCommand(QueryStr, conn);
scmd1.Parameters.Add("#Image", SqlDbType.VarBinary).Value = imgbytes;
scmd1.ExecuteNonQuery();
}
//String QueryStr = "UPDATE MapDataImage SET Image = #Image WHERE Source='" + TextBox1.Text + "';";
//SqlCommand scmd = new SqlCommand(QueryStr, conn);
//scmd.Parameters.Add("#Image", SqlDbType.VarBinary).Value = imgbytes;
sqldread.Close();
conn.Close();
}
}
first if condition will convert to bytes which i uploaded file through the file upload control.
Select command will check the user textbox input name equals with database value
..
if it's equal the code will get the id from that table and store it as a int variable.
my uploaded image and that id will goes to another table.
my first SQL table =
Id = int
Source = varchar(max)
my second SQL data table =
image_id = int (primary key) Auto increment
Id = int (first table id store in here)
image = (varbinary)MAX
scenario is....
ex- think Facebook, if Facebook account name is valid, we can upload unlimited photos.
so situation is same here. if my name is equal with data base it will retrieve its id and under that id it will insert the images to second data table
when i want to retrieve those images. i can use for loop retrieve the images from second table.. yeah?
Try to use a new connection instead in the sqldread.Read()
SqlConnection conn2 = new SqlConnection();
conn2.ConnectionString = ""; //your connection string
SqlCommand scmd1 = new SqlCommand(QueryStr, conn2);
scmd1.Parameters.Add("#Image", SqlDbType.VarBinary).Value = imgbytes;
conn2.Open();
scmd1.ExecuteNonQuery();
conn2.Close();
You can not reuse the connection in the loop while you are still reading from the SqlDataReader.
Two options:
Read all the ids and save them in a temporary list. Then loop through with this list.
Create a new connection to do the image insert.
You need to close the SqlDataReader object right after you get the Id value from the database and re-associate the reader with the next command object, like this:
while (sqldread.Read())
{
int Dbid = (int)sqldread["Id"];
}
sqldread.Close();
Label4.Text = Convert.ToString(Dbid);
String QueryStr = "INSERT INTO User_Images(Id,Image) VALUES ('" + Dbid + "',#Image)";
SqlCommand scmd1 = new SqlCommand(QueryStr, conn);
scmd1.Parameters.Add("#Image", SqlDbType.VarBinary).Value = imgbytes;
SqlDataReader sqldread = scmd1.ExecuteNonQuery();
Note: You should also look into the using statement, which allows for the database connection to be correctly closed on success or error (read: exception) in your logic.
You will need another connection object. You can use use you connection if one command is all ready associate with it.
So what you can do is create another object of the command and use it.
Other wise change your logic as follows
crate an array while reading
ArrayList ar=new ArrayList();
while (sqldread.Read())
{
int Dbid = (int)sqldread["Id"];
ar.add(Dbid);
}
Dispose the command
and use you update command using for loop on arraylist.
for(int i=0;i<ar.length;i++)
{
//write update statement here.
}

OleDb not reading all rows from excel file, in spite of using IMEX=1

I use the Microsoft.ACE.OLEDB.12.0 driver in my C# to read and write to excel files (XLS).
The extended properties for my reader looks like : Excel 8.0;HDR=NO;IMEX=1;
and for writer looks like : Excel 8.0;HDR=NO;IMEX=0;
This is the scenario :
I read from an excel file, say input.xls , and create a new output.xls file and write to it using my writer.
Now I open the file output.xls in MS Excel, and add a few more rows to it.
Next, I feed my output.xls as input to my program, and when I debug, I see that it reads only the rows originally written using OleDb. It does not read any of the new rows I added and the writer spits out the rows that were read.
Is this how OleDb works? i.e. treat the database as locked by it, and doesn't value external inserts.
Or could there be an issue with how I create and save the files?
private void Initialize(string fileName, FileType fileType)
{
string connectionString = GetConnectionString(fileName, fileType);
string sheet;
using (OleDbConnection connection = OpenConnection(connectionString))
{
DataTable sheets = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
}
tableName = "[ListingDetails]";
conn = new OleDbConnection();
conn.ConnectionString = connectionString;
conn.Open();
cmd1 = new OleDbCommand();
cmd1.Connection = conn;
cmd1.CommandText = string.Format(CultureInfo.InvariantCulture, #"CREATE TABLE {0} {1}", tableName, fieldstring);
int x = cmd1.ExecuteNonQuery();
}
public void InsertRow(string[] data)
{
StringBuilder fieldString = new StringBuilder();
fieldString.Append("(");
foreach (var h in headers)
{
fieldString.Append(" ["+h+"], ");
}
fieldString.Remove(fieldString.Length - 2, 2);
fieldString.Append(")");
StringBuilder dataString = new StringBuilder();
dataString.Append("('");
foreach (var d in data)
{
if(d!=null)
dataString.Append(d.Replace("'", "''") + "', '");
else
dataString.Append("', '");
}
dataString.Remove(dataString.Length - 4, 4);
dataString.Append("')");
cmd1.CommandText = string.Format(CultureInfo.InvariantCulture, #"INSERT INTO {0} {1} values {2}", tableName, fieldString, dataString);
int x = cmd1.ExecuteNonQuery();
}
For closing the file, I just do a conn.Close();
I'm somehow suspecting the way I'm creating/using the sheet here in the Initialize() method.
P.S. I've seen a similar question, but the issue there seemed to be something with the Data and IMEX flag not being set to 1. Let me tell you before hand that this is not a duplicate question.
Thanks
I used the code below, which is really a simplification of your code but with a few minor changes. It works everytime and I can even have Excel open and watch the rows being inserted as I execute the code. I can then make edits to the file and subsequently load them into a datagrid while the file is still open and without ever having saved the changes.
private void Initialize(string fileName, string tableName)
{
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Mode=ReadWrite;Extended Properties=\"Excel 8.0;HDR=NO\"";
string fieldstring = "(ID int, Field1 char(255), Field2 char(255))";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = string.Format(CultureInfo.InvariantCulture, #"CREATE TABLE [{0}] {1}", tableName, fieldstring);
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
public void InsertRow(string fileName, string tableName, string data)
{
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Mode=ReadWrite;Extended Properties=\"Excel 8.0;HDR=YES\"";
string headers = "ID,Field1,Field2";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = string.Format(CultureInfo.InvariantCulture, #"INSERT INTO [{0}$] ({1}) values({2})", tableName, headers, data);
txtQuery.Text = cmd.CommandText;
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
Create the file with
Initialize("C:\\path\\to\\file\\Test File.xls", "ListingDetails");
Insert test rows with
for (int i = 0; i < 10; i++)
{
InsertRow("C:\\path\\to\\file\\Test File.xls", "ListingDetails",
"'" + i.ToString() + "','test" + (i + 2).ToString() + "','test" + (i + 5).ToString() + "'");
}
I cleaned up the code surrounding the creation and disposal of the OleDb objects. This may have been causing problems for you, I'm not sure, but this way at least you know that everything is getting finished off properly.
Hope this helps.

Reading Data From Excel and then updating It

My Excel workbook is stored in some location, Basically i'm using Export to excel from a gridview when i Click on a button.
All works fine,
My Question is, " I want to first lookup the file, and if its already present, then update it with the data i got with my gridview, if there are any new data present."
My function just creates a whole lot of new data which overrides the previous one.
Thanks
You can check for the file first as follows
string filePath = Request.PhysicalApplicationPath + "filename.xls";
FileInfo imageFile = new FileInfo(filePath);
bool fileExists = imageFile.Exists;
Label1.Text = "File exits?: " + fileExists.ToString();
Here is a code for reading and updating the excel file
var myConnection = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\\Language_Batch1_OneClick.xls';Extended Properties=Excel 8.0;"); ;
var myCommand = new OleDbCommand();
var upCommand = new OleDbCommand();
int i = 0;
try
{
string sql = null;
myConnection.Open();
myCommand.Connection = myConnection;
sql = "select ANSWER_CODE,Punjabi from [Batch_Lang_1$]";
myCommand.CommandText = sql;
var dataReader = myCommand.ExecuteReader();
while (dataReader.Read())
{
var langText = Convert.ToBase64String(Encoding.UTF8.GetBytes(dataReader["Punjabi"].ToString()));
if (langText.Length >= 1000)
{
continue;
}
var ansCode = dataReader["ANSWER_CODE"].ToString();
sql = "update [Batch_Lang_1$] set Punjabi= '" + langText + "' where ANSWER_CODE='" + ansCode + "'";
upCommand.Connection = myConnection;
upCommand.CommandText = sql;
upCommand.ExecuteNonQuery();
i++;
}
Here is a link which has code for reading and updating the excel file.
C# Convert MS Excel column to utf-8 and then to base64

Categories