Compare tables between two MDF files - c#

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

Related

Connecting to local database

I am trying to create to a local database via a mdf file, like so:
scon = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDBFilename=|DataDirectory|\articles.mdf; Integrated Security=True");
scon.Open();
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)");
scmd.Parameters.AddWithValue("#url", "http://google.com");
scmd.ExecuteNonQuery();
MY mdf file is in the root folder, and in the debug folder too. When I run the following code I get an error saying the following:
I can't use the full connection path because it's a long url with spaces, here is my file structure:
My database exists:
How can I fix this so I can connect to my database?
Pass the connection object to the SqlCommand constructor
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)", scon);
The connectionstring is fine, the error message informs you that it is not possible to execute a command if the database is not known. The SqlConnection contains this information and you need to pass it to your command.
Another possibility is through the
scmd.Connection = scon;
but, personally, I prefer to pass that info in the constructor.
Final but really important note:
SqlConnection and SqlCommand are disposable objects. You should always dispose these kind of objects. The using statement is the correct method
using(scon = new SqlConnection(....))
using(scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)",scon))
{
scon.Open();
scmd.Parameters.AddWithValue("#url", "http://google.com");
scmd.ExecuteNonQuery();
}
The Problem With Your Code Is That You Have A Command and a Connection But There Is Nothing To Till The Command To Use This Connection Object ... You Can Use The SqlCommand Constructor To Do That
scmd = new SqlCommand("Insert INTO articles(url) VALUES(#url)",scon)
Or Use The Connection Property Of The SqlCommand Class Like This
scmd.Connection = scon
Consider Adding Using To Your SQL Connection ... Or Else You Will Have To Manually Close The Connection By Calling scon.Close();
if You Didn't Do either Of Those You Will Run Into An Exception If Your Tried To Open The Connection Again While It's Already Open

How to save DataSet after adding data?

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

Making a copy of an azure database

I need to make a copy of an azure database but I don't have access to any management tools, only a connection string.
I know that to use the CREATE DATABASE x AS COPY OF y command I need to be in the master database but I don't know how to tell Azure to run my command from there. For example, I have this code:
var commandText = "CREATE DATABASE foobar AS COPY OF " + database;
var connectionString = <my_connection_string>;
using (var conn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(commandText, conn))
{
cmd.CommandType = CommandType.Text;
conn.Open();
cmd.ExecuteNonQuery();
}
}
which fails with error "User must be in the master database" - as I expected.
However my connection string is not valid for the master database, so how do I execute this command from the master database? If I was in SQL Management Studio I would just do:
use master
CREATE DATABASE x AS COPY OF y
Is there any way of emulating that in my code?
Change your connection string to access the master database instead of your regular one. It's as simple as that and the only solution.

Creating a custom installer for occasionally connected application using database of another software

I am trying to create an application which will synchronize its database with another software's database..
Problems are:
How will the database will synchronize with external database after I have created the installer and installed..i.e. how will it take the connection string.
I am looking for a solution which will provide a button to select the required database and based on the selection automatically generate the connection string.
Is it possible to run SQL create queries on external database while installation after the database is selected via browse button?
You have an option to create a Connection Settings form, which will help user to construct the connection string.
Yes, it's possible. It looks something like this:
using (var sqlConnection = new SqlConnection(#"Data Source=myServerAddress;User Id=myUsername;Password=myPassword;"))
{
sqlConnection.Open();
string query = "CREATE DATABASE...";
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = query;
sqlCommand.ExecuteNonQuery();
}
}
If it won't work, try to set Initial Catalog to master:
#"Data Source=myServerAddress;Initial Catalog=master;User Id=myUsername;Password=myPassword;"

How to execute a query which uses multiple database

I am developing an ASP.Net website. I have to execute a query which fetches data from two different database.
I have two SqlConnection objects for these connections.
I have both the connections open. But in SqlCommand object, I can specify just one SqlConnection object.
SqlConnection conn = new SqlConnection("Data Source=xxx;Initial Catalog=xxx1;User ID=web_writeonly;Password=aaa;Network Library=DBMSSOCN");
SqlConnection conn1 = new SqlConnection("Data Source=xxx;Initial Catalog=xxx2;User ID=randomUser;Password=bbb;Network Library=DBMSSOCN");
conn.open();
conn1.open();
SqlCommand cmdUserInfo = new SqlCommand("<query goes here>", conn);
cmdUserInfo.Parameters.Add("#ifa", SqlDbType.NVarChar).Value = ifacode;
SqlDataAdapter sdaUserInfo = new SqlDataAdapter(cmdUserInfo);
sdaUserInfo.Fill(dtSummaryTbl);
conn.Close();
conn1.Close();
When I execute this code snippet, I get an error "The SELECT permission was denied on the object '*', database 'xxx2', schema 'dbo'."
Please help me out in sorting this problem.
Thanks!
That error means that you don't have sufficient permissions... check what sql login your website is associated with and then the permissions on the table you're trying to select data from.
Also, on closer inspection, one of your usernames is "web_writeonly"... kind of a hint if you're trying to do a select!!! ;)
Assuming your databases are on the same server why can't you just put your SQL into a stored procedure on one of the databases. I am pretty sure you can then just use one connection object and execute your stored procedure which gets data from two databases.

Categories

Resources