How to save DataSet after adding data? - c#

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();
}

Related

Compare tables between two MDF files

I am attempting to synchronizing tables in two different .MDF files. After successfully creating a datatable for the first file I get an error when trying to create the second:
Cannot attach file 'E:\JVT-Inventory.mdf' as database 'JVT-Inventory' because this database name is already attached with file 'C:\Database\JVT-Inventory.mdf'
I have created separate procedures for each connection to create the tables then disposed the connection. Both the datatable and adapter are global variables to be used in my routines to compare the tables. None of the online research seems to apply to what I am trying to accomplish.
string conString;
conString = "Data Source=(LocalDB)\\v11.0;attachdbfilename=" + #txtPath.Text + ";Initial Catalog=JVT-Inventory;integrated security=True";
using (SqlConnection connection = new SqlConnection(conString))
{
daRemote = new SqlDataAdapter("SELECT * FROM tblProduct ORDER BY keyPartNo", connection);
SqlCommandBuilder cbRemote = new SqlCommandBuilder(daRemote);
daRemote.Fill(dtRemote);
connection.Dispose();
This connection is made to a file on a flash drive.
The issue appears to be that the MDF file remains open until I exit the application. My question now is, how do I close the MDF file from within my application?
After searching many articles about working with databases I figured out the follow:
SqlConnection cnRemoteBye = new SqlConnection();
SqlCommand cmdRemoteBye = new SqlCommand();
cnRemoteBye.ConnectionString = #"Data Source=(LocalDB)\v11.0;Integrated Security=True";
cmdRemoteBye.CommandText = "ALTER DATABASE [JVT-Inventory] SET OFFLINE WITH ROLLBACK IMMEDIATE \n\r exec sp_detach_db #dbname = [JVT-Inventory]";
cmdRemoteBye.Connection = cnRemoteBye;
cnRemoteBye.Open();
cmdRemoteBye.ExecuteNonQuery();
cnRemoteBye.Close();

Backup localDB database in ClickOnce

I've created a WPF 4.5 .NET application it with a database backup feature. The functions and the backup works fine when debugging but when I publish it in ClickOnce and install it in target machine everything works except the backup won't work because ClickOnce obfuscate the app folder location so it becomes too long for the backup statement to work! Is there a way to make the backup statement shorter? here's my code and the error I get:
code:
SaveFileDialog sfd = new SaveFileDialog();
string stringCon = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\whdb.mdf;Integrated Security=True";
string dbPath = Application.StartupPath + #"\whdb.mdf";
if (sfd.ShowDialog() == DialogResult.OK)
{
using (SqlConnection conn = new SqlConnection(stringCon))
{
string backupStmt = string.Format(#"backup database #whdb to disk='{0}' WITH INIT ", sfd.FileName);
using (SqlCommand sqlComm = new SqlCommand(backupStmt, conn))
{
sqlComm.Parameters.AddWithValue("#whdb", dbPath);
conn.Open();
sqlComm.ExecuteNonQuery();
conn.Close();
}
}
)
************** Exception Text **************
System.Data.SqlClient.SqlException (0x80131904): Invalid database name 'C:\Users\Abubaker\AppData\Local\Apps\2.0\52WR4JTO.12O\D6M4D7OQ.Z3D\sa3a..tion_fef19ab42c2b8f22_0001.0000_9fc10c82bbf23ed2\whdb.mdf' specified for backup or restore operation.
BACKUP DATABASE is terminating abnormally.
The whdb.mdf database file is create by another existing application? And your WPF application is only for Backup the existing whdb.mdf database?
I also struggled for days for this kind of situation. I tried |Data Directory| and Application.StartupPath and some other approaches as you've found as well.
However, I finally chose this way and successfully launched(published) my service.
According to my experience, |Data Directory| indicates different places depending on circumstances, in other word, it's not always same..
And I could read (SQL Select command) database with |Data Directory| setting in connectionString but couldn't insert or update the database. You can find some people are having this difficulties by searching on interent. I think when we set |Data Directory| in connectionString, the database plays a role as read-only data file like the nuance of |Data Directory|.
Instead the |Data Directory|, I chose more obvious path which indicates always same place(directory).
#"Data Source=(LocalDB)\v11.0;AttachDbFilename=" + Environment.GetEnvironmentVariable("APPDATA") + #"\whdb.mdf;Integrated Security=True";
Above Environmental variable indicates always C:\Users\Abubaker\AppData\Roaming directory.
For this scenario, you're needed to create the whdb.mdf database file with above path first.
And further, you may create your own additional directory like mybackup with the connectionString as,
#"Data Source=(LocalDB)\v11.0;AttachDbFilename=" + Environment.GetEnvironmentVariable("APPDATA") + #"\mybackup" + #"\whdb.mdf;Integrated Security=True";
I couldn't find the official document from Microsoft how the |Data Directory| works but failed. Understanding |Data Directory| would be your key, otherwise, there's alternative way like my case.
My case is also WPF, ClickOnce, SQL Database (it was localDB but I changed to normal SQL Database because of remote networking)
Solved the problem by adding Initial catalog=whdb in the connection string and then replace the full path Application.StartupPath + #"\whdb.mdf" with just the database name "whdb"!

Dynamic Datasource Path C#

I created an app where a combobox is bound with an Access Database. The application was working fine on my computer because the source path in the connectionstring I defined was related to my computer. I copied the project folder to another computer which gives error of not finding the database at the specified location.
Can I dynamically set the path from a textbox or some other input? Can I call a database from the application where the source path doesn't matter. Even when I refer to Resources.Database1 it still gives full path to application folder for my computer which doesn't work on another computer. Any idea would be appreciated. Thanks!
My code is the following:
private void button1_Click(object sender, EventArgs e)
{
OleDbCommand command = new OleDbCommand();
command.CommandType = CommandType.Text;
command.CommandText = "INSERT INTO SubrubDatabaseT(SuburbName,DeliveryTime) values('" + textBox1.Text + "','" + textBox2.Text + "')";
OleDbConnection connect = new OleDbConnection();
connect.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\WoolsValley\Desktop\Database1.accdb ;
Persist Security Info = False; ";
connect.Open();
command.Connection = connect;
command.ExecuteNonQuery();
MessageBox.Show("Data Saved Successfully");
connect.Close();
}
For your case, the solution is to use an App.config (or Web.config depending on the type of the project you are developing) file and put all the settings there. Then if the path doesn't exist, you can still change it to an existing one in this file, and it will not be necessary to recompile the application.
This is the main use of these lind of files, to add there any settings that could change on the users machines or when the application is published and it may need little adjustments, as in this case, and it may not be needed to recompile for every computer the application runs.
As you mentioned yourself, you can simply have a text box for the file path or maybe an OpenFileDialog component to select the file. You then pass that in the connection string:
//GetFileSource() a method that gets the source from somewhere, like a textbox or a configuration entry in app.config.
var fileSource = GetFileSource();
connect.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileSource + ";Persist Security Info = False;";
What's equally important is that you make sure the file actually exists at the destination.
You could create a method that searches the users folder for data files or let the user specify a data file on startup and save that to the users profile directory. There are many ways to do this and which way you choose depends on factors like how is the data file copied to the users PC, are there many data files possible, etc.
If the data file only exists with the app, there is only one data file possible, and the data file is copied/created at deployment time (ie. when you run the MSI) then put it in the app.config instead as a connection element. See Connection Strings and Configuration Files.
First thing is to always use parameterized queries. See https://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters(v=vs.110).aspx
Remarks
The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used.
Your code refactored with using statements and parameterized inputs.
// get file from the drop down
var filePath = getSelectedDataFile();
using (OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath))
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO SubrubDatabaseT(SuburbName,DeliveryTime) values(?,?)";
cmd.Parameters.Add(new OleDbParameter("#suburbName", OleDbType.VarChar)).Value = textBox1.Text;
cmd.Parameters.Add(new OleDbParameter("#deliveryTime", OleDbType.VarChar)).Value = textBox2.Text;
con.Open();
cmd.ExecuteNonQuery();
}
Note that:
OleConnection and OleDbCommand are wrapped in using blocks so they are disposed/cleaned up even when an exception occurs.
Parameters are now used instead of hard coding the string values
Parameters use the correct data types

