Need the result of a FoxPro RLOCK() command via OLEDbCommand - c#

I'm trying to execute an RLOCK() command (record lock) on a FoxPro table via OleDbCommand but I need to know if the lock succeeded. In FoxPro, the RLOCK() returns .T. or .F. to indicate if it succeeded.
How do I get that result via OleDbCommand?
Here is my current code:
using(var conn = new OleDbConnection(...)) //connection string with VFPOLEDB provider
{
conn.Open();
using(var comm = new OleDbCommand())
{
string cText = #"[use table in 0] + chr(13) + "
+ #"[RLOCK(table)]";
comm.Connection = conn;
comm.CommandText = "Execute(" + cText + ")";
var result = comm.ExecuteNonQuery();
Consle.WriteLine(result);
comm.Dispose();
}
conn.Close();
conn.Dispose();
}
Right now, I'm always getting back a 1 (true) even when the Lock should not have taken place due to the fact that the record is already locked by someone else.
Thanks for your help.

Because you are not returning the result of the rlock() (and that you are using ExecuteNonQuery, when you should ask a return value and use ExecuteScalar instead). You would normally get back true with that code if you properly have used ExecuteScalar. In VFP each and every procedure returns .T. if no return value is specified (or call it a function if you will - in VFP procedure and function have no difference except name).
Here is a revised version of your code:
string myCode =
#"use c:\temp\lockTest
locked = rlock()
return m.locked
";
string strCon = #"Provider=VFPOLEDB;Data Source=c:\temp";
using (OleDbConnection con = new OleDbConnection(strCon))
{
OleDbCommand cmd = new OleDbCommand("ExecScript", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#code", myCode);
con.Open();
Console.WriteLine(cmd.ExecuteScalar());
con.Close();
}
While this code works perfectly well, I have no idea what you would do with a useless rlock() other than learning that you can't lock it due to some reason. In real life Execscript has little value.

Related

adding to database oledb c#

After searching for about an hour it appears this is the correct way to use the oledb libary to insert a record to an access database however it doesnt work for me , HELP...
InitializeComponent();
System.Data.OleDb.OleDbConnection conn = new
System.Data.OleDb.OleDbConnection();
// TODO: Modify the connection string and include any
// additional required properties for your database.
conn.ConnectionString = #"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = \\crd-a555-015.occ.local\c$\Users\james.piper\Documents\Visual Studio 2015\Projects\Project V1\Project Database.accdb";
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO Work_Done (employee,client,project,task,hours)" + " VALUES (#employee,#client,#project,#task,#hours)";
cmd.Parameters.AddWithValue("#employee", user.employee);
cmd.Parameters.AddWithValue("#client", listBox1.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#project", listBox2.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#task", listBox3.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#hours", listBox4.SelectedItem.ToString());
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("sql insert fail");
}
I would write this code like this:
var connectionString = #"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = \\crd-a555-015.occ.local\c$\Users\james.piper\Documents\Visual Studio 2015\Projects\Project V1\Project Database.accdb";
var query = "INSERT INTO Work_Done (employee,client,project,task,hours) VALUES (#employee,#client,#project,#task,#hours)";
using (var conn = new OleDbConnection(connectionString))
{
using(var cmd = new OleDbCommand(query, conn))
{
// No need to specifiy command type, since CommandType.Text is the default
// I'm assuming, of course, your parameter data types. You should change them if my assumptions are wrong.
cmd.Parameters.Add("#employee", OleDbType.Integer).Value = user.employee;
cmd.Parameters.Add("#client", OleDbType.Integer).Value = Convert.ToInt32(listBox1.SelectedItem);
cmd.Parameters.Add("#project", OleDbType.Integer).Value = Convert.ToInt32(listBox2.SelectedItem);
cmd.Parameters.Add("#task", OleDbType.Integer).Value = Convert.ToInt32(listBox3.SelectedItem);
cmd.Parameters.Add("#hours", OleDbType.Integer).Value = Convert.ToInt32(listBox4.SelectedItem);
try
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show($"sql insert fail: {ex}");
}
}
}
The major changes are these:
use the Using statement for each instance of a class that implements the IDisposable interface.
Using constructors with parameters to make the code shorter (and more readable, IMHO).
Note that the constructor of the OleDbCommand also has the OleDbConnection object. In your code, you didn't specify the active connection to the command.
Adding parameters with Add and not AddWithValue. Read this blog post to find out why.

C# MySql Parameterized Query makes longs into null

The code is based on https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html
public void TableTest(string connectionString)
{
string sqlToCreateTable = #"CREATE TABLE IF NOT EXISTS my_table
(auction_key BIGINT NOT NULL, auction_owner VARCHAR(25), first_seen BIGINT,
PRIMARY KEY(auction_key))";
string sqlInsertOrUpdateAuction = "INSERT INTO my_table (auction_key) VALUES (#my_auc_id); ";
using (MySqlConnection dbConnection = new MySqlConnection(connectionString))
{
dbConnection.Open();
// is the table in the database?
MySqlCommand cmd = new MySqlCommand(sqlToCreateTable, dbConnection);
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.ExecuteNonQuery();
}
}
The error is that 123456 is seen as null.
Message=Column 'auction_key' cannot be null
I tried changing the "strict" setting in my.ini and it makes no difference.
Help please.
Well, you add the parameter to the command and then instantiate a new command:
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
If you do that, the command will no longer have the value for the #my_auc_id. Try switching those two lines:
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
Hope this helps.
You could alleviate your issue, by simply doing the following:
using(var connection = new MySqlConnection(dbConnection))
{
connection.Open();
using(var command = new MySqlCommand(createTableQuery, connection))
{
command.ExecuteNonQuery();
}
using(var command = new MySqlCommand(insertOrUpdate, connection))
{
command.Parameters.Add("..", SqlDbType = SqlDbType.Int).Value = 123456;
command.ExecuteNonQuery();
}
}
Keep in mind that ExecuteNonQuery will return a zero or one, if it successfully worked. Also you may want to manually specify the SqlDbType. To avoid SQL inferring incorrectly. Also, this will correctly scope your MySqlCommand, so you can correctly utilize for the queries.
And according to the documentation, it does implement the IDisposable to utilize the using block. This ensures you instantiate your MySqlCommand again.

Query Timing out when Command Timeout = 0

I have a frustrating issue with a query that typically takes between 1.5-2 minutes to run (due to a lack of ability to modify this database, we cannot improve it more than this time). The query times out, despite the Command Timeout property being set to 0 (this is C# code).
Here is the code that executes the query:
public DataTable GetData()
{
DataTable results = new DataTable();
try
{
using (var sqlConnection = new SqlConnection(ConfigurationManager.AppSettings["SqlConnectionString"].ToString()))
{
String command = _query;
sqlConnection.Open();
var sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = command;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandTimeout = 0;
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand.CommandText, sqlConnection);
daM.Fill(results);
sqlConnection.Close();
}
}
catch(Exception e)
{
Console.WriteLine("Error " + e.StackTrace);
}
Console.WriteLine("Retrieving results for query " + _query);
Console.WriteLine("Total Results: " + results.Rows.Count);
return results;
}
I'm not sure where to look for the culprit. Setting a more explicit timeout does nothing, and as I said there's no way to further improve the query that we've been able to find. The connection string has the following parameters:
server =
Integrated Security = SSPI
database =
Connection Timeout = 0
Any advice of where I should look next? We are using Microsoft SQL Server.
You have set sqlCommand.CommandTimeout, but later you've created SqlDataAdapter as
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand.CommandText, sqlConnection)
Here adapter implicitly creates and uses new SqlCommand (not the one you've configured) since you've passed there command text, not instance of SqlCommand.
Use another constructor of SqlDataAdapter and create it like
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand)
Set timeout on SqlConnection does not work in your case, you need do it on SqlDataAdapter.
daM.SelectCommand.CommandTimeout = Value;
Google for "How do you change a SqlDataAdapter .CommandTimeout?"

