In the light of Closing connections explicitly in Entity Framework and http://msdn.microsoft.com/en-us/library/bb738582%28v=vs.90%29.aspx it seems that I should be using the context to create connections rather than doing the following
using (SqlConnection con = new SqlConnection("Persist Security Info=False;Integrated Security=true;Initial Catalog=Remember;server=(local)"))
{
...
}
My understanding is that I'll
Get rid of the connection string
Utilize connection pooling built into EF
But how do I acquire an SQL connection through the context?
In EF5 (changed for EF6) the following would return the connection:
var connection = ((EntityConnection)context.Connection).StoreConnection;
If you are using EF in a right way you will probably never need to get inner db connection.
I used next code to getting connection (Entity Framework 5.0):
var connection = Context.Database.Connection;
I found out that the magic lies in ExecuteStoreCommand()
new AdventureEntities().ExecuteStoreCommand(
#" UPDATE Users
SET lname = #lname
WHERE Id = #id",
new SqlParameter("lname", lname), new SqlParameter("id", id));
Then there is no need for an explicit Connection, it actually made the code a lot cleaner. The one-liner above replaced all of the following code
using (SqlConnection con = new SqlConnection("Persist Security Info=False;Integrated Security=true;Initial Catalog=Remember;server=(local)"))
{
con.Open();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = #"
UPDATE Users
SET lname = #lname
WHERE Id = #id";
cmd.Parameters.AddWithValue("lname", lname);
cmd.Parameters.AddWithValue("id", id);
cmd.ExecuteNonQuery();
}
}
var efConnectionStringBuilder = new EntityConnectionStringBuilder(efConnectionString);
string sqlConnectionString = efConnectionStringBuilder.ProviderConnectionString;
If the EF connection string is stored in your web config file, you can assign it to a SQL Data Source with this code:
var connString = ConfigurationManager.ConnectionStrings["MyDataEntities"].ConnectionString;
EntityConnection ec = new EntityConnection(connString);
var storeConnect = ec.StoreConnection;
SqlDataSource1.ConnectionString = storeConnect.ConnectionString;
I believe the easiest way to create a SqlConnection in EF6 is to do the following:
DBContext context = new DBContext();
SqlConnection sqlconn = new SqlConnection(context.Database.Connection.ConnectionString);
You could use the following as well. I wanted to inject some Dapper.NET into a existing project that already had Entity framework entity context so I created the following:
public class EFConnectionAccessor : IDisposable
{
private readonly SqlConnection sqlConnection;
private readonly MyEntities entities;
public EFConnectionAccessor()
{
entities = new MyEntities();
var entityConnection = entities.Connection as EntityConnection;
if (entityConnection != null)
{
sqlConnection = entityConnection.StoreConnection as SqlConnection;
}
}
public SqlConnection connection
{
get
{
sqlConnection.Open();
return sqlConnection;
}
}
public void Dispose()
{
sqlConnection.Close();
sqlConnection.Dispose();
entities.Dispose();
}
}
Called using
using (SqlConnection sqlConnection = new EFConnectionAccessor().connection)
{
// ADO.NET CODE HERE - Or in my case dapper.net
}
the DataContext will allow you to call your Entity Objects right off of your DataContext reference, abstracting away all of the details of the underlying connection logistics.
Related
I want to create a class that has SQL connection and functions (like insert, select, delete queries) and I want to call it to my forms (buttons and etc.)
I don't know if it's possible or not or maybe there are some ways on doing this so...
I've done some research and come up with this code on class SQL connection and I'm not sure if it's correct.
Thank you very much in advance. I'm a beginner and want to learn more on c#.
Any type of response is appreciated. Thank you
Sorry for my bad English
using System.Data.SqlClient;
class SqlConnClass
{
public static SqlConnection GetConnection()
{
string str = "Data Source=localhost;Initial Catalog=kwem;Integrated Security=True;";
SqlConnection conn = new SqlConnection(str);
conn.Open();
return conn;
}
You were close! You may want to take the `conn.Open()' out of your method as you can open it for your query. (Remember to close it or put it in a using statement!)
public static void UpdateDB(string valToUpdate)
{
SQLConnection conn = GetConnection();
using (conn)
{
SQLCommand updateCommand = new SQLCommand(GetConnection(), "Update Table
Set Val = #newValue");
updateCommand.Parameters.AddWithValue("#newValue", valToUpdate);
conn.Open();
updateCommand.ExecuteNonQuery();
}
}
You would then do the same for any other kind of DB functions.
It's true but; if your string str do not work. Please try this:
string str = "Data Source=local host ;Initial Catalog=kwem;Integrated Security=True"
also you need to define sql table and then select your database.
You are on the right path.
What you are referring to is called a data access layer, or DAL for short.
It's a part of the n-tier architecture model (in the simple version there are 3 tiers - presentation, business logic and data access layer).
The basic concept is that you separate the presentation, logic and data into 3 different parts of the application.
As for the data access layer, usually you'll have a static or singleton class responsible to connect the business layer to the data. This class will contain methods for CRUD operations - Create, Read, Update and Delete data. You will need to create methods for each operation and for each data entity.
One approach I see all the time is this:
public static class DAL
{
private static string _ConnectionString = null;
static DAL() // A static constructor to initialize the connection string
{
_ConnectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
}
public static DataSet GetCategories()
{
var ds = new DataSet();
var sql = "SELECT * FROM Categories";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(ds);
}
}
}
return ds;
}
public static int DeleteCategory(int categoryId)
{
int rowsEffected = 0;
var sql = "DELETE FROM Categories WHERE Id = #Id";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add("#Id", SqlDbType.Int).Value = categoryId;
con.Open();
cmd.ExecuteNonQuery();
}
}
return rowsEffected;
}
}
and so on. As you can see, there is a lot of code that repeats itself.
This means longer code, herder maintenance, and if for some reason you will want to support other types of databases (like migrating to MySql, Oracle or whatever) You will have to work very hard to change all the vendor specific classes in your DAL (SqlConnection, SqlCommand etc`).
These problems are exactly the reason I wrote ADONETHelper. I've been using it for a few years (mostly in earlier, different forms) and I feel now it's matured enough to go public. It's currently under MIT licence, meaning it's completely free and you can download your copy and change it as you see fit.
Should you choose to use it, your DAL class should probably look like this:
public static class DAL
{
private static IDBHelper _DB;
static DAL() // A static constructor to initialize _DB
{
// initialize connection string from config file
var connectionstring = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
_DB = DBHelperFactory.GetInstance(DataBaseType.SQLServer, connectionstring);
}
public static DataSet GetCategories()
{
var sql = "SELECT * FROM Categories";
return _DB.FillDataSet(sql, CommandType.Text);
}
public static int DeleteCategory(int categoryId)
{
var sql = "DELETE FROM Categories WHERE Id = #Id";
var param = _DB.CreateParameter("#Id", ADONETType.Int, categoryId);
return _DB.ExecuteNonQuery(sql, CommandType.Text, param);
}
}
As you can see, code repetitions are down to the bare minimum, and migrating to a different database is as simple as changing the static constructor to use a different DataBaseType. Of course, if you are using vendor-specific sql you will have to change that too.
What I want to do is have text boxes for the user to input the required fields for the connection to the MySQL table, Here is the code I currently have.
public partial class Form1 : Form
{
MySqlConnectionStringBuilder conn_string = new MySqlConnectionStringBuilder();
conn_string.Server = serverTextBox.Text;
conn_string.UserID = userTextBox.Text;
conn_string.Password = passwordtextBox.Text;
conn_string.Database = dataBaseTextBox.Text;
using (MySqlConnection mcon = new MySqlConnection(conn_String.ToString()));
MySqlCommand mcd;
MySqlDataAdapter mda;
//-----open connection-----//
public void openCon()
{
if (mcon.State == ConnectionState.Closed)
{
mcon.Open();
}
}
//-----close connection-----//
public void closeCon()
{
if (mcon.State == ConnectionState.Open)
{
mcon.Close();
}
}
}
I really have no idea how to setup a MySQL connection properly and this was my (failed) best guess.
here is a new picture that might help http://prntscr.com/bgubj5
There should be a lot of reasons of Your problem. You posted only small piece of code, which is not enaught. If You want to connect do database consider following steps:
-make proper connection string (it depends on the database)
-connection string can be make from user inputs, but must be known before calling MySqlConnection
so, firstly save the user inputs to variable, make connectionstring of them, and finally pass it to MySqlConnection constructor
PS. this would help with making connectionstring: https://www.connectionstrings.com/
What exceptions does it throw?
Build the connection string first. Set a breakpoint and check if it looks good.
Or an even better approach will be to use the MySqlConnectionStringBuilder object
your code will look like this:
MySqlConnectionStringBuilder conn_string = new MySqlConnectionStringBuilder();
conn_string.Server = serverTextBox.Text;
conn_string.UserID = userTextBox.Text;
conn_string.Password = passwordtextBox.Text;
conn_string.Database = dataBaseTextBox.Text;
using (MySqlConnection conn = new MySqlConnection(conn_string.ToString()))
using (MySqlCommand cmd = conn.CreateCommand())
{
//query whatever you want, be aware of SQL injection
}
I have a problem. I cannot fix the problem with The ConnectionString property has not been initialized. The problem is in this method:
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand())
{
using (TransactionScope ts = new TransactionScope())
{
products.Update(dataSet, "Produktai");
offers.Update(dataSet, "Pasiulimai");
ts.Complete();
}
}
connection.Close();
}
}
catch
{ }
In the class constructor i already have a SqlDataAdapter and SqlCommandBuilder declared. My connection string is in App.config and it looks like this:
<connectionStrings>
<add name="connectionString" connectionString="server=ANDREW-PC\LTSMSQL;database=MarketDB; Integrated Security=true;" providerName="System.Data.SqlClient" />
In my program I already assigned this connection string parameter to string variable. Here is a code sample:
private string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
Any ideas how I can fix this error?
The command isn't assigned to the connection. You need to use the sqlcommand constructor like so: new SQLCommand(connection, "querystring"). I also suggest you use a newer technology such as ORM. I used basic ADO.NET data access before I found Fluent NHibernate, and Fluent is so much easier to use :-)
why are you using System.Transaction.TransactionScope? are you dealing with multiples transaction aware data sources such as sql server and oracle, where you need a transaction manager to coordinate the transaction? if not, then why don't you create a transaction from the connection?
using (var connection = new System.Data.SqlClient.SqlConnection(" "))
{
connection.Open();
var tran = connection.BeginTransaction();
var cmd = new System.Data.SqlClient.SqlCommand();
cmd.Connection = connection;
cmd.Transaction = tran;
//I dont know how the sql command relates to this
products.Update(dataSet, "Produktai");
offers.Update(dataSet, "Pasiulimai");
//commit
tran.Commit();
}
Ok, I just found the problem. For some reasons my database was "read only" for me when I connect with visual studio. I have changed some settings in the database and now it works fine. Thanks for your answers. :)
I am trying to make a simple MS Access Database connection by using the SqlConnection and SqlCommand objects.
As you can see here is how I make the connection:
private SqlConnection GetConnection()
{
String connStr = ConfigurationManager.ConnectionStrings[0].ConnectionString;
SqlConnection conn = new SqlConnection(connStr);
return conn;
}
And before you ask, yes I have tried to move this piece of code to the method that calls it. Didn't change anything. It still reads the connection string wrong.
The connection string looks like this and is located in the App.config file:
<add name="ConnString" connectionString="Server=*.*.*.*;Database=familie;User Id=mfs;Password=********;"/>
But when I get this error:
And look at the connection string object at the time, the string looks like this:
"data source=.\\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
I have spent about 2 hours now trying to make this work, going to many different sites to figure out what I did wrong, but I either get information is that is too old, conflicting or deals with connecting to a local database, when this is in fact an external one access through a proxy that was given to me by my client (TrustGate if anyone should ask)
The method that calls GetConnection() looks like this:
public Dictionary<int,String> GetPostNrList()
{
SqlConnection conn = GetConnection();
SqlCommand cmd = new SqlCommand("Execute dbo.HENT_POST_NR_LISTE", conn);
var reader = cmd.ExecuteReader();
Dictionary<int, String> liste = new Dictionary<int, string>();
while (reader.NextResult())
{
int post_nr = (int) reader.GetSqlInt32(0);
String by = reader.GetString(1);
liste.Add(post_nr, by);
}
CloseConnection(conn);
return liste;
}
What exactly am I doing wrong?
The exception message tells you exactly what the problem is - your connection is not open. You just need to open the connection prior to executing a command:
conn.Open();
BTW, a good pattern is to using a using block when dealing with SQL connections, to ensure it gets disposed properly:
using (var conn = GetConnection())
{
using (var comm = xxxxxxx)
{
conn.Open();
using (var rdr = comm.ExecuteReader())
{
// xxxxx
}
}
}
You don't have to specifically close anything - the using pattern does all that for you.
I tried to insert some data into my database (sql server/local file) but it doesn't work.
public bool SaveCookie(string cookie, string expires)
{
SimpleDBM db = new SimpleDBM();
db.Connect();
try
{
string query = string.Format("INSERT INTO Cookies(cookie_value, cookie_expires) VALUES('{0}', '{1}');", cookie, expires);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = query;
//...
SqlDataReader data = db.Query(ref cmd);
return data.Read();
}
catch
{
return false;
}
finally
{
db.Close();
}
}
The SimpleDBM class:
public class SimpleDBM {
public static string dbpath = #"...";
public static string dbname = "db.mdf";
public static string dfullPath = Path.Combine(dbpath, dbname);
public static string connStr = string.Format(#"Data Source=.\SQLEXPRESS;AttachDbFilename={0};Integrated Security=True;Connect Timeout=30;User Instance=True", dfullPath);
private SqlConnection con;
public void Connect()
{
con = new SqlConnection();
con.ConnectionString = connStr;
con.Open();
}
public SqlDataReader Query(ref SqlCommand cmd)
{
cmd.Connection = con;
return cmd.ExecuteReader();
}
public void Close()
{
con.Close();
}
}
Can someone point out my mistake? For other queries it seems to work fine.
Thanks in advance.
The problem seems to be that you're trying to execute a query that doesn't return a result set using the ExecuteReader method of the SqlCommand class which will attempt to execute your query and create and return a DataReader for an eventual result set.
You should use ExecuteNonQuery for INSERT and UPDATE sql statements.
SIDE NOTE
Not that it's the reason you're getting the error but you should also consider using SqlParamters instead of composing the values into the INSERT statement. Using prepared SQL statements generally gives a performance enhancement and also helps prevent SQL injection attacks.
For an example of using prepared statements, see the MSDN page or the Prepare method.
You are using a ExecuteReader when you should be using ExecuteNonQuery.
Not related to your error you really should not be using String.Format with SqlCommand. What you should do is
string query = "INSERT INTO Cookies(cookie_value, cookie_expires) VALUES(#cookie, #expires);", cookie, expires);
SqlCommand cmd = new SqlCommand();
cmd.Parameters.AddWithValue("#cookie", cookie);
cmd.Parameters.AddWithValue("#expires", expires);
cmd.CommandText = query;
With your method ask your self if someone passed a cookie of ' ''); Drop table Cookies --? This is called a "Sql Injection Attack" and is one of the top 5 reasons websites get hacked.
EDIT
Just to help give another example of why using String.Format to pass values you did not generate is bad.