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());
}
Related
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 connect to a SQL Server on a local machine, run a SQL command against it and log the results. The code keeps failing at making the connection to the server.
I can't quite see what I'm doing wrong. Everything I've searched for either doesn't apply to this method or seems to match what I'm doing. I think I have other problems in the code as well, but I can't even get past the SQL connection to test the rest. Here is my code:
string svrConnection = "Server=.\\sqlexpress;Database="+db+";User ID=user;Password=password;";
SqlConnection con;
SqlCommand cmd;
Directory.CreateDirectory("C:\\"db"\\");
FileInfo file = new FileInfo("C:\\script.sql");
string PCS = file.OpenText().ReadToEnd();
con = new SqlConnection(svrConnection);
StreamWriter PCSLog = new StreamWriter(#"C:\\" + db + "\\Log" + db + ".txt");
try
{
con.Open();
cmd = new SqlCommand(PCS, con);
cmd.ExecuteNonQuery();
using (SqlDataReader pcsrdr = cmd.ExecuteReader())
using (PCSLog)
{
while (pcsrdr.Read())
PCSLog.WriteLine(pcsrdr[0].ToString() + pcsrdr[1].ToString() + ",");
}
PCSLog.Close();
cmd.Dispose();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection !", ex.Message);
}
There are additional problems with your code:
The Lines
cmd.Dispose();
con.Close();
are not guaranteed to execute if an exception occurs.
You call PCSLog.Close AFTER after you have disposed of it
I would suggest this as a better alternative (irrespective of the other comments made here).
string svrConnection = "Server=.\\sqlexpress;Database="+db+";User ID=user;Password=password;";
Directory.CreateDirectory("C:\\" + db + "\\");
FileInfo file = new FileInfo("C:\\script.sql");
string PCS = file.OpenText().ReadToEnd();
try
{
using (SqlConnection con = new SqlConnection(svrConnection))
{
con.Open();
using (SqlCommand cmd = new SqlCommand(PCS, con))
{
cmd.ExecuteNonQuery();
using (SqlDataReader pcsrdr = cmd.ExecuteReader())
using (StreamWriter PCSLog = new StreamWriter("C:\\" + db + "\\Log" + db + ".txt"))
{
while (pcsrdr.Read())
PCSLog.WriteLine(pcsrdr[0].ToString() + pcsrdr[1].ToString() + ",");
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection !", ex.Message);
}
I think the issue is your connection string. Try this:
string svrConnection = "Data Source=.\\SQLEXPRESS;Initial Catalog=" + db + ";User Id=user;Password=password;"
Or to get a connection using your windows credentials:
string svrConnection = "Data Source=.\\SQLEXPRESS;Initial Catalog=" + db + ";Trusted_Connection=True;"
Also, ExecuteNonQuery does not run each command separated by GO. You will need to split your query into sections and run each individually.
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.
I currently have a little app sends a lot of different MySQL Queries to the server. My idea was to wrap the connection, the query and the read to a function with only the actual query as a parameter.
Here is what I got:
public static MySqlDataReader mySqlRead(string cmdText)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
command.CommandText = cmdText;
try
{
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
return reader;
}
catch (MySqlException)
{
throw;
}
}
I connect and send the query here:
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlDataReader orRead = ORFunc.mySqlRead("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
}
Works like a charm... BUT, as you can see above, the connection is never closed. When I add the conn.Close() behind the .ExecuteReader() the reader is empty and everything after return is of course useless.
Maybe it's a stupid question but I'm rather new to C# so please be generous, any hint is appreciated.
cheers,
PrimuS
I had a similar problem in JAVA recently, but I think the same will work for you. Essentially, you can create a class that represents a "SqlCall" object (or something). The class would have accessible members including the connection and the results. The ctor for the class would take in your query text.
Then, all you would have to do is create a new instance of that class, run the query in a method in that class (which would set and/or return the results), GET the results, and then when you are done, call close() on your class (which would then have to be coded such that it closes the connection held internally).
Technically, a better way to do this is to EXTEND the connection class itself, but as you are new to C#, I will not go into the details of doing so.
As I was writing the code below, I realized I may have not actually answered your question. But there's no point in backing out now, so here's what I have:
public class SqlCall {
private static connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
private MySqlConnection conn;
private MySqlCommand command;
private MySqlDataReader reader;
public SqlCall(String query) {
conn = new MySqlConnection(connString);
command = conn.CreateCommand();
command.CommandText = query;
}
public MySqlDataReader execute() throws Exception {
conn.Open();
reader = command.ExecuteReader();
return reader;
}
public void close() {
reader.close();
conn.close();
}
}
Your login code would be:
private void btnLogin_Click(object sender, EventArgs e) {
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
SqlCall sqlcall = new SqlCall("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
try {
MySqlDataReader orRead = sqlcall.execute();
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
sqlcall.close();
} catch (Exception ex) {
// dostuff
}
}
The point is, unless you copy the data into a new datatable at the very beginning, you'll have to keep the connection open.
On a separate note, YOUR CODE IS PRONE TO SQL INJECTION. Don't know what that is? An example: if I said my username was ';DROP TABLE orUsers;--, then your entire user database would be gone. Look into stored procedures if you want a (very healthy) way around this.
You have difficulties because your idea works against the pattern expected by programs that connects to a database in NET Framework.
Usually, in this pattern you have a method that
INITIALIZE/OPEN/USE/CLOSE/DESTROY
the ADO.NET objects connected to the work required to extract or update data
Also your code has a serious problem called Sql Injection (see this famous explanation) because when you concatenate strings to form your command text you have no defense against a malicious user that try to attack your database
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlParameter p1 = new MySqlParameter("#uname", username);
MySqlParameter p2 = new MySqlParameter("#pass", pass);
string cmdText = "SELECT * FROM orUsers WHERE username = #uname AND pass = #pass"
DataTable dt = ORFunc.GetTable(cmdText, p1, p2);
foreach(DataRow r in dt.Rows)
{
Console.WriteLine(r["ID"].ToString());
}
}
public static DataTable GetTable(string cmdText, params MySqlParameter[] prms)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
// This is the INITIALIZE part
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = new MySqlCommand(cmdText, conn))
{
// OPEN
conn.Open();
DataTable dt = new DataTable();
command.Parameters.AddRange(prms);
// USE
MySqlDataReader reader = command.ExecuteReader();
dt.Load(reader);
return dt;
} // The closing brace of the using statement is the CLOSE/DESTROY part of the pattern
}
Of course this is a generic example and in my real work I don't use very often these generic methods and prefer to write specialized data access code that return the base object needed to the upper layer of code
What's the simplest way to connect and query a database for a set of records in C#?
#Goyuix -- that's excellent for something written from memory.
tested it here -- found the connection wasn't opened. Otherwise very nice.
using System.Data.OleDb;
...
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = "Provider=sqloledb;Data Source=yourServername\\yourInstance;Initial Catalog=databaseName;Integrated Security=SSPI;";
using (OleDbCommand cmd = new OleDbCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "Select * from yourTable";
using (OleDbDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
Console.WriteLine(dr["columnName"]);
}
}
}
}
Very roughly and from memory since I don't have code on this laptop:
using (OleDBConnection conn = new OleDbConnection())
{
conn.ConnectionString = "Whatever connection string";
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "Select * from CoolTable";
using (OleDbDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
// do something like Console.WriteLine(dr["column name"] as String);
}
}
}
}
That's definitely a good way to do it. But you if you happen to be using a database that supports LINQ to SQL, it can be a lot more fun. It can look something like this:
MyDB db = new MyDB("Data Source=...");
var q = from db.MyTable
select c;
foreach (var c in q)
Console.WriteLine(c.MyField.ToString());
This is an alternative way (DataReader is faster than this one):
string s = "";
SqlConnection conn = new SqlConnection("Server=192.168.1.1;Database=master;Connect Timeout=30;User ID=foobar;Password=raboof;");
SqlDataAdapter da = new SqlDataAdapter("SELECT TOP 5 name, dbid FROM sysdatabases", conn);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
s += dt.Rows[i]["name"].ToString() + " -- " + dt.Rows[i]["dbid"].ToString() + "\n";
}
MessageBox.Show(s);
If you are intending on reading a large number of columns or records it's also worth caching the ordinals and accessing the strongly-typed methods, e.g.
using (DbDataReader dr = cmd.ExecuteReader()) {
if (dr.Read()) {
int idxColumnName = dr.GetOrdinal("columnName");
int idxSomethingElse = dr.GetOrdinal("somethingElse");
do {
Console.WriteLine(dr.GetString(idxColumnName));
Console.WriteLine(dr.GetInt32(idxSomethingElse));
} while (dr.Read());
}
}
If you are querying a SQL Server database (Version 7 and up) you should replace the OleDb classes with corresponding classes in the System.Data.SqlClient namespace (SqlConnection, SqlCommand and SqlDataReader) as those classes have been optimized to work with SQL Server.
Another thing to note is that you should 'never' select all as this might lead to unexpected results later on if you add or remove columns to this table.
I guess, you can try entity framework.
using (SchoolDBEntities ctx = new SchoolDBEntities())
{
IList<Course> courseList = ctx.GetCoursesByStudentId(1).ToList<Course>();
//do something with courselist here
}
Charge the libraries
using MySql.Data.MySqlClient;
This is the connection:
public static MySqlConnection obtenerconexion()
{
string server = "Server";
string database = "Name_Database";
string Uid = "User";
string pwd = "Password";
MySqlConnection conect = new MySqlConnection("server = " + server + ";" + "database =" + database + ";" + "Uid =" + Uid + ";" + "pwd=" + pwd + ";");
try
{
conect.Open();
return conect;
}
catch (Exception)
{
MessageBox.Show("Error. Ask the administrator", "An error has occurred while trying to connect to the system", MessageBoxButtons.OK, MessageBoxIcon.Error);
return conect;
}
}