I am using C# for a WPF application in Visual Studio Express 2012. I followed the tutorial found here.
I created a testDb.mdf local Service-based database. I open the application, enter text, hit add, and the data adds to the db. I only know this because I have the one field setup as a primary key and unique. If I try to add the same thing again I get an error saying it already exists.
When I exit my application nothing shows in the database. The data I entered is gone. Why is the data not permanent?
Here is the code I'm using for my button click:
private void Add_Click(object sender, RoutedEventArgs e)
{
SqlConnection cn = new SqlConnection(global::testdb.Properties.Settings.Default.testDBConnectionString);
try
{
string sql = "INSERT INTO Test (TestInsert) Values('" + txtName.Text + "')";
SqlCommand cmd = new SqlCommand(sql, cn);
cn.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Added new record", "Message", MessageBoxButton.OK);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message,"Error", MessageBoxButton.OK);
}
finally
{
cn.Close();
}
}
Connection String:
<connectionStrings>
<add name="testdb.Properties.Settings.testDBConnectionString"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\testDB.mdf;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
It is a common scenario. You have a connection string that uses the substitution string |DataDirectory|. In a desktop application this directory is usually the same directory where your program runs. Inside Visual Studio, your program runs in the BIN\DEBUG (or x86 variant) directory. Thus the Visual Studio copies your MDF file from the project directory to the BIN\DEBUG folder. You add records to this copy, not to the one in the project folder. However, the Visual Studio Server Explorer window has a connection that points to the Project Folder database that, of course, remains empty.
You could add another connection to the Server Explorer pointing to the folder BIN\DEBUG and check that your database has been updated or not.
To complicate the matter, there is the property Copy to the Output Directory associated with the MDF file. If this property is set to Copy Always everytime you start a new session within Visual Studio, the file is copied again from the project folder to the output directory (BIN\DEBUG) overwriting the copy already there with a new empty one. So the first run succeds, the second one fails.
The symptoms that you observed are a clear sign of this situation.
Simply change the property Copy to the Output directory to Copy if newer, the code works well.
(Peraphs it is too early, but remember to change your query to a parameterized query. As is, you could break your code simply inserting a single quote in the txtName textbox like O'Malley, not to mention the Sql Injection hack)
I think your issue is not with the insert code. It's with the way you're checking the database/table yourself. Particularly because you say you're getting primary key errors so something's being added to the table.
Are you sure you're refreshing your view of the table properly? Are you sure you're checking the right table in the right database?
Make sure your initial catalog is set in your connection string, and be sure you are pointing to the right server/ instance of SQL. You may have multiple instances of SQL Server on the same server or whatever DB Server you are using. Also ensure you're going to the right table, of course.
using (SqlConnection cn = new SqlConnection(#"Persist Security Info=False;Integrated Security=true;Initial Catalog=testDB;server=(local)"))
{
string sql = "INSERT INTO Test (TestInsert) Values('" + txtName.Text + "')";
SqlCommand cmd = new SqlCommand(sql, cn);
cn.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Added new record", "Message", MessageBoxButton.OK);
}
Check in SQL Server Studio that the database exists. I don't recommend using the filename mdf in your code directly using AttachDbFilename. Use the initial catalog.
Well, i found the solution. I solved it by installing SSDT(SQL server data tools) for visual studio. Install it according to your visual studio version. Go to following link to download the SSDT for visual studio.
https://msdn.microsoft.com/en-us/mt186501
In the following of the Steve's answer you can get your database full path in properties window and substitute it with |DataDirectory| in string connection.
your code will be like
conn.ConnectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=G:\MhD\c#\phonebook\phonebook\phonebook\tellbook.mdf;Integrated Security=True";
Related
What is the proper way to create a local-database file and then connect the app to it ? I want it to work even if you change the location of the project folder.
Right know what I do is: Project -> Add new item -> Service-based Database and I create one and then I go to Data -> Add new Data Source, I add the created database and I get the connection string.
Ok, all good, I can connect to it as I wish BUT all my data is erased from the database when I close the application (not always).
For example, this code:
SqlConnection c = new SqlConnection(#"DataSource=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\DB.mdf;Integrated Security=True;User Instance=True");
c.Open();
SqlCommand cmd;
cmd = new SqlCommand("CREATE TABLE Persons (id int primary key, nume char(20), age int)");
cmd.ExecuteNonQuery();
cmd = new SqlCommand("INSERT INTO Persons VALUES (#id, #name, #age)", c);
cmd.Parameters.AddWithValue("#id", 1);
cmd.Parameters.AddWithValue("#name", "Catalin");
cmd.Parameters.AddWithValue("#age", 20);
cmd.ExecuteNonQuery();
I run it first time to create the table and add an item to it and then, then if I run it the second time without the sqlcommand to create the table persons, it tells me that there is no Persons object, BUT if I run the second time the project with the same code, it tells me that there is already a Persons object...
I am using Visual C# Express Edition 2010.
The whole User Instance and AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Mgmt Studio Express - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio Express
create your database in SSMS Express, give it a logical name (e.g. MyDatabase)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=MyDatabase;Integrated Security=True
and everything else is exactly the same as before...
Also see Aaron Bertrand's excellent blog post Bad habits to kick: using AttachDbFileName for more background info.
Change the Copy to output directory setting from Copy always to Copy if newer in the property page for your database files. Every time you run the application the new database file is copied from your project to the bin folder, so all of your datas from the previous run are removed.
More: https://msdn.microsoft.com/en-us/library/ms246989.aspx
I figured out a pretty simple answer but maybe it's not the best use to do it this way.
Anyway, I add the database to the project and then I connect directly to it by doing so:
string path = Path.GetDirectoryName(Path.GetDirectoryName(Directory.GetCurrentDirectory)));
SqlConnection c = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=""" + path + #"Database1.mdf"";Integrated Security=True;User Instance=True");
This way, if you move your project between multiple PCs, the connection will still work (I needed this the most).
This also works with .SDF files and it's easier too.
I have a Windows web application and have created a .mdf file in the App_Data folder and I am trying to insert data into the tables already created.
It is able to retrieve codes with a basic SELECT * statement, but I can't insert data, this is the code I have:
private void Update(string username)
{
SqlConnection con = new SqlConnection(#"MYSQLCONNECTION");
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
string bcd = "INSERT INTO NameList(name) VALUES (#paraUsername)";
cmd = new SqlCommand(bcd, con);
cmd.Parameters.AddWithValue("#paraUsername", username);
cmd.ExecuteNonQuery();
list.Update();
con.Close();
}
This code has worked for me in the past, but this time round it does not work. There is no error shown, but the data is not inserted into the table.
This is how I call the method in side my button_click method:
Update(tbName.text);
What might be the problem?
Assuming you have a
AttachDbFileName=......
section in your connection string - then this is a known issue:
The whole AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Mgmt Studio Express - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio Express
create your database in SSMS Express, give it a logical name (e.g. YourDatabase)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=YourDatabase;Integrated Security=True
and everything else is exactly the same as before...
Also see Aaron Bertrand's excellent blog post Bad habits to kick: using AttachDbFileName for more background info.
I tried too many times but insertion doesn't work!
Please help me..
codes:
SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True");
conn.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO mytbl(Id, Nav) VALUES('yek','du')", conn); //yek and du are examples
//Following command doesn't work, too
//"INSERT INTO mytbl(Id, Nav) VALUES('"+tb.Text+"','"+tb2.Text+"')"
cmd.ExecuteNonQuery();
conn.Close();
The whole User Instance and AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Mgmt Studio Express - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio Express
create your database in SSMS Express, give it a logical name (e.g. VictoryDatabase)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=VictoryDatabase;Integrated Security=True
and everything else is exactly the same as before...
Also see Aaron Bertrand's excellent blog post Bad habits to kick: using AttachDbFileName for more background info.
Your code is working but the db(.mdf) is getting copied to \bin\debug directory first and the app is using that one(\bin\debug\Database1.mdf). Use the following code to get the db (.mdf) path which is present at your App root directory.
string path = AppDomain.CurrentDomain.BaseDirectory.ToLower().Replace("\\bin", "").Replace("\\debug", "").Replace("\\release", "").TrimEnd('\\');
string conStr = "Data Source=(LocalDB)\\v11.0;AttachDbFilename=" + path + "\\Database1.mdf;Integrated Security=True";
I'm fight with a strange error occurs a couple of day ago and I'm not able to find a solution.
I have a C# Form application that talks with a SQL database made by Visual Studio Express (.mdf file). Everything works fine if my connection string points to the database in the root directory (where the DB has been automatically created by VS). I can compile the executable in Debug and Release.
To do a test in a different machine (where I copied the executable file and the database .mdf)I have changed the connection string in order to point to the database in the same executable directory and, in this case, it doesn't work (both release and debug).
I come to my PC and I use the same connection string above pointing not to the DB in the root directory bu to DB in Release directory.
The strange thing is that it works in debug but not in release.
The error occurs is the following one
Exception: One or more files do not match the primary file of the
database. If you are attempting to attach a database, retry the
operation with the correct files. If this is an existing database,
the file may be corrupted and should be restored from a backup. Could
not open new database 'C:\USERS\TEST\VISUAL
STUDIO\PROJECTS\LEONARDO\LEONARDO
0.1.1.1\LEONARDO\BIN\RELEASE\DB.MDF'. CREATE DATABASE is aborted. An attempt to attach an auto-named database for file C:\Users\Test\Visual
Studio\Projects\Leonardo\Leonardo 0.1.1.1\Leonardo\bin\Release\DB.mdf
failed. A database with the same name exists, or specified file cannot
be opened, or it is located on UNC share. Log file
'C:\Users\Test\Visual Studio\Projects\Leonardo\Leonardo
0.1.1.1\Leonardo\bin\Release\DB.ldf' does not match the primary file. It may be from a different database or the log may have been rebuilt
previously.
and the code is
string Result = string.Empty;
SqlConnection conn = new SqlConnection(Settings.DataBasePath);
try
{
conn.Open();
}
catch (Exception ex)
{
string Errore = String.Format("Exception: {0}", ex.Message);
MessageBox.Show(Errore);
throw;
}
SqlDataReader leggi = null;
//SqlCommand comando = new SqlCommand("SELECT " + "Database Version" + " FROM Data", conn);
SqlCommand comando = new SqlCommand("SELECT * FROM Data", conn);
leggi = comando.ExecuteReader();
while (leggi.Read())
{
Result += leggi["Database Version"].ToString().TrimEnd();
}
conn.Close();
Best regards
Your problem is here:
Log file 'C:\Users\Test\Visual Studio\Projects\Leonardo\Leonardo 0.1.1.1\Leonardo\bin\Release\DB.ldf' does not match the primary file.
You should make sure your debug and release folders contain the same .mdf and .ldf files.
I'm making an ASP.net with c# webapp using VS 2008, and I added a new sql database item to my project. I added tables to the databse. In the database explorer the test connection works. I guess I have two questions. One:In the application, how does one connect to the database using a connection string? or what connection string should I use? Second: How do I add a username and password to the database?
Right now I'm using this connection string in the web.config file, but when I run the app it times out and says it can't make a connection. The error is on the conn.open line.
add name="ReportsConnectionString" connectionString="Data Source=(local); Initial Catalog=REPORTS;Integrated Security=True" providerName="System.Data.SqlClient"
I have this code in one of my page's codebehind.
string sqlquery = "SELECT * FROM reportitems";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ReportsConnectionString"].ConnectionString))
{
conn.Open();
using (SqlCommand comm = new SqlCommand(sqlquery, conn))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(comm))
{
DataSet ds = new DataSet();
adapter.Fill(ds, "reportitems");
DataRowCollection dra = ds.Tables["reportitems"].Rows;
foreach (DataRow dr in dra)
{
string DRZ = dr[0].ToString();
//more stuff here
}
}
}
}
Usually SqlServer Express is reachable on your local PC using this syntax for the Data Source parameter yourpcname\SQLEXPRESS. To be sure start Management Studio and look at the Server Name request.
For the security part of your question, I suppose that you don't want the Integrated Security option (Windows User), but you want a SQLServer user. In this case you could use the User ID and Password parameters for the connection string:
Data Source=MYPC\SQLEXPRESS;Initial Catalog=REPORTS;User Id=MYNAME;Password=MYPASS;
However, this works only after you have added this user to the SQLServer.
You could use the interface of Management Studio app or you could execute a script like this
USE [master]
GO
CREATE LOGIN [MYNAME] WITH PASSWORD=N'MYPASS', DEFAULT_DATABASE=[master]
GO
USE [REPORTS]
GO
CREATE USER [MYNAME] FOR LOGIN [MYNAME]
GO
The Integrated Security=True part of the connectionstring means that the server will use the credentials of the app pool running the site, and you don't need to specify username or password. The app pool identiy will, however, need to have access to your database.
Visit http://www.connectionstrings.com/ for a good primer on various ways to set the connection string for various applications. That'll show you why (local) didn't work but .\SQLEXPRESS did and how to add username and password to it. Here's an example lifted from http://www.connectionstrings.com/sql-server-2008
Data Source=myServerAddress;Initial Catalog=myDataBase;User
Id=myUsername;Password=myPassword;
As others have said, you need a SqlExpress engine running as .mdf is not a flat file. It is a SQL server express database file and you need to connect to it.
But what have not said is that a Database in your App_Data folder needs to be attached to the SqlServer instance. This step is only done once in the first connection.
In http://www.connectionstrings.com/sql-server-2008 you will find an example in the "Attach a database file, located in the data directory, on connect to a local SQL Server Express instance" section that looks like this:
Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf; Database=dbname;Trusted_Connection=Yes;
Also you can read this: http://msdn.microsoft.com/en-us/library/ms247257.aspx
I believe that you will need to run some scripts and stuff like that to create a user and assign permissions to this user in this database, and then change the connection string (once the database attached), so I don't see a point in having the database in the App_Data folder. I believe it should be better if since the beginning you create your database using the SqlServer tools and connect to it from your application.