c# how to properly write into a .dbf (foxpro) - c#

I am trying to insert new data into an old .dbf database created with foxpro.
The database has a lot of columns and I dont need to fill every single one.
The connection itself works. But now im getting the exception "Field XY does not allow null values" for every single one I'm not adding in my insert statement. But the database is configured to allow null values.
I am using the following code:
OleDbConnection dbfcon = new OleDbConnection("Provider=VFPOLEDB.1;" +
"Data Source=" + Application.StartupPath + "\\Daten;");
dbfcon.Open();
String query = "INSERT INTO TB_KUVG (KDNR, Kuvg_id) " +
"VALUES(?,?)";
OleDbCommand cmd = new OleDbCommand(query, dbfcon);
cmd.Parameters.AddWithValue("#KDNR", 1);
cmd.Parameters.AddWithValue("#Kuvg_id", 1);
cmd.ExecuteNonQuery();
dbfcon.Close();
So what am I doing wrong?
Is it better to use another way to write into a .dbf from c#?

You are almost doing it right. Note that parameter names are not important and would be located positionally (ie: #KDNR is added first so that it correspond to first ? placeholder). What you are missing was, if the fields you don't pass doesn't accept NULL values then you should notify the connection that instead you want "empty" values for those fields ('' for string, / / for date, 0 for numeric and vice versa). To notify the driver, you execute 'SET NULL OFF' on the same connection.
While adding it, I revised your existing code a bit:
string dataFolder = Path.Combine(Application.StartupPath, "Daten");
String query = #"INSERT INTO TB_KUVG
(KDNR, Kuvg_id)
VALUES
(?,?)";
using (OleDbConnection dbfcon = new OleDbConnection("Provider=VFPOLEDB;Data Source=" + dataFolder))
{
OleDbCommand cmd = new OleDbCommand(query, dbfcon);
cmd.Parameters.AddWithValue("#KDNR", 1);
cmd.Parameters.AddWithValue("#Kuvg_id", 1);
dbfcon.Open();
new OleDbCommand("set null off",dbfcon).ExecuteNonQuery();
cmd.ExecuteNonQuery();
dbfcon.Close();
}
PS: Application.StartupPath might not be a good idea as it may be under "Program Files" which is read only.
PS2: It would be better if you added "VFP" tag there, instead of "DBF".

Related

No value given for one or more required parameters in Oledb query

I'm trying to query a CSV file. It works when I do a simple select, but as soon as I try to add a where clause, I run into No value given for one or more required parameters.
Obviously, it sounds like it's not getting the supplied parameter, but I've tried to pass it in a number of ways. See below for some code samples
DateTime lastRunDate = Convert.ToDateTime(ConfigurationManager.AppSettings["LastRunDate"]);
OleDbConnection conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + base.applicationRoot + ";" +
"Extended Properties=\"text;HDR=Yes;FMT=CSVDelimited\"");
// This works just fine
//OleDbDataAdapter adapter = new OleDbDataAdapter(String.Format("select * from {0}",
// This gives the error
OleDbDataAdapter adapter = new OleDbDataAdapter(String.Format("select top 100 * from [{0}] where {0}.sale_date = #sDate", base.csvFileName), conn);
//adapter.SelectCommand.Parameters.Add("#sDate", OleDbType.DBDate).Value = lastRunDate;
adapter.SelectCommand.Parameters.AddWithValue("#sDate", lastRunDate);
// This also gives the same error as above
//OleDbDataAdapter adapter = new OleDbDataAdapter(String.Format("select top 100 * from {0} where sale_date = '{1}'", base.csvFileName, lastRunDate), conn);
base.csvFileName, lastRunDate.ToShortDateString()), conn);
DataTable dt = new DataTable();
adapter.Fill(dt);
I don't know anything about C#, and I'm still decently new to SQL, but perhaps it's the SELECT TOP part of your query. I know that SELECT TOP isn't really accepted on all db systems, and that it's included in both of your queries that are giving you problems. Have you tried removing that and using LIMIT instead?
"select top 100 * from [{0}] where {0}.sale_date = #sDate"
to
"select * from [{0}] where {0}.sale_date = #sDate LIMIT 100"
I would have added this as a comment as it's not a concrete answer, but I have not the required rep yet.:(
Remove this line. You have added parameter twice.
adapter.SelectCommand.Parameters.AddWithValue("#sDate", lastRunDate);
and make sure the value is present in lastRunDate variable. it should not be null.
EDITED:
Remove table name from the where condtion, Use like this
select top 100 * from [{0}] where sale_date=#sDate
Column Names in the Excel file and in the Query are not Same.
Either column name is missing.
Column Name not existing in the Excel File.
I found he issue with this. The query simply didn't understand the column names.
I thought that setting HDR=Yes meant that the oledb would read the first row headers, hence know them. But it wasn't until I added a schema.ini file that I managed to query in this way.
Here's some more about schema.ini files

