I wrote a set of codes using SQL command to delete and update Access records through a C# program. Here is the set of codes:
Update
OleDbCommand cmd = new OleDbCommand("UPDATE Available SET Status = 'AVAILABLE' WHERE AvailableID = ?", cnn);
cmd.Parameters.Add(new OleDbParameter { Value = id.AvailableID });
cmd.CommandType = CommandType.Text;
cnn.Open();
cmd.ExecuteNonQuery();
cnn.Close();
Delete
OleDbCommand cmd = new OleDbCommand("DELETE FROM Log WHERE LogID = ?", cnn);
cmd.Parameters.Add(new OleDbParameter { Value = l.LogID });
cmd.CommandType = CommandType.Text;
cnn.Open();
cmd.ExecuteNonQuery();
cnn.Close();
The program is executable. When I'm trying to delete and update records, the updating record has not been updated and the deleting record still exists.
Pressing the delete button will delete a record in log and updates the product into 'available'. However, the status didn't change and the record didn't delete.
Am I missing something? I always refresh when every transaction has been made.
That is strange. Here are my recommendations:
Verify that you are not accidentally swallowing an error somewhere. You can do this by stepping through the code and verifying that it doesn't jump to a catch handler. Bear in mind this may be somewhere else far away from the location of the code you posted. Just depends on how it's been set up.
Verify that the parameters are the correct values by hard coding the entire query with the LogID as well. Though it's better to use them, parameters sometimes behave in ways you wouldn't expect. It's been some time since I've used dynamic SQL but off the top of my head I don't see anything wrong with your code.
As an aside, I would recommend making the switch to an ORM. Dynamic SQL is very difficult to manage in larger projects and hence it's better to get comfortable with it even when your project is small. It also takes care of any syntactical differences that might exist should you ever port the application to use a MSSQL database in the future. Personally I recommend nHibernate.
Related
How can I prevent duplicate data inserting in database?
What I like is when click button save it will show message "Cannot Insert Duplicate Value". I'm using MSAcess for my database.
Code:
connection1.Open();
OleDbCommand cmd = connection1.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "insert into Taxation (ShoesBrand, ShoesCode, ShoesColor) Values (ShoesBrand, ShoesCode, ShoesColor)";
cmd.Parameters.AddWithValue("ShoesBrand", textBox1.Text);
cmd.Parameters.AddWithValue("ShoesCode", textBox2.Text);
cmd.Parameters.AddWithValue("ShoesColor", textBox3.Text);
cmd.ExecuteNonQuery();
connection1.Close();
How do I prevent not to insert same value? Or how can i add to throw exemption when values are the same in database.
You have to create a unique index on the required column of the table. in this way, It will not allow you to insert duplicate records from C# code.
You can learn more about Unique constraints here.
Few points to be noted here. you should use using when initializing the connection. and please read about SQL injections.
I have a CLR stored procedure running on SQL Server 2014. When I execute the following code, the data reader only returns the top row of the result set. The SQL, when ran by itself, returns more than one row. I have also tried filling a DataTable with the SqlDataAdapter, but still only get one row.
using (SqlConnection conn = new SqlConnection("context connection=true"))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM some_table", conn))
{
cmd.CommandType = CommandType.Text;
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
SqlContext.Pipe.Send(reader.GetInt32(0).ToString());
}
reader.Close();
conn.Close();
}
Thank you for any help in advance. This truly has me baffled, as it is the simplest of things.
There is nothing inherently wrong with this code. I ran it myself on SQL Server 2014, compiled against .NET Framework version 4.5.2 and it works as you are expecting it to. And just to be clear, for what you are doing here, the version of SQL Server and .NET Framework don't really matter.
I also tried passing in CommandBehavior.SingleRow to cmd.ExecuteReader() and that still returned all rows.
Since this code does work, here are some things to check:
Make sure that you are publishing to the same DB (and Instance) that you are running the SELECT statement in in SSMS.
Make sure that you have published the most recent version of this code to the DB.
Other external factors
Also, please create the SqlDataReader within a using() construct as it is a Disposable object.
UPDATE FROM O.P.:
The SQLCLR Stored Procedure is being called from a T-SQL Stored Procedure that had issued SET ROWCOUNT 1; prior to calling the SQLCLR Stored Procedure. Hence, only 1 row could be returned by any query. The 1 row problem was fixed by issuing SET ROWCOUNT 0; prior to calling the SQLCLR Stored Procedure.
Please note: it is generally preferred to use the TOP () clause instead of SET ROWCOUNT n;.
Beware! Microsoft have a bug here:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/83b23289-a24b-4f82-b81f-3e8ccf6d8001/is-this-serious-sqlclr-bug-present-in-sql-server-2012?forum=sqlnetfx
The SqlDataReader class actually briefly grabs a lock yet it should not because SQL CLR approved code should never take locks.
I submitted a sample to MS that proved this, a very simple loop using only approved SQL/CLR classes/methods would cause an AppDomain unload when an SSMS user hits cancel - totally catastrophic.
Here's the reference source, take a look and you'll find "lock" statements - illegal for SQL/CLR yet they approved this class!
https://referencesource.microsoft.com/#system.data/system/Data/SqlClient/SqlDataReader.cs
This says/implies its approved:
https://msdn.microsoft.com/en-us/library/ms131094.aspx
Yet this fails to include it on the most recent approved list:
https://learn.microsoft.com/en-us/sql/relational-databases/clr-integration/database-objects/supported-net-framework-libraries
(Oddly OracleClient is on the list !)
This is bugging me. Something so simple and it does not work. What could I be doing wrong?
Here is the code I am using ...
string strSQL = "SELECT ac.ContactEmail AS fldEmail FROM vwApprenticeshipContactDetails ac WHERE (ac.ApprenticeshipID = #ApprenticeshipID)";
SqlCommand cmd2 = new SqlCommand(strSQL, cnn);
cmd2.Parameters.Add("#ApprenticeshipID", SqlDbType.Int).Value = wsAppID;
Object fldEmail = cmd2.ExecuteScalar();
Believe it or not, the above returns what looks like an array when I debug and look at the value of 'fldEmail'. In otherwords it's empty, nothing or null (cannot tell as the output window shows an array). I have run this directly in SQL server and I get the email showing fine. Could the '#' character inside the database field be causing something here?
The email I expected back is 'g.somebody#domain.com.au', which to me looks ok.
UPDATE
I replaced the ContactEmail field above, with another column name from the database and it comes back fine. Not sure why emails are an issue. The datatype by the way here is VARCHAR(50).
UPDATE
In debug mode I noticed it returns system.DBNull data type (and digging deeper it returns empty), but why? I ran the exact same query with the correct parameter in SQL server and I get a email showing. Strange
Thanks
Solved it!
For some reason (and I am a noob when it comes to email objects in C#), but an ExecuteScalar is not properly populating as it was not "read" first. What I mean by this is that when I changed ExecuteScalar to an SqlReader, it worked because I am "forcing" the read of the SQL before testing it.
So my code looks now like this and it returns an email!
strSQL = #"SELECT TOP 1 ContactEmail FROM vwApprenticeshipContactDetails WHERE ApprenticeshipID = #ApprenticeshipID";
SqlCommand cmd2 = new SqlCommand(strSQL, cnn);
cmd2.Parameters.Add("#ApprenticeshipID", SqlDbType.Int).Value = wsAppID;
using (SqlDataReader rdr = cmd2.ExecuteReader())
{
string fldEmail = "support#domain.com.au"; //this is as a default in case the sql above does not return a value
while (rdr.Read())
{
fldEmail = rdr.GetSqlValue(0).ToString();
}
}
I was avoiding SqlReader initially because I thought they were specifically designed for when reading in more than one row of data. In my case I know the parameter given only returns one row or nothing at all.
Thanks
At the first change select to top 1 for performance reason.
string strSQL = "SELECT Top 1 ac.ContactEmail AS fldEmail FROM ...
If you dont have any result in query, you will get null value as result.
You can check how many records returned by query in sql server profiler.
Also you can check your connection string to make sure are you connected to correct database.
This question already has answers here:
Get the generated SQL statement from a SqlCommand object?
(25 answers)
Closed 6 years ago.
Scenario
I am executing a stored procedure using ADO.NET SqlCommand:
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_Trk_GetSuspiciusVisitor";
cmd.Parameters.Add(new SqlParameter("channel","gb"));
cmd.Parameters.Add(new SqlParameter("data", DateTime.Today.AddDays(-1)));
cmd.Connection = conn;
I would like to log the executed sql statement. In this case I would like to log the string:
sp_Trk_GetSuspiciusVisitor 'gb', '2012-08-12'
Question
Is there any property of the SqlCommand or of the SqlConnection classes that does the job?
There is no magic way to do this, but there are a number of tools that can play nicely with ADO.NET to capture what is happening. For example, mini-profiler does this by wrapping ADO.NET, which usually involves just a single change to your "create a connection" code - it then logs operations internally. The code is open source, so it would be trivial to tweak it to your own logging framework.
As an example, if I go (logged in) to SEDE, and look at a random page, here, say, I can see all the logged SQL operations (no code changes were necessary to get this logging), here - or in case that becomes unavailable:
The only minor glitch is your explicit use of SqlParameter, which might need changing to cmd.CreateParameter(). Alternatively, use something like dapper to make it easier:
conn.Execute("sp_Trk_GetSuspiciusVisitor",
new { channel = "gb", data = DateTime.Today.AddDays(-1) },
commandType: CommandType.StoredProcedure);
Note that the declare statements show above were not part of the original query; the tool has added these to make it easy to run the query in SSMS, etc.
no, unfortunatelly you would have to loop through all the paramenters to get their values and concatenate it with the command text
or edit your stored procedure to do the logging by editing it to add the equivalent of:
insert into my_sp_log
values ('sp_trk_getSuspiciousVisitor', #channel, #data, getdate())
My code is construct to read data in a datagridView named (dg) from my database.
Its actually work well whit a SqlDataAdapter.
First Is it a good idea to change my SqlDataAdapter for a SqlCommand ?
If YES
I want to use this for change my SqlDataAdapter.
//SqlCommand cmd = new SqlCommand("Command String", con);
//SqlDataReader readdata;
CODE
SqlConnection con = new SqlConnection(dc.Con);
SqlDataAdapter da = new SqlDataAdapter();
con.Open();
da.SelectCommand = new SqlCommand("SELECT * FROM tblContacts", con);
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
dg.DataSource = dt;
I typically use the DataAdapter for data access when I need to do data-binding to controls. It's very convenient and efficient in those scenarios. Otherwise, I use the Command objects directly. Performance-wise, I'm inclined to agree w/ punzki. There shouldn't be much difference between the two.
http://msforums.ph/forums/p/9057/9057.aspx
Actually, from what I remember, SqlDataAdapter uses SqlDataReader to retrieve records. So It's always good to use SQLDataReader when you're going to just retrieve data from the backend. But if you're going to retrieve data and then update (insert, update, delete) data later on, then it's better to use SqlDataAdapter. I think it's more efficient that way.
http://msforums.ph/forums/t/29256.aspx
There IS an effect on performance.
SqlDataReader is no doubt faster than a SqlDataAdapter as the DataReader reads data in a forward only mode and you can get a specific type of value returned back to you, such as a string or int etc... however with the SqlDataAdapter, it will fill a datatable or dataset will records it finds in your select statement, taking with it the correct value type for the columns and is a disconnected representation of in memory database and is ideal and easier to use if you are going to show large amounts of records to a binding source, as with a SqlDataReader, it is not possible but to only obtain a value for a column you specify per row.
The SqlDataAdapter also allows you to Update, Delete or Insert rows into the Dataset/DataTable which is an advantage and will execute the appropriate command, if you implemented it correctly, based on how the rows were modified in the Dataset/DataTable.
SqlDataAdapter is expensive compared to a fast forward read on the SqlDataReader, and has more advantages but entirely depends on your solution and what you require.
You are stating that you are going to show alot of records, whilst that is all very well, it would be even better for the benefit of the performance and memory usage to only obtain records that you require to be shown and a SqlDataAdapter would be suitable for this also but still you are required to select records which are the ones you will most likely show to the user, either by input search criteria, or perhaps by paging.
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/c2d762fd-f4a0-4875-8bb8-42f7480e97c8/