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.
Related
I have virtual dataGridView which displays all values in table by Just-In-Time method documentation here. My view has more computed columns, so I use it only to show data and then only delete by single SQLCommand.
The problem comes when I am executing the delete command. When I execute it, it throws error
Conversion failed when converting the nvarchar value 'TextValueFromThirdColumn' to data type int.
xxx is not ID, but computed data in third column.
using(SqlConnection c = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
c.Open();
SqlCommand command = new SqlCommand("delete from entryTable where ID = #id", c);
command.Parameters.AddWithValue("#id", dataGridView1.SelectedRows[0].Cells["ID"].Value.ToString());
command.ExecuteNonQuery();
}
As you can see I am building query with parameter which adds just fine, but the error thrown seems inadequate for me, because third column has nothing to do with my ID column. Thanks in advance for any advice
Okay, It was my dumb fault. This is problem with trigger on SQL server. I did not realize I made changes to database layout and trigger stopped working because it inserted values into wrong column. The error code showed what happened with trigger, not with row.
I'm trying to properly bind a Data Adapter to my SQL database to insert records submitted by a person in a c# program. I feel like I am 80% of the way, but now i've hit a hitch.
So as in the code below, I can create and bind a Data Table just fine. I've tested the delete functions and they work just fine. I am now attempting to have a 'save' button insert a new row to my database. The problem I have now is that a user is supposed to put in their 'notes' and then hit save. I auto populate the rest of the columns, but I do not know how to grab the notes that the user entered.
Here is my code so far:
string userVerify = User.CurrentUser.UserName.ToString();
int participantID = this.mParticipant.ParticipantID;
DateTime date = DateTime.Now;
string properRow = dtNotes[1, dtNotes.NewRowIndex - 1].Value.ToString();
sqlDataAdapter.InsertCommand = new SqlCommand("INSERT INTO xxMyDatabasexx (ParticipantID,Verifier,Notes,Date) VALUES (#participantID,#notes, #userVerify,#date);");
sqlDataAdapter.InsertCommand.Parameters.AddWithValue("#participantID", participantID);
sqlDataAdapter.InsertCommand.Parameters.AddWithValue("#userVerify", userVerify);
sqlDataAdapter.InsertCommand.Parameters.AddWithValue("#date", date);
sqlDataAdapter.InsertCommand.Parameters.AddWithValue("#notes", properRow);
sqlDataAdapter.Fill(dataTable);
sqlDataAdapter.Update(dataTable);
I am aware that the properRow variable's logic is wrong. Of course if there are no rows then the program will crash, but also if no new note has been entered it will just reproduce the last note entered which of course is wrong as well. When i look into my dataTable at the time of sqlDataAdapter.Fill, I can see the note in the correct column but I don't know how to simply save it.
Any help is appreciated. Thanks.
EDIT:
What I was unaware of is that the InsertCommand (naturally) also needs the ExecuteNonQuery command with it. I was under the assumption that since both Delete and Update did not, that Insert wouldn't either. This seemed to fix the issue. Thanks all for the help.
You can insert the record into SQL Database without need for DataAdapter just by using Command object as shown in the following code snippet (just pass your Insert SQL statement string):
void SqlExecuteCommand(string InsertSQL)
{
try
{
using (SqlConnection _connSqlCe = new SqlConnection("Conn String to SQL DB"))
{
_connSql.Open();
using (SqlCommand _commandSqlCe = new SqlCommand(CommandSQL, _connSql))
{
_commandSql.CommandType = CommandType.Text;
_commandSql.ExecuteNonQuery();
}
}
}
catch { throw; }
}
The general format of SQL INSERT query string is shown below:
INSERT INTO YourTable (column1,column2,column3,...)
VALUES (value1,value2,value3,...);
You can further extend this solution by adding parameters to the SQL String/Command in order to protect against possibility of SQL injection (see the following example):
INSERT INTO YourTable (column1,column2,column3,...)
VALUES (#param1,#param2,#param3,...);
_commandSql.Parameters.Add("#param1","abc");
_commandSql.Parameters.Add("#param2","def");
_commandSql.Parameters.Add("#param3","ghijklm");
You can also use the alternative syntax for SQL Parameters, like for e.g.:
_commandSql.Parameters.Add("#param1", SqlDbType.NChar).Value = "abc";
_commandSql.Parameters.Add("#param2", SqlDbType.NChar).Value = "def";
_commandSql.Parameters.Add("#param3", SqlDbType.NVarChar).Value = "ghijklm";
Pertinent to your particular question, it should be like:
"INSERT INTO xxMyDatabasexx (ParticipantID, Verifier, Notes, [Date]) VALUES (#participantID, #userVerify, #notes, #dt)"
_commandSql.Parameters.Add("#ParticipantID",SqlDbType.NChar).Value= participantID;
_commandSql.Parameters.Add("#userVerify",SqlDbType.NChar).Value= userVerify ;
_commandSql.Parameters.Add("#notes",SqlDbType.NVChar).Value= properRow ;
_commandSql.Parameters.Add("#dt",SqlDbType.DateTime).Value= DateTime.Now;
Note: in case ParticipantID is the IDENTITY (i.e. Autonumber) Column, then do not include it in INSERT statement.
Hope this may help.
It seems to me that You are a bit lost. The way adapters are meant to work is
fill table from database via adapter (or take empty table)
bind table to GUI or manually transfer the information to GUI
change/add/delete data in table via binding or manually
update changes (inserts/updates/deletes) into database via adapter
The changes in table are automatically traced, so the adapter knows, what should be updated/inserted/deleted and use appropriate commands.
If You use adapter just as a holder for command You can ExecuteNonQuery with arbitrary parameters, You pass the whole concept and do not need adapter at all (see #AlexBells answer).
Apart from this, are You really going to write all that plumbing code by hand? Life is too short. If I were You, I would look for some ORM. You get simple CRUDs or concurrency checking with no effort.
I am working on a C# windows form which is connected to MySQL and updates strings within the form. I have everything working properly except for a small issue.
Say you want to update the "notes" field to read "The dog's bone", that apostrophe is causing the SQL query to end and cause an error. How can I get around this please?
UPDATE `database`
SET `notes` = 'The dog's bone'
WHERE `Pet` = 'Dog';
Thanks!
You can escape ' character in MySQL with doubling it like ''.
Other than that, if you use parameterized queries, you will not need this at all. Just pass your The dog's bone string directly to your parameterized query and you will be fine.
Also I strongly suspect you try to use UPDATE instead of SELECT statement. In MySQL, SELECT syntax doesn't have any SET part.
And using a reserved keyword as a column name is a bad idea. As a best practice, change your database column name to non-reserved word.
using(var con = new MySqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"UPDATE `database` SET notes = #notes
WHERE Pet = #pet";
cmd.Parameters.AddWithValue("#notes", "The dog's bone");
cmd.Parameters.AddWithValue("#pet", "Dog");
con.Open();
cmd.ExecuteNonQuery();
}
I used AddWithValue method as an example in my code since I didn't know your column types but you don't use it. This method may generate unexpected and surprising results sometimes. Use Add method overloads to specify your parameter type and it's size.
Escape it with another single quote ':
SELECT `database`
SET `notes` = 'The dog''s bone'
WHERE `Pet` = 'Dog';
I am writing a C# WPF application with controls bound to a MySQL 5.5 database. I'm populating a DataTable using a MySqlDataAdapter, passing in a MySQL SELECT query.
When the query is something trivial, like SELECT * FROM People or SELECT LastName, FirstName, PersonID FROM People, all is well and my ListBox control ends up populated with the expected names.
When the query contains a fairly simple CONCAT operator, though, the query silently fails and the ListBox stays empty. In particular neither of the following have worked, even though both work fine from within the MySQL command line.
SELECT CONCAT(LastName, FirstName) as Name FROM People
SELECT CAST(CONCAT(LastName, FirstName) AS CHAR) as Name FROM People
Both LastName and FirstName are defined as VARCHAR. So, I wouldn't expect this to be an instance of CONCAT returning a binary string in any case. I mention that because it appears to have been the problem for similar issues that other folks have mentioned.
I'd imagine the DataAdapter attempts to parse your query into an internal format so that it can do things like generate Update and Insert commands.
Can you fill your datatable using a MySqlDataReader instead? This is probably only helpful if you are not planning to do database updates with the DataTable
Going from memory...
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader reader = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
Please help me to store apostrophe. I m creating a website (C#, .net, SQL Server) and want to have a message box for the users but the problem is that when I inserts any message such as John's it shows an error near ''s'.
Please tell me how could I store apostrophe in database
I used nvarchar, varchar and everything but failed to store apostrophe containing messages.
A general solution is to write message with double apostrophe but this is not a solution for a website
You are open for SQL-Injection. Don't concatenate strings to build your query. Instead use SQL-Parameters. That also makes your code more readable and prevents errors like yours.
Here's an example:
int amt;
using (var con = new SqlConnection(ConnectionString)) {
var sql = "INSERT INTO dbo.Message(UserID, Message) VALUES(#UserID, #Message);";
using (var cmd = new SqlCommand(sql, con)) {
cmd.Parameters.AddWithValue("#UserID", userID); // passed as argument
cmd.Parameters.AddWithValue("#Message", txtMessage.Text); // f.e. "John's"
con.Open();
int inserted = cmd.ExecuteNonQuery();
}
}
The same works also with other sql like UPDATE commands.
The problem is that you need to escape Apostrophe by another Apostrophe.
For example have a look at:http://sqlfiddle.com/#!3/d2f75/1
CREATE TABLE tblTEst( col1 NVARCHAR(50))
INSERT INTO tblTest
(Col1)
SELECT 'John''s'
The best solution is to use a prepared statement (or whatever the equivalent in C# is) where your SQL only contains placeholders and you pass the actual values through a different method.
In a character literal, the single quote ' can be used by simply doubling it:
insert into foo (bar)
values
('John''s');
use CHAR(39)between john & s like this: 'john'+CHAR(39)+'s'