SQL Server Compact Insertion

i want to insert data into sql server Compact edition the database table screenshot is Here >>>
i Want to add data in users the addition script is as follows
SqlCeConnection Con = new SqlCeConnection();
Con.ConnectionString = "Data Source = 'Database.sdf';" +
"Password='Password';";
Con.Open();
int Amount=Convert.ToInt32(AmBox.Text),
Code=Convert.ToInt32(MCode.Text),
Num=Convert.ToInt32(MNum.Text);
string Name=Convert.ToString(NBox.Text),
FName=Convert.ToString(SOBox.Text),
Address=Convert.ToString(AdBox.Text);
SqlCeCommand Query =new SqlCeCommand("INSERT INTO Users VALUES " +
"(++ID,Name,FName,Address,Code,Num,Amount)",Con);
Query.ExecuteReader();
When it runs it generates an error SAYING "The column name is not valid [Node Name (if any) =,Column name=ID ]
I don't figure out the problem kindly tell me thanks!
You should change your code to something like this
using(SqlCeConnection Con = new SqlCeConnection("Data Source = 'Database.sdf';" +
"Password='Password';")
{
Con.Open();
SqlCeCommand Query = new SqlCeCommand("INSERT INTO Users " +
"(Name,FName,Address,MCode,MNum,Amount) " +
"VALUES (#Name,#FName,#Address,#Code,#Num,#Amount)",Con);
Query.Parameters.AddWithValue("#Name", NBox.Text);
Query.Parameters.AddWithValue("#FName", SOBox.Text));
Query.Parameters.AddWithValue("#Address",AdBox.Text));
Query.Parameters.AddWithValue("#Code", Convert.ToInt32(MCode.Text));
Query.Parameters.AddWithValue("#Num", Convert.ToInt32(MNum.Text));
Query.Parameters.AddWithValue("#Amount" , Convert.ToInt32(AmBox.Text));
Query.ExecuteNonQuery();
}
The using statement guarantees the correct disposing of the
connection
The Parameter collection avoid Sql Injection Attacks and quoting
problems
Use of ExecuteNonQuery because this is an insert query.
Removed the ++ID, it is not a valid value to pass to the database
If the ID field is an Identity column, then you don't pass any value from code, but let the database calculate the next value.
Also, I'm not sure you really need the single quote in your connection string around the data source and password keys.
EDIT ---
Sometimes the .SDF database could be located in a different folder.
(Modern operating systems prevent writing in the application folder).
In this case is necessary to set the path to the SDF file in the connection string.
For example, the SDF could be located in a subfolder of the C:\ProgramData directory.
string conString = "Data Source=" +
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"MyAppData\\database.sdf") + ";Password=yourPassword;";

SqlCommand.ExecuteNonQuery() does NOT update my database