C# mdf database doesn't update on program startup

I create simple example to create question easyer.
So in my c# project I create an mdf database with articles. Then I connect database in my program and read values from table articles. It gives me results, but not the latest.
If I have one result it showes me this one. Then I go in articles table to add one new article and run program again and in this case program showes me only the first one. But if I "Build solution" it finds all of them.
What I have to do? I wish, that program will have the latest result on startup.
SqlConnection cn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True");
try
{
cn.Open();
string sqlQuery = "SELECT * FROM Articles";
SqlCommand sqlCommand = new SqlCommand(sqlQuery, cn);
SqlDataReader sqlDataRead = sqlCommand.ExecuteReader();
while (sqlDataRead.Read())
{
MessageBox.Show(Convert.ToString(sqlDataRead["ArticleLabel"]));
}
sqlDataRead.Close();
sqlDataRead.Dispose();
sqlCommand.Cancel();
cn.Close();
}
catch (Exception) { MessageBox.Show("Database error!"); Application.Exit(); }
If your MDF file has the property Copy To Output Directory set to Copy Always, then every time you build your application a fresh copy of the database file is copied from the project directory to the output Directory (BIN\DEBUG or BIN\RELEASE).
Of course this destroy any changes you have made in a previous run of your program
Change the property to Copy if Newer
Also, don't be fooled by what you see in the Server Manager Windows. The connections there could not point to the database in the Output directory but on the database in the Project Directory where you don't write anything.

