I have a problem running a simple insert query from my C# app towards a Postrges DB.
This is the function that builds the query:
string push = "INSERT INTO \"Tasks\"( \"TName\", \"Desc\", \"TType\", \"DCreated\", \"DEnd\") VALUES (\'" + this.Name + "\',\'" + this.Descr + "\'," + this.Type + ",\'" + this.StartDate + "\', \'" + this.EndDate + "\');";
GenericDbClass.ExecutePush(push);
And this is the string that gets passed to the DB:
INSERT INTO "Tasks"( "TName", "Desc", "TType", "DCreated", "DEnd") VALUES ('dddddd','dddddddddddd',3,'13.04.2015 17:00', '24.04.2015 16:42');
If I copy the string and run it inside pgAdmin it works right of the bat, but from here it doesn't do anything - no exceptions thrown,no errors, nothing in the logs, as if it just doesn't reach the server.
In addition here is the push method:
public static void ExecutePush(string sql)
{
try
{
NpgsqlConnection conn = new NpgsqlConnection(GenericDbClass.GetDbConnString());
conn.Open();
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
conn.Close();
}
catch (Exception msg)
{
MessageBox.Show(msg.ToString());
throw;
}
}
Edit: This is the working solution I found
public static void ExecutePush(string sql)
{
try
{
NpgsqlConnection conn = new NpgsqlConnection(GenericDbClass.GetDbConnString());
conn.Open();
NpgsqlCommand nc = new NpgsqlCommand(sql, conn);
nc.ExecuteNonQuery();
conn.Close();
}
catch (Exception msg)
{
MessageBox.Show(msg.ToString());
throw;
}
}
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
Means "Please create a data-adaptor that uses the INSERT SQL passed as sql to do a selection". That doesn't make much sense, and then you don't do anything with it, anyway.
conn.CreateCommand(sql).ExecuteNonQuery();
Seems more like what you want.
Related
In Excel writing a VSTO Plugin (using C#) I'm trying to retrieve a value from a SQL database using OLEDB. When I debug this function, it fails on the catch.
The message I get is:
must declare the scalar variable \"#uname\"
But I already did this when I bound the parameter. What am I doing wrong?
public static int getUserID(string username)
{
int result = 0;
string sql = #"select top 1 [ID] FROM " + tbl_users + " WHERE ( [UNAME]=#uname );";
Console.WriteLine("sql: " + sql);
using (OleDbConnection conn = new OleDbConnection(connStr))
{
try
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#uname", username);
result = (int)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
result = -15;
}
finally
{
conn.Close();
conn.Dispose();
}
}
return result;
}
So I think I figured it out... This change works, but I don't really like it.
First I need to use OleDb parameter binding and not SqlParameter binding.
It also seems like OleDb does not like custom naming parameters like #uname and instead relies on the order of parameters (I don't like this).
So here's the fix in case anyone was interested:
public static int getUserID(string username)
{
int result = 0;
string sql = #"select top 1 [ID] FROM " + tbl_users + " WHERE ( [UNAME]=? );";
Console.WriteLine("sql: " + sql);
using (OleDbConnection conn = new OleDbConnection(connStr))
{
try
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.Parameters.Add("?", OleDbType.VarChar).Value = Convert.ToString(username);
result = (int)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
result = -15;
}
finally
{
conn.Close();
conn.Dispose();
}
}
return result;
}
I created the following code:
public static bool setHeadword(int id, string headword)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\pms.mdf;Integrated Security=True";
conn.Open();
SqlCommand command = new SqlCommand("UPDATE headwords SET Headword = #headword WHERE Id = #id", conn);
command.Parameters.AddWithValue("#headword", headword);
command.Parameters.AddWithValue("#id", id);
int result = command.ExecuteNonQuery();
conn.Close();
return true;
}
But the code doesn't work because the value in the database doesn't change.
If I run the code manually in the database the change takes place. But it won't work with C#.
Also the result variable are holding the right number of affected rows (1 in this case).
I'm not sure I have to flush the changes or something else.
Thanks for your help and best regards
Franz
static void Update(int id, string headword)
{
try
{
//You should create connectionString with correct details otherwise fail connection
string connectionString =
"server=.;" +
"initial catalog=employee;" +
"user id=sa;" +
"password=123";
using (SqlConnection conn =
new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd =
new SqlCommand("UPDATE headwords SET Headword=#headword" +
" WHERE Id=#Id", conn))
{
cmd.Parameters.AddWithValue("#Id", id);
cmd.Parameters.AddWithValue("#headword", headword);
int rows = cmd.ExecuteNonQuery();
}
}
}
catch (SqlException ex)
{
//Handle sql Exception
}
}
I'm trying to write a method to check if a table exists. I am trying to use the using statement to keep it consistent through my database.
public void checkTableExists()
{
connectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\keith_000\Documents\ZuriRubberDressDB.mdf;Integrated Security=True;Connect Timeout=30";
string tblnm = "BasicHours";
string str = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = " + tblnm + ");";
SqlDataReader myReader = null;
int count = 0;
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(str, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
MessageBox.Show("The count is " + count);
myReader = command.ExecuteReader();
while (myReader.Read())
{
count++;
}
myReader.Close();
MessageBox.Show("Table Exists!");
MessageBox.Show("The count is " + count);
}
connection.Close();
}
}
}
catch (SqlException ex)
{
MessageBox.Show("Sql issue");
}
catch (Exception ex)
{
MessageBox.Show("Major issue");
}
if (count > 0)
{
MessageBox.Show("Table exists");
}
else
{
MessageBox.Show("Table doesn't exists");
}
}
It throws an exception when it hits the try block. It catches in the SqlException block.
This is the point where I am learning to interact with databases again. The solution would be good, but more importantly, a brief explanation of where I have need to learn how to improve my code.
Thanks
Keith
Your code fails because when you write directly a query searching for a string value then this value should be enclosed in single quotes like 'BasicHours'.
However there are some improvements to apply to your actual code.
First, you can use a simplified sql command.
Second, you use parameters instead of string concatenations.
SqlCommand cmd = new SqlCommand(#"IF EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #table)
SELECT 1 ELSE SELECT 0", connection);
cmd.Parameters.Add("#table", SqlDbType.NVarChar).Value = tblName;
int exists = (int)cmd.ExecuteScalar();
if(exists == 1)
// Table exists
This command text don't require you to use an SqlDataReader because the query returns just one row with one 'column' and the value of this single cell is either 1 or 0.
A lot less overhead.
A part from this, it is of uttermost importance, that you never build sql queries concatenating strings. This method is well know to cause problems.
The worse is called SQL Injection and could potentially destroy your database or reveal confidential information to hackers. The minor ones are crashes when the string concatenated contains single quotes. Use always a parameterized query.
I have used the following code in my project and worked for me:
try
{
using (con = new SqlConnection(Constr);)
{
con.Open();
string query = $"IF EXISTS (SELECT * FROM sys.tables WHERE name = '{tableName}') SELECT 1 ELSE Select 0;"
Exists = int.Parse(sqlQuery.ExecuteScalar().ToString())==1;
con.Close();
}
}
catch{}
The problem could be the line: string tblnm = "BasicHours";. You table name is a string and should be apostrophed, try this: string tblnm = "'BasicHours'";
Inside catch blocks you could also log exception messages and details.
Thanks for the help on this issue. This is the solution that I'm implemnenting.
public void checkTableExists()
{
connectionString = #"
Data Source=(LocalDB)\MSSQLLocalDB;
AttachDbFilename=C:\Users\keith_000\Documents\ZuriRubberDressDB.mdf;
Integrated Security=True;
Connect Timeout=30";
string tblName = #"BasicHours";
string str = #"IF EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #table)
SELECT 1 ELSE SELECT 0";
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(str, connection))
{
connection.Open();
SqlCommand cmd = new SqlCommand(str, connection);
cmd.Parameters.Add("#table", SqlDbType.NVarChar).Value = tblName;
int exists = (int)cmd.ExecuteScalar();
if (exists == 1)
{
MessageBox.Show("Table exists");
}
else
{
MessageBox.Show("Table doesn't exists");
}
connection.Close();
}
}
}
catch (SqlException ex)
{
MessageBox.Show("Sql issue");
}
catch (Exception ex)
{
MessageBox.Show("Major issue");
}
}
I am extremely new to C# web development (or any development for that matter) but I am trying to figure out how to save the results from a SQL query to a variable. I think I understand the process, but many of the examples I am finding on the Web use a SqlConnection statement. My copy of Visual Studio does not seem to have that command (pretty sure I am using the wrong word here). What am I missing either softwarewise or knowledgewise accomplish my task?
Thank you in advance for your help.
Dep
It depends on what you want to do: insert, update, get data. It also depends if you want to use an ORM library or not. I all depends. The code that I copy below is an example of how to retrieve a DataTable using Ado.Net (as you mentioned SqlConnection):
You have to use:
using System.Data;
using System.Data.SqlClient;
This is the code for retrieving a DataTable
private DataSet ExecuteDataset(string query)
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
DataSet ds;
try
{
conn.Open();
ds = new DataSet();
var da = new SqlDataAdapter(query, conn);
da.Fill(ds);
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
return ds;
}
private DataSet ExecuteDataset(string query, SqlParameter[] parametros)
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
DataSet ds;
try
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = query;
foreach (SqlParameter p in parametros)
{
command.Parameters.Add(p);
}
ds = new DataSet();
var da = new SqlDataAdapter(command);
da.Fill(ds);
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
return ds;
}
This is the code for running a query that does not expect result with and without parameters:
private void ExecuteNonQuery(string query)
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
try
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = query;
command.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
}
private void ExecuteNonQuery(string query, SqlParameter[] parametros)
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
try
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = query;
foreach (SqlParameter p in parametros)
{
command.Parameters.Add(p);
}
command.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
}
Here is the simplest example I can think of, take note of the using statements and comments
using System;
using System.Data;
using System.Data.SqlClient;
namespace DataAccess
{
class Program
{
static void Main(string[] args)
{
//Use your database details here.
var connString = #"Server=localhost\SQL2014;Database=AdventureWorks2012;Trusted_Connection=True;";
//Enter query here, ExecuteScalar returns first column first row only
//If you need to return more records use ExecuteReader/ExecuteNonQuery instead
var query = #"SELECT [AccountNumber]
FROM [Purchasing].[Vendor]
where Name = #Name";
string accountNumber = string.Empty;
//Using statement automatically closes the connection so you don't need to call conn.Close()
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(query, conn);
//Replace #Name as parameter to avoid dependency injection
cmd.Parameters.Add("#Name", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = "Michael";
try
{
conn.Open();
//Cast the return value to the string, if it's an integer then use (int)
accountNumber = (string)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Console.WriteLine(accountNumber);
//ReadKey just to keep the console from closing
Console.ReadKey();
}
}
}
If you are really new to C# with SQL Server, I would recommend to start from scratch using one of the tutorials shown here. It provides a lot of information in a step-by-step manner:
The basics
Clearly definition of the core ceoncepts
How to setup dependencies to get started
How to choose between development models (code, model vs. database first)
How to write queries
and much more.
Using SqlConnection is a valid choice, but requires more effort in writing the queries for doing basic stuff like selecting, updating, deleting or inserting data. You actually have to construct the queries and take care to build and dispose the commands.
On a related note:
The new way of doing all database-related activities in C# or .NET would be to harness Entity Framework (EF), and try to move away from any ADO.NET-based code. The latter still exists and hasn't been marked as obsolete, though. You may want to use ADO.NET for small apps or for any PoC tasks. But, otherwise, EF is the way to go.
EF is an ORM, and is indeed built as a repository pattern and generates a conceptual layer for us to work with. All of the nuances of the connection and command are completely encapsulated from us. This way, we don't have to meddle with these bare-bones.
If you want to do it well, you have to edit a file named Web.config in your project and put something like this inside (with your own DB data):
<connectionStrings >
<add
name="myConnectionString"
connectionString="Server=myServerAddress;Database=myDataBase;User ID=myUsername;Password=myPassword;Trusted_Connection=False;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Then, in the code, you can use it with:
SqlConnection con = new SqlConnection(
WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
Finally you can do that you want with "con", for example:
string queryString = "SELECT name, surname FROM employees";
SqlCommand command = new SqlCommand(queryString, con);
con.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader["name"], reader["surname"]));
}
}
finally
{
reader.Close();
}
i use this nuget library.
https://www.nuget.org/packages/SqlServerDB_dotNET/
using SqlServerDB;
string server = #"INSTANCE\SQLEXPRESS";
string database = "DEMODB";
string username = "sa";
string password = "";
string connectionString = #"Data Source="+ server + ";Initial Catalog="+ database + "; Trusted_Connection=True;User ID="+ username + ";Password="+ password + "";
DBConnection db_conn = new DBConnection(connectionString);
Console.WriteLine("IsConnected: " + db_conn.IsConnected());
if (db_conn == null || !db_conn.IsConnected())
{
Console.WriteLine("Connessione non valida.");
return;
}
string sql = "SELECT ID, Message FROM Logs ORDER BY IDLic;";
DataTable dtLogs = db_conn.SelectTable(sql);
if (dtLogs == null || dtLogs.Rows.Count == 0)
return;
// Loop with the foreach keyword.
foreach (DataRow dr in dtLogs.Rows)
{
Console.WriteLine("Message: " + dr["Message"].ToString().Trim());
}
I am trying to save some data in a database using an INSERT query but it is saving double value on single click. For example I save 'Lahore', it'll save it two times:
Lahore
Lahore
SqlConnection conn = new SqlConnection("Data Source = HAMAAD-PC\\SQLEXPRESS ; Initial Catalog = BloodBank; Integrated Security = SSPI ");
try
{
conn.Open();
SqlCommand query = new SqlCommand("insert into City values('" + txtCity.Text + "')", conn);
query.ExecuteNonQuery();
SqlDataReader dt = query.ExecuteReader();
if (dt.Read())
{
MessageBox.Show("Saved....!");
}
else
{
MessageBox.Show("Not saved.....");
}
}
catch (Exception ex)
{
MessageBox.Show("Failed....." + ex.Message);
}
Your code is doing exactly what you told it to.
If you call an Execute*() method twice, it will run your query twice.
It's saving twice because you are executing the query twice:
query.ExecuteNonQuery();
SqlDataReader dt = query.ExecuteReader();
You are saving twice.
The executeNonQuery will return the number of rows affected so use this instead.
SqlConnection conn = new SqlConnection("Data Source = HAMAAD-PC\\SQLEXPRESS ; Initial Catalog = BloodBank; Integrated Security = SSPI ");
try
{
conn.Open();
SqlCommand query = new SqlCommand("insert into City values('" + txtCity.Text + "')", conn);
var rowsAffected = query.ExecuteNonQuery();
if (rowsAffected == 1)
{
MessageBox.Show("Saved....!");
}
else
{
MessageBox.Show("Not saved.....");
}
}
catch (Exception ex)
{
MessageBox.Show("Failed....." + ex.Message);
}