SQL SELECT With Stored Procedure and Parameters?

I've been writing a lot of web services with SQL inserts based on a stored procedure, and I haven't really worked with any SELECTS.
The one SELECT I have in mind is very simple.
SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization
WHERE AD_SID = #userSID
However, I can't figure out based on my current INSERT code how to make that into a SELECT and return the value of ReturnCount... Can you help? Here is my INSERT code:
string ConnString = "Data Source=Removed";
string SqlString = "spInsertProgress";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("attachment_guid", smGuid.ToString());
cmd.Parameters.AddWithValue("attachment_percentcomplete", fileProgress);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
Here is where you are going wrong:
cmd.ExecuteNonQuery();
You are executing a query.
You need to ExecuteReader or ExecuteScalar instead. ExecuteReader is used for a result set (several rows/columns), ExecuteScalar when the query returns a single result (it returns object, so the result needs to be cast to the correct type).
var result = (int)cmd.ExecuteScalar();
The results variable will now hold a OledbDataReader or a value with the results of the SELECT. You can iterate over the results (for a reader), or the scalar value (for a scalar).
Since you are only after a single value, you can use cmd.ExecuteScalar();
A complete example is as follows:
string ConnString = "Data Source=Removed";
string userSid = "SomeSid";
string SqlString = "SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization WHERE AD_SID = #userSID;";
int returnCount = 0;
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#userSID", userSid);
conn.Open();
returnCount = Convert.ToInt32(cmd.ExecuteScalar());
}
}
If you wanted to return MULTIPLE rows, you can use the ExecuteReader() method. This returns an IDataReader via which you can enumerate the result set row by row.
You need to use ExecuteScalar instead of ExecuteNonQuery:
String query = "SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization WHERE AD_SID = #userSID ";
using (OleDbConnection conn = new OleDbConnection(ConnString)) {
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.AddWithValue("userSID", userSID.ToString());
conn.Open();
int returnCount = (Int32) cmd.ExecuteScalar();
conn.Close();
}
}
cmd.executescalar will return a single value, such as your count.
You would use cmd.executereader when you are returning a list of records