I am designing a database app, and have a form which populates with data from a sql database. If a user double clicks on any of the text boxes on the form they are able to change the value using an input box, which then executes the following code to update the database.
private void ProcessChanges(string strField, string strCurrentValue)
{
//...Connect To Database...//
string strCaseNo = txtCaseNo.Text;
string strConnect = BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnect);
linkToDB.Open();
//...Request User Input New Value...//
string strMessage = "Enter ammended details and click OK," + Environment.NewLine +
"or click Cancel to exit.";
string strInput = Interaction.InputBox(strMessage, "Case Details", strCurrentValue);
//...Send User Input to Database...//
string commandText = "UPDATE tblCases SET #FieldVal = #InputVal WHERE CaseNo = #CaseNoVal;";
SqlCommand sqlCom = new SqlCommand(commandText, linkToDB);
sqlCom.Parameters.Add("#FieldVal", SqlDbType.Text);
sqlCom.Parameters.Add("#InputVal", SqlDbType.Text);
sqlCom.Parameters.Add("#CaseNoVal", SqlDbType.VarChar);
sqlCom.Parameters["#FieldVal"].Value = strField;
sqlCom.Parameters["#InputVal"].Value = strInput;
sqlCom.Parameters["#CaseNoVal"].Value = strCaseNo;
int intQuery = sqlCom.ExecuteNonQuery();
MessageBox.Show(intQuery.ToString());
}
The problem is the database does not update at all. I know the connection is ok because the same ConnectionStringBuilder is used throughout my app. I have also added the messagebox at the end which tells me the return value of ExecuteNonQuery() which is '1', so that suggests a row has been updated. However nothing changes in my database and its really annoying me now.
You can't use variables for column names. You have to construct your sql string that the column names are embedded into the string.
string commandText =
"UPDATE tblCases SET [" + strField + "] = #InputVal WHERE CaseNo = #CaseNoVal;"
But you have to check the value of strField for sql injection attacks.
If you update the CommandText line as follows:
string commandText = "UPDATE tblCases SET #FieldVal = " + strField + " WHERE CaseNo = #CaseNoVal;";
and remove the lines
sqlCom.Parameters.Add("#FieldVal", SqlDbType.Text);
sqlCom.Parameters["#FieldVal"].Value = strField;
Be aware though that by doing this you are potentially opening yourself to sql injection attacks, so you need to really trust the values being supplied into this method or do some work to make sure that any value of strField does not contain actual SQL statements.
e.g. if strField contains ;[some malicious SQL here] then this will be run with the permissions of the user assigned to the connection.
#Jan has it. But as an aside you really should be disposing or closing your SqlConnection, from MSDN:
If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent. If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is actually closed.
The using construct is present in C# for just such a thing:
using (SqlConnection linkToDB = new SqlConnection(strConnect)
{
// use the linkToDb here
}

Updating SQL column based on text file (foreach line in it)

What I have is an extremely large text file that needs to go into a specific column at a specific raw. The file is around 100k lines. So what I want to do is read the whole file, and for each line append into that specific SQL column the line. Here's what I have but i really need help on the SQL query
string[] primaryfix = File.ReadAllLines(dinfo+"\\"+filex);
string filename = filex.ToString();
string[] spltifilename = filename.Split('.');
foreach (string primary in primaryfix)
{
string sqltable = ("dbo.amu_Textloadingarea");
string sql = "update " + sqltable + " set [Text] = [Text] + '" + primary + "' where begbates = '" + spltifilename[0] + "'";
SqlConnection con = new SqlConnection("Data Source= Corvette ;Initial Catalog= GSK_Avandia_SSECASE;Integrated Security= SSPI");
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader reader = cmd.ExecuteReader();
con.Close();
}
everything is fine except for the string sql, it doesn't update the way I would like it to.
Any help is always appreciated.
Look likes you're trying to read from the database with that code inside the loop. SqlDataReader provides a way to read rows from the database, but not the other way around.
Replace
SqlDataReader reader = cmd.ExecuteReader();
with
cmd.ExecuteNonQuery();
The first thing I see is that you are not escaping the input from the text file; any SQL escape characters (like a single quote) will break that command. I'd recommend using parameters so you needn't worry about escapes at all.
Other than that, nothing pops to mind that would suggest why the command isn't working, but I do wonder if it might not cause fewer problems if it's such a large file to read it line-by-line rather than all at once.

SQLiteDataAdapter Fill exception

I'm trying to use the OleDb CSV parser to load some data from a CSV file and insert it into a SQLite database, but I get an exception with the OleDbAdapter.Fill method and it's frustrating:
An unhandled exception of type
'System.Data.ConstraintException'
occurred in System.Data.dll
Additional information: Failed to
enable constraints. One or more rows
contain values violating non-null,
unique, or foreign-key constraints.
Here is the source code:
public void InsertData(String csvFileName, String tableName)
{
String dir = Path.GetDirectoryName(csvFileName);
String name = Path.GetFileName(csvFileName);
using (OleDbConnection conn =
new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
dir + #";Extended Properties=""Text;HDR=No;FMT=Delimited"""))
{
conn.Open();
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM " + name, conn))
{
QuoteDataSet ds = new QuoteDataSet();
adapter.Fill(ds, tableName); // <-- Exception here
InsertData(ds, tableName); // <-- Inserts the data into the my SQLite db
}
}
}
class Program
{
static void Main(string[] args)
{
SQLiteDatabase target = new SQLiteDatabase();
string csvFileName = "D:\\Innovations\\Finch\\dev\\DataFeed\\YahooTagsInfo.csv";
string tableName = "Tags";
target.InsertData(csvFileName, tableName);
Console.ReadKey();
}
}
The "YahooTagsInfo.csv" file looks like this:
tagId,tagName,description,colName,dataType,realTime
1,s,Symbol,symbol,VARCHAR,FALSE
2,c8,After Hours Change,afterhours,DOUBLE,TRUE
3,g3,Annualized Gain,annualizedGain,DOUBLE,FALSE
4,a,Ask,ask,DOUBLE,FALSE
5,a5,Ask Size,askSize,DOUBLE,FALSE
6,a2,Average Daily Volume,avgDailyVolume,DOUBLE,FALSE
7,b,Bid,bid,DOUBLE,FALSE
8,b6,Bid Size,bidSize,DOUBLE,FALSE
9,b4,Book Value,bookValue,DOUBLE,FALSE
I've tried the following:
Removing the first line in the CSV file so it doesn't confuse it for real data.
Changing the TRUE/FALSE realTime flag to 1/0.
I've tried 1 and 2 together (i.e. removed the first line and changed the flag).
None of these things helped...
One constraint is that the tagId is supposed to be unique. Here is what the table look like in design view:
Can anybody help me figure out what is the problem here?
Update:
I changed the HDR property from HDR=No to HDR=Yes and now it doesn't give me an exception:
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dir + #";Extended Properties=""Text;HDR=Yes;FMT=Delimited""");
I assumed that if HDR=No and I removed the header (i.e. first line), then it should work... strangely it didn't work. In any case, now I'm no longer getting the exception.
The new problem arose here: SQLiteDataAdapter Update method returning 0
First thing: IMO emplacing keys and constraints on a transport structure such as your dataset is a bad idea.
Use a transaction and let the target db throw if it wants.
Second: have you examined the ds to ensure the csv is getting loaded? VS has a dataset debug visualizer built in - simply set a break point after the ds is loaded and hover over the variable name, click the little down-arrow and select the appropriate visualizer.
Third: I don't think that you are generating an insert command. Just before you call update, check the InsertCommand.CommandText..
var cmdText = sqliteAdapter.InsertCommand.CommandText;
I think you will find that it is empty.
This is the source of the SQLiteDataAdapter ctor that ultimately gets called. Note that no command builder is employed. You need to explicitly set the InserCommand property on the SQLiteDataAdapter, perhaps by using a SQLiteCommandBuilder?
public SQLiteDataAdapter(string commandText, SQLiteConnection connection)
{
this.SelectCommand = new SQLiteCommand(commandText, connection);
}
I changed the HDR property from HDR=No to HDR=Yes and now it doesn't give me an exception anymore... here is what the connection string looks like:
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dir + #";Extended Properties=""Text;HDR=Yes;FMT=Delimited""");
I assumed that if HDR=No and I removed the header (i.e. first line), then it should work... the only way to get rid of the exception if HDR=No is if I remove the constraints by calling ds.EnforceConstraints = false;
In any case, now I'm no longer getting the exception. If anybody can explain why this is happening, then please do tell.

Categories

Resources