In my C# application, I do the following:
using (SqlConnection connection = new SqlConnection(connectionstr))
{
connection.Open();
SqlCommand com1 = new SqlCommand("insert into Anfangstierbestand(bestand, jahr, loginid) VALUES (" + bestand + ", " + jahr + ", " + loginid + ");", connection);
SqlCommand com2 = new SqlCommand("select * from Anfangstierbestand;", connection);
com1.Connection = connection;
int ferksum = 0;
com1.ExecuteNonQuery();
connection.Close();
connection.Open();
SqlDataReader read = com2.ExecuteReader();
while (read.Read())
{
ferksum += Convert.ToInt32(read[2]);
}
// MessageBox.Show("Fehler beim Erstellen des Tierbestandes", "Fehler"); }
MessageBox.Show(ferksum.ToString());
}
It's a simple insert to a database. I added com2 to check, if the insert works.
Unfortunately, the the value of com2 tells me, that it works, but when I go to the Server Explorer and press Execute SQL, there are no new values.
I don´t know the reason. The code above is just an example, since a few days, no insert works anymore(before, the same code works).
Does anybody know what the reason can be?
EDIT:
C#:
string connectionstr = "Data Source=.\\SQLEXPRESS;" + "AttachDbFilename=|DataDirectory|\\Datenbank\\FarmersCalc.mdf;" + "Integrated Security=True;" + "User Instance=true;";
EDIT2:
Server Explorer:
Data Source=.\SQLEXPRESS;AttachDbFilename="C:\Users\user\Desktop\Farmer´s Calc\Programmierung\WPF\Finanz_WPF\Finanz_WPF\Datenbank\FarmersCalc.mdf";Integrated Security=True;User Instance=True
EDIT3:
Here are the columns:
id int,
jahr int,
anzahl int,
loginid int
EDIT4:
Is it possible that it´s a problem that I opened my project with expression blend? Normally, I work with VS 2010...
EDIT5:
Even because I can not answer my question(<100 reputations) I write it here:
Shame on me. Some of you were right, it was the wrong database-file. But I´m still wondering, why this happened, because I did not change anything since a few days and before this, it worked!
Thanks to all for helping!
You're using user instances, why? Isn't it possible that the instance you're connecting to in Server Explorer is not the same as the instance where your app is inserting data? What happens when you select data from within the app, does it reflect your insert(s)? It seems to me based on your connection strings that these are two completely different MDF files - they have the same name but they are in different locations.
Is the issue implicit transactions? Do you need to issue a commit of the SQL Insert? If com2 tells you that it's there then it may only see it since it's in the context of the current SQL transaction.
You should share your connection string for both Server Explorer and your SqlConnection (connectionstr). Ensure that you setup your Server Explorer connection with User Instance=true;.
As a diagnostic,
connection.Open();
int n = com1.ExecuteNonQuery();
// log or show 'n' , the nr of rows affected
Edit, after seeing the connectionstrings:
local db files in |DataDirectory|\ are very prone to be overwritten by the next run or build command.
Make sure you set them to 'copy never' or 'copy if newer' in the VS Solution explorer.
Perhaps somewhere in the callstack above this code, someone has added a TransactionScope.
This would cause the connections to enroll automatically in the transaction, and the connections could see the data inserted via that not-yet-committed transaction. When the scope is exitted without calling scope.Complete, the transaction gets rolled back and no data is saved.
Related
I'm new to coding. I'm attempting to access a SQL Server file through WPF / C# and I am having trouble getting in the correct string, I believe. I do not yet fully understand SQL logins, but here is the code I have now, which I believe as close to correct as I can get on my own:
string CS = #"Data Source=(LocalDB)\v11.0; Integrated Security=true; AttachDbFileName=C:\Users\Madison\source\repos\TheRealStudyBot\TheRealStudyBot\TestingData.mdf";
SqlConnection con = new SqlConnection(CS);
SqlCommand cmd = new SqlCommand("CREATE TABLE table1 (PK int, Name nvarchar(255), PRIMARY KEY *PK),);", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
con.Close();
This code is under public MainWindow(), after InitializeComponent(). The file path should be correct. The database is empty. I get this exception:
Win32Exception: Unknown error (0x89c50118)
Ran it once more and I think I may have accidentally altered my debug settings because now it also provides a window stating
The solution does not contain the specified document
(along with plenty of other jargony-code-exception-results-text). I don't see where I'm going wrong. Please help!
If you are on Visual Studio 2019,
Double Click on your LocalDB which opens Server Explorer
Clicking on your database, On the properties tab shows the connection string.
Copy that & Paste on CS!
And the Normal Connection String Format For LocalDB is,
Data Source=Your_DataSource;Initial Catalog=YourDatabaseName;Integrated Security=True;Pooling=False
Yes, I know that this questions has been asked at least 5-10 times in here, but I can't for the life of me get any of the methods to save the data.
The idea is to create a new row in table Companies in column Name (there is only one column) with value "asdf"`.
I've tried combinations of the following:
DatabaseDataSetTableAdapters.CompaniesTableAdapter adapter = new DatabaseDataSetTableAdapters.CompaniesTableAdapter();
DatabaseDataSet ds = new DatabaseDataSet();
adapter.Insert("asdf");
adapter.Fill(ds.Companies);
adapter.Update(ds.Companies);
ds.AcceptChanges();
ds.Companies.AddCompaniesRow("asdf");
ds.Companies.AcceptChanges();
ds.Companies.AddCompaniesRow("asdf");
ds.Companies.Rows[0]["Name"] = "asdf";
adapter.Update(ds.Companies);
I'm using C# WPF .NET 4.5.1
It does add the data, but it doesn't save it when I exit the program - I know that it adds data, because if I call this method twice it crashes, because the value is no longer unique.
Here is the DatabaseDataSetTableAdapters:
http://pastebin.com/gNsaRFD5
This did not work either:
SqlConnection myConnection = new SqlConnection(global::AliBabaMailer.Properties.Settings.Default.DatabaseConnectionString);
myConnection.Open();
SqlCommand myCommand = new SqlCommand("INSERT INTO Companies (Name) " +
"Values ('string')", myConnection);
myCommand.ExecuteNonQuery();
myConnection.Close();
Ok so your problem is the Connection String:
Properties.Settings.Default.DatabaseConnectionString
This connection string is of the form:
“Data Source=ServerName;AttachDbFilename=|DataDirectory|\DataBaseName;Integrated Security=True”
The |DataDirectory| is usually here:
C:\Users\UserName\AppData
When you save the data it is being saved to a database file at `|DataDirectory| location but when you try to view the data using Server Explorer you are trying to view from a database file which is in your project's folder, that is why If you try to save and then view the data on run time it will work fine because then you will be querying the same database you are storing your data into.
|DataDirectory|:
|DataDirectory| (enclosed in pipe symbols) is a substitution string that indicates the path to the database. It eliminates the need to hard-code the full path which leads to several problems as the full path to the database could be serialized in different places. |DataDirectory| also makes it easy to share a project and also to deploy an application.
For example, instead of having the following connection string:
"Data Source= c:\program files\MyApp\Mydb.sdf"
Using DataDirectory, you can have the following connection string:
“Data Source = |DataDirectory|\Mydb.sdf”
To set the DataDirectory property, call the AppDomain.SetData method. If you do not set the DataDirectory property, the following default rules will be applied to access the database folder:
For applications that are put in a folder on the user's computer, the database folder uses the application folder.
For applications that are running under ClickOnce, the database folder uses the specific data folder that is created.
Link
Coding Advice:
Try to dispose your Command and Connection Objects like this:
using(SqlConnection myConnection = new SqlConnection(global::AliBabaMailer.Properties.Settings.Default.DatabaseConnectionString))
using(SqlCommand myCommand = new SqlCommand("INSERT INTO Companies (Name) " + "Values ('string')", myConnection))
{
myConnection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
}
after connecting to database in C#
string MyConString2 = "SERVER=localhost;" + "user id=mytest;" + "DATABASE=clusters;" + "PASSWORD=mypass;";
I have an algorithm which I need to after each run of algorithm that will fill the database, drop the database "clusters" of mysql manually and again connect to the empty database and run it again,gaining new data in tables
I want to make it automatically how can I drop or empty my database if exists in C# and then run my algorithm?
Here is example code that works and I think this is what you are talking about, if not, feel free to correct me.
using (var connection = new MySqlConnection("server=localhost;user=root;password="))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "drop schema if exists clusters";
command.ExecuteNonQuery();
command = connection.CreateCommand();
command.CommandText = "create schema clusters";
command.ExecuteNonQuery();
}
Prepare sql query for clearing your DB and test it in f.e. MySQL workbench. Following this, just execute it as you would execute regular query against DB in C#. One way is to clear all the tables in your database by using TRUNCATE statement and the second way is to DROP DATABASE and recreate it.
I have a SQL Server database in a C# project.
I use a connection string to connect to it.. I can use the method ExecuteNonQuery to insert data, no problem there.
But when I delete, it only deletes it momentarily, as soon as I restart the application it kind of rolls back the deletion.. Any ideas?
PS: I tested the string in a direct query, and it worked fine there.
public void executeNonQuery(string input)
{
db.Open();
SqlCommand cmd = new SqlCommand(input, db);
cmd.ExecuteNonQuery();
db.Close();
}
EDIT: DELETION CODE:
private void buttonSletPost_Click(object sender, EventArgs e)
{
if(dataGridView1.GetCellCount(DataGridViewElementStates.Selected)>0){
for (int i = 0;i < dataGridView1.GetCellCount(DataGridViewElementStates.Selected); i++)
{
String str1 = String.Format("WARNING about to DELETE:\n {0} \n BE CAREFULL NO TURNING BACK NOW!", Regnskab.getInstance().dbSelectPostID(dataGridView1.SelectedCells[i].Value.ToString())[0].ToString());
if (MessageBox.Show(str1, "Confirm Deletion", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
string str = String.Format("DELETE FROM PostTable WHERE PostID={0}", dataGridView1.SelectedCells[i].Value.ToString());
Database.getInstance().executeNonQuery(str);
Console.WriteLine(str);
}
}
}else {MessageBox.Show("No cells selected");}
}
Which will give following output:
DELETE FROM PostTable WHERE PostID=7
Connection string in app.config:
<connectionStrings>
<add name="EndProject.Properties.Settings.DBtestConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\DBtest.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True" providerName="System.Data.SqlClient" />
private Database()
{
string connStr = ConfigurationManager.ConnectionStrings["EndProject.Properties.Settings.DBtestConnectionString"].ConnectionString;
db = new SqlConnection(connStr);
}
And then I open and close it, so the connection ain't open each time.
To be honest:
I don't exactly know where to see my DB info, here's some info from properties in VS2010.
Provider: .NET Framework Data Provider for SQL Server
Type: Microsoft SQL Server
Andrew's 3rd: I think they are deleted momentarily because I reloaded the information in my datagridview and from there it is gone. But then when I close the application and start it again, it is back...
Also i just checked with VS2010's server explorer and did a "Show Data" after I deleted (before I shut it down) and it wasn't deleted.
But I'm totally clueless now. :-(
Many applications use Transactions to manage db connections. SQL Server doesn't do it by default, but other factors in your application may be doing this.
Also, if you're really doing this, and your input is coming from a user interface, I can't wait to introduce you to Little Bobby Tables
Use the SQL Server Profiler to run a trace and capture the actual T-SQL statements that are getting executed on the database.
This is the easiest solution.
The behavior you're describing sounds like autocommit is off. Try the following and see if the record(s) stays deleted:
public void executeNonQuery(string input)
{
db.Open();
using (var txn = db.BeginTransaction())
{
SqlCommand cmd = new SqlCommand(input, db);
cmd.Transaction = txn;
cmd.ExecuteNonQuery();
db.Close();
txn.Commit();
}
}
Ok it was apperently me who was mistaken on the inserting part...
Someone suggested that i was because of the Visual Studio databases created every time the applikation ran.
So i installed MS SQL 2008 R2. Created a new DB with same layout.
Changed the connection string
And wuupti woo it seems to work, ill come back to this thread if it breaks down later..
But delete + insert both working greatly now :-)
Thanks to all who tried to help!
I'm using following code to restore databases,
void Restore(string ConnectionString, string DatabaseFullPath, string backUpPath)
{
string sRestore =
"USE [master] RESTORE DATABASE [" + DatabaseFullPath + "] FROM DISK = N'" + backUpPath + "' WITH FILE = 1, NOUNLOAD, STATS = 10";
using (SqlConnection con = new SqlConnection(ConnectionString))
{
con.Open();
SqlCommand cmdBackUp = new SqlCommand(sRestore, con);
cmdBackUp.ExecuteNonQuery();
}
}
but I receive below exception
"Exclusive access could not be obtained because the database is in use.
RESTORE DATABASE is terminating abnormally.
Changed database context to 'master'."
How can I fix it ?
A restore can only happen if the database does not have any connections to it (besides yours). The easy way on a MS SQL Server to kick all users off is:
ALTER DATABASE [MyDB] SET Single_User WITH Rollback Immediate
GO
Now, you can perform your restore with impunity. Make sure you set it back to Multi-user mode when you're done with the restore:
ALTER DATABASE [MyDB] SET Multi_User
GO
Thus I've written the below method to restore my database,
Am I in right way ?
void Restore(string ConnectionString, string DatabaseFullPath, string backUpPath)
{
using (SqlConnection con = new SqlConnection(ConnectionString))
{
con.Open();
string UseMaster = "USE master";
SqlCommand UseMasterCommand = new SqlCommand(UseMaster, con);
UseMasterCommand.ExecuteNonQuery();
string Alter1 = #"ALTER DATABASE [" + DatabaseFullPath + "] SET Single_User WITH Rollback Immediate";
SqlCommand Alter1Cmd = new SqlCommand(Alter1, con);
Alter1Cmd.ExecuteNonQuery();
string Restore = #"RESTORE DATABASE [" + DatabaseFullPath + "] FROM DISK = N'" + backUpPath + #"' WITH FILE = 1, NOUNLOAD, STATS = 10";
SqlCommand RestoreCmd = new SqlCommand(Restore, con);
RestoreCmd.ExecuteNonQuery();
string Alter2 = #"ALTER DATABASE [" + DatabaseFullPath + "] SET Multi_User";
SqlCommand Alter2Cmd = new SqlCommand(Alter2, con);
Alter2Cmd.ExecuteNonQuery();
labelReport.Text = "Successful";
}
}
The best approach
Alter Database <Db_Name> SET [SINGLE_USER | RESTRICTED_USER]
With ROLLBACK [IMMEDIATE | AFTER 30]
go
--do your job that needs exclusive access
go
--Back to normal mode
Alter Database <Db_Name> SET MULTI_USER
WITH ROLLBACK IMMEDIATE - this option doesn't wait for transactions
to complete it just begins rolling back all open transactions
WITH ROLLBACK AFTER nnn - this option will rollback all open
transactions after waiting nnn seconds for the open transactions to
complete. In our example we are specifying that the process should
wait 30 seconds before rolling back any open transactions.
When RESTRICTED_USER is specified, only members of the db_owner,
dbcreator, or sysadmin roles can use the database. MULTI_USER returns
the database to its normal operating state.
2nd way :using ssms 2008 R2 we can do the same thing
right-click database property
go to options -> last section with header of state
change Restrict Access to SINGLE_USER
answer yes to this helpful question which shows that this kind of action will close all other connections and i guess it is the only thing we are looking for here to by pass the error
To change the database properties, SQL Server must close all other connections to the database. Are you sure you want to change the properties and close all other connections? yes or no
restore your database
do step 1-4 changing Restrict Access back to MULTI_USER
3rd way : the following commands will also close all connections too.
ALTER DATABASE [DbName] SET OFFLINE
go
ALTER DATABASE [DbName] SET ONLINE
now database is ready for restore
More (mssqltips :Getting exclusive access to restore SQL Server databases)
You can use the method on SMO SqlServer object to kiil all processes on a specified database before performing a restore:
sqlServer.KillAllProcesses("databaseName");
The reason for this issue is self-evident (connections to the database currently open/active), but use the following (google it too so you understand it) and it'll be fine:
Alter Database YOURDB
SET SINGLE_USER With ROLLBACK IMMEDIATE
GO
Obviously, replace YOURDDB with the name of your database and run that against the master DB.
Oh, and just incase, if you get it 'stuck' in single user mode, this will undo it:
Alter Database YOURDB
SET MULTI_USER With ROLLBACK IMMEDIATE
GO
Hope this helps.
EDIT:
You can also follow this, to see where the connections are from, and other information:
I tested this while having services
running that would reconnect to the
database. I found you had to set to
Single User Mode, then run sp_who2 to
see where the one connection was
coming from, and note the SPID. You
can run the kill command for that SPID
and the restore in the same
transaction, and it should go through.
Here is the sequence I used:
USE MASTER ALTER DATABASE DATABASENAME
SET SINGLE_USER WITH ROLLBACK
IMMEDIATE GO
-This will make it so only one connection to the database can be
made.
-Run the following command to see where any recurring connections to
database are coming from.
EXEC SP_WHO2
-Check this list, looking under the DBName column. If the database is
listed, check the ProgramName, and
HostName column to see who is
attempting to connect.
-If it is not a service, or other application that would automatically
reconnect which can be shut down, note
the number in the SPID column to kill
the connection, and immediately begin
the backup. Replace SPID below with
just the number.
KILL SPID RESTORE DATABASE
DATABASENAME FROM DISK =
'X:\PATHTO\BACKUP.BAK' GO
-If this completes successfully, we can set the newly restored database
back to multi user mode.
ALTER DATABASE DATABASENAME SET
MULTI_USER WITH ROLLBACK IMMEDIATE GO
only one connection to the database can be made. -Run the following command to see where any recurring connections to database are coming from.
EXEC SP_WHO2
Check this list, looking under the DBName column. If the database is listed, check the ProgramName, and HostName column to see who is attempting to connect.
If it is not a service, or other application that would automatically reconnect which can be shut down, note the number in the SPID column to kill the connection, and immediately begin the backup. Replace SPID below with just the number.
KILL SPID RESTORE DATABASE DATABASENAME FROM DISK = 'X:\PATHTO\BACKUP.BAK' GO
If this completes successfully, we can set the newly restored database back to multi user mode.
ALTER DATABASE DATABASENAME SET MULTI_USER WITH ROLLBACK IMMEDIATE GO