C# sql query if() else() based on results null?

The title is probably confusing, but basically i want to do something along the lines of this,
string sql = "select dataset1 from dbo.ste where project = 'whatever' and date = '11/30/10'";
SqlConnection con = new SqlConnection("Data Source= Watchmen ;Initial Catalog= doeLegalTrending;Integrated Security= SSPI");
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
cmd.ExecuteNonQuery();
con.Close();
if(cmd "is not null")
{
//do this string
}
else
{
//do this one
}
obviously cmd "is not null") is not real, but i think you guys might get the point.
I don't understand why everyone is trying to use ExecuteNonQuery or ExecuteScalar when the query in the question is a SELECT statement. If it was a stored procedure call that took care of the logic of INSERT versus UPDATE based on the existence of a value, the ExecuteScalar would make sense because you can return whatever single value you want from a stored procedure.
However, given the structure of the question, I'm leaning towards this as the answer.
// Automatically dispose the connection when done
using(SqlConnection connection = new SqlConnection(sqlConnection.ConnectionString)) {
try {
connection.Open();
// query to check whether value exists
string sql = #"SELECT dataset1
FROM dbo.ste
WHERE project = 'whatever'
AND date = '2010-11-30'";
// create the command object
using(SqlCommand command = new SqlCommand(sql, connection)) {
using(SqlDataReader reader = command.ExecuteReader()) {
// if the result set is not NULL
if(reader.HasRows) {
// update the existing value + the value from the text file
}
else {
// insert a value from a text file
}
}
}
}
finally {
// always close connection when done
if(connection.State != ConnectionState.Closed) {
connection.Close();
}
}
}
You can change the query to use WHERE EXISTS if you don't want to stream back full matches, but from the sounds of it, you would only have at most 1 match anyways.
If you want to check if there is any matching records, you can count them:
string sql = "select count(*) from dbo.ste where project = 'whatever' and date = '11/30/10'";
To get the result you use the ExecuteScalar method:
int cnt = Convert.ToInt32(cmd.ExecuteScalar());
It looks like you want to do var result = cmd.ExecuteScalar(); and then compare if (result == DBNull.Value).
ExecuteNonQuery returns the number of rows affected (if certain options are not selected) as an integer. So, you can either verify the count is equal to (or greater than) some success condition or execute scalar and return a value from your query to indicate success.
Try this:
string sql = "select COUNT(dataset1) from dbo.ste where project = 'whatever' and date = '11/30/10'";
SqlConnection con = new SqlConnection("Data Source= Watchmen ;Initial Catalog= doeLegalTrending;Integrated Security= SSPI");
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
int count = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();
if(count != 0)
{
//do this string
}
else
{
//do this one
}

Categories