Getting data from a table to ASP.NET web application

I'm using Visual Studio 2010 to build an ASP.NET web application, I'm working on dynamically populating (part) of the site map from information in a database. Right now I just have a dummy table in my App_Data folder, called DrugTest.mdf. The table is just called DrugTest1, which only has one field, DrugName. Where I'm hitting a wall is actually getting the data out of that table. Part of what I'm confused about is the connection string. I've looked at a lot of different information about connection strings, most notably http://www.connectionstrings.com/ but I'm a little confused as to how to actually apply said information to this project.
EDIT: I'm using SQL Server 2008 RC.
For example: Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;
Password and User Id are pretty self-explanatory, but as far as I know I didn't get either one of those, I just added a table to the App_Data folder and filled it with dummy data. ServerAddress is a little confusing, because this information isn't really stored on a server, it's just stored locally. And I'm honestly not sure what Initial Catalog means.
Here's the code to populate the sub-tree. You'll notice the connection string is left blank.
string connString = ""; // get the connection string
string commandString = "SELECT drugName FROM DrugTable1";
SqlConnection connection = new SqlConnection(connString); // connect to db
SqlCommand command = new SqlCommand(commandString, connection); // set up the command
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet drugs = new DataSet();
adapter.Fill(drugs);
foreach (DataRow row in drugs.Tables[0].Rows)
{
string drugName = row["Name"] + "";
SiteMapNode node = new SiteMapNode(this, drugName,
"~/PlaceHolderUrl?path=" + drugName,
drugName);
AddNode(node, root);
}
Furthermore, I've got a nagging suspicion that I'm not going about this the right way. I think this will be the proper implementation once the database is up and running, but for right now I just want to get it working so it's ready to go - just slap in the proper connection string and table/field names.
So, finally, my question(s): How would I go about connecting to this local table? What format should my connection string be? I noticed there's a lot of them. Is there a better way to do this/am I doing this wrong?
Another way of getting the right connection string check this out in the ServerExplorer window
On the Menu click on View->Server Explorer
In the Server Explorer window locate DrugTest.mdf
Right click the file and select Properties
You can see the right connection string in the properties
Copy the connection string and use
Note: that the file location was hard-coded. You might need to use |DataDirectory| later
Try replacing the Initial Catalog portion of your connection string with AttachDbFilename=|DataDirectory|DrugTest.mdf.
Also, if you're using SQL Server Express, you might need to include the instance in the Data Source, so might try Data Source=mySeverAddress\SQLExpress, where SQLExpress is the instance name.
BTW, at the http://www.connectionstrings.com site, you can find this information in the SQL Server 2008 page if you scroll down a bit to the section titled "Attach a database file, located in the data directory, on connect to a local SQL Server Express instance."

Categories

Resources