Executing SQL scripts with GO statements without SMO - c#

One thing I’m having problems with, is deploying app to machine not having SMO installed on it. I want to execute scripts having GOstatements, but also would like to avoid the need for installing SMO package on a target machine or parsing SQL script file (since I don't know if sql script will contain functions or SPs).
I tried manually copying SMO relevenat dlls to bin folder of executable but there are always some other dlls needed to run the app.
Any help with this?

Alternatively to SMO, the sqlcmd utility can understand GO statements. You will need to use System.Diagnostics.Process in order to call out to it with your script as an argument.
By no means am I saying this is the way to do it, but it is a valid alternative. You still have the same issues as before if the utility doesn't exist on the target machine.
You might also be able to deploy SMO with the installer package without "installing" it on the target machine:
Embedding SMO dlls in Setup and deployment

I find below solution well tested
using (SqlConnection cn = new SqlConnection(connectionString))
{
try
{
cn.Open();
FileInfo file = new FileInfo(fileName);
string script = file.OpenText().ReadToEnd();
string[] splitChar = { "\r\nGO\r\n" };
var sqlLines = script.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);
int res = 0;
SqlCommand cmd = null;
foreach (var query in sqlLines)
{
cmd = new SqlCommand(query, cn)
{
CommandTimeout = 5400
};
res = cmd.ExecuteNonQuery();
}
cn.Close();
}
catch (Exception ex)
{
msg = ex.Message;
}
finally
{
cn.Close();
}
}

Related

Unable to Load DLL 'sqlite.interop.dll' After Create Setup File

I am working on a windows application using Visual studio 2015(Professional) and Sqlite DataBase, windows 8.1(x64). i Install Sqlite From Nuget it Autometically install These References... system.componentmodel.dataannotations, System.Data.SQLite, System.Data.SQLite.EF6, System.Data.SQLite.Linq .
when i execute my app in visual Studio, Everything is working Fine. then Publish it by Windows Setup. then Install The Newly Created Setup File on My machine windows 8.1(x64). Whenever i try to Run it and Click on Login Button it gives the following error
"unable to load dll 'sqlite.interop.dll': the specified module could not be found. (exception from hresult: 0x8007007e)".
my Code is...
string connectionString = #"Data Source = SampelTest.db; Version = 3; new = false; compress = true; ";
private void buttonLogin_Click(object sender, EventArgs e)
{
using (SQLiteConnection con = new SQLiteConnection(connectionString))
{
try
{
using (SQLiteCommand sqlcmd = new SQLiteCommand("select count(*) from [SampelTest]", con))
{
con.Open();
Int32 count = Convert.ToInt32(sqlcmd.ExecuteScalar());
con.Close();
if (count > 0)
{
MessageBox.Show("User have in DataBase");
}
else
{
MessageBox.Show("Empty DataBase");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
}
My Database file in the Debug Folder "SampelTest.db"i already tried these step that are from Google to resolve my problem.
Coppy Sqlite.Interop.dll File From x64 To Debug Folder.
create x86 and x64 folder from solution Explorar and add Sqlite.Interop.dll from x86 and x64 respectively and Set Property, Build Option => Content, Copy to output Directory => Copy always.
Unchake the Prefer 32-bit.
After Try these steps can't able to solve this problem. Please Help to me to solve this. Thanks For Looking.

Error while doing writing unit test case -Could not load file or assembly 'Oracle.DataAccess, Version=4.112.4.0

We have a requirement to do unit testing using either MS Test or NUnit Framework for our C# code. There are many methods which includes DB call. When trying to do so, I am getting below error:
*{"Could not load file or assembly 'Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=*******' or one of its dependencies. An attempt was made to load a program with an incorrect format."}*
I checked the Oracle version to make sure there is no mismatch, but no success. Also read couple of articles that instead of making DB call one should be using mocking to bypass DB. But with this limitation the coverage is very minimal.
Could anyone please guide to fix the above error. Adding the sample code which i tried just for POC
public class Class1
{
public IEnumerable<ModelClass> GetListOfExceptions()
{
OracleConnection conn = new OracleConnection(Constants.ConnectionString);
try
{
conn.Open();
OracleCommand cmd = new OracleCommand(Constants.<Oracle Query>, conn);
cmd.CommandType = CommandType.Text;
//cmd.CommandType = CommandType.StoredProcedure;
OracleDataReader dr = cmd.ExecuteReader();
ModelClass modelException = null;
List<ModelClass> lst = new List<ModelClass>();
while (dr.Read())
{
modelException = new ModelClass();
modelException.POLICYNO = Convert.ToString(dr.GetValue(1));
modelException.PREMIUM = Convert.ToInt32(dr.GetValue(2));
modelException.AGE = Convert.ToInt32(dr.GetValue(3));
lst.Add(princeException);
}
return lst;
}
catch (Exception)
{
throw;
}
finally
{
conn.Close();
}
}
}
[TestFixture]
public class Class1Tests
{
[Test]
public void GetListOfExceptionsTest()
{
Class1 obj = new Class1();
obj.GetListOfExceptions();
}
}
Most likely the ODP.NET (i.e. Oracle.DataAccess) is not installed on your machine. Or maybe it is installed but you did not install any Oracle Client (e.g. Oracle Instant Client)
Go to this page Oracle Data Access Components - .NET Downloads and download and install the Oracle Data Provider for .NET. Ensure that you download the same version as your Oracle Client in case you installed already one. Ensure also that you have the same architecture, i.e. 32-bit vs. 64-bit as your application.
Finally the issue is fixed after installation to Oracle Client 12.1 (32 bit version).

Restore Database from bak file

I'm trying to restore a database from a bak file. I found some code on how to do it grammatically but I'm not sure what I'm doing wrong. I'm getting an error:
Error:
Restore failed for Server 'www.freegamedata.com'.
I assume because i'm remotely connected? I'm not sure. The bak file is not on the server machine. I'm trying to build a desktop application that will install my database on the users server using my file. Here is my code:
private void Restore_Database()
{
try
{
Server server = new Server(Properties.Settings.Default.SQL_Server);
string filename = "Test.bak";
string filepath = System.IO.Directory.GetCurrentDirectory() + "\\file\\" + filename;
Restore res = new Restore();
res.Database = Properties.Settings.Default.SQL_Database;
res.Action = RestoreActionType.Database;
res.Devices.AddDevice(filepath, DeviceType.File);
res.PercentCompleteNotification = 10;
res.ReplaceDatabase = true;
res.PercentComplete += new PercentCompleteEventHandler(res_PercentComplete);
res.SqlRestore(server);
}
catch(Exception ex)
{
}
}
I'm not sure if I'm going about this the correct way. I'd like to add my database with my data to the users server as a base database. Am I doing something wrong? My connection string is good so I know its not a connection issue.
I have found a workaround for those whom do not have local access. This is a bit involved so I hope I explain this correctly and it makes sense.
Also note you will need to export your data to an excel spreadsheet before you do the steps listed below.
Exporting Data
Part 1:
Backup Your DATA!
This is a pretty simple process. Open SQL Management Studio and right click on your database. Choose export data and export it as an excel spreadsheet 2007. I'm not going to give detailed steps on this part because its pretty basic and you can google it. Sorry for the inconvenience.
Part 2:
Delete your database for testing purposes but make sure you have a working backup before you delete your database.
Importing Data
Part 1:
You need to create a script that will build your database for you automatically. You can do this by logging into SQL management Studio and right click on the database and choose:
Task -> Generate scripts
you should only need the default information. However, if your like me, I excluded the users in the list. This will generate a large SQL script.
Part 2:
Next you will want to store this file in your solution/project. Make sure you right click it and choose always copy or or copy if newer. I think that's the options. Basically it just copies your file when you debug or build it. This is critical because you will need to access this file to execute the script. Next you need to make a SQL function similar to mine to execute the script:
public bool SQLScript_ExecuteSQLScript(string ScriptLocation)
{
try
{
//5 min timeout
SqlConnection SQLConn = new SqlConnection(cn + "; Connection Timeout = 300;");
string script = File.ReadAllText(ScriptLocation);
Server server = new Server(new ServerConnection(SQLConn));
server.ConnectionContext.ExecuteNonQuery(script);
return true;
}
catch (Exception ex)
{
return false;
}
}
In my code sample please note I changed my timeout to 5 minutes. In the event you have a large script you may need to adjust the timeout to make sure your script fully executes.
Congrats you have rebuilt your database.
Part 3:
Load SQL Management Studio and make sure your database has been rebuilt successfully. You should see all your tables and Stored Procs but no data. If this is true, great you can continue. If not please go back and review your script. If you have SQL comments in your script, you may need to remove them. I had to in order for my script to execute without errors.
Part 4:
Now you need to import your data from your excel spreadsheet you created earlier. If your like me, you had multipal sheets. If you have multipal sheets then you will want to make a list to loop through each item in your list to import the sheets. If not then you can ignore my code on the list. I also put mine in a background worker but you don't need to depending on the size of your data. Also note I created a separate class containing my list but you dont have to do that if you don't want too. My sheet names are Table_1, Table_2 and Table_3 your will be differently most likely.
Sample Sheet List:
public List<string> GetTestTableList()
{
try
{
List<string> testlist = new List<string>();
testlist.Add("Table_1");
testlist.Add("Table_2");
testlist.Add("Table_3");
return testlist;
}
catch (Exception ex)
{
return null;
}
}
Part 5:
Next we will import the data from excel into SQL. This is a function I made but you can modify this to meet your needs.
Function:
private bool Import_Data_Into_SQL(string filepath, string SheetName, string Database, string Schema)
{
try
{
// sql table should match your sheet name in excel
string sqltable = SheetName;
// select all data from sheet by name
string exceldataquery = "select * from [" + SheetName + "$]";
//create our connection strings - Excel 2007 - This may differ based on Excel spreadsheet used
string excelconnectionstring = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source='" + filepath + " '; Extended Properties=Excel 8.0;";
string sqlconnectionstring = Properties.Settings.Default.SQL_Connection;
//series of commands to bulk copy data from the excel file into our sql table
OleDbConnection oledbconn = new OleDbConnection(excelconnectionstring);
OleDbCommand oledbcmd = new OleDbCommand(exceldataquery, oledbconn);
oledbconn.Open();
OleDbDataReader dr = oledbcmd.ExecuteReader();
SqlBulkCopy bulkcopy = new SqlBulkCopy(sqlconnectionstring);
bulkcopy.DestinationTableName = Database + "." + Schema +"." + sqltable;
while (dr.Read())
{
bulkcopy.WriteToServer(dr);
}
dr.Close();
oledbconn.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
I hope this helps. This was my workaround solution. Originally I wanted/tried to import my data using the .bak file but as pointed out above you can only do that if the sql server is local. So I hope this work around helps those who where faced with a similar issue as me. I'm not marking this as the answer because the above post answers the question but I'm posting this in case someone else needs this workaround. Thanks
Restore file must be on server. For installation use SQL script. This can be generated by SQL Server Management Studio (including data).
Right click on database. Choose "Tasks" - "Generate scripts". On second page of wizard choose "Advanced" and find "Types of data to script". Select "Schema and data" and save script to file.
Then use this code to run script on database
string scriptText = File.ReadAllText(scriptFile, Encoding.Default);
ExecuteBatch executeBatch = new ExecuteBatch();
StringCollection commandTexts = executeBatch.GetStatements(scriptText);
using (SqlConnection sqlConnection = new SqlConnection(conn))
{
sqlConnection.InfoMessage += SqlConnection_InfoMessage;
sqlConnection.Open();
for (int i = 0; i < commandTexts.Count; i++)
{
try
{
log.InfoFormat("Executing statement {0}", i + 1);
string commandText = commandTexts[i];
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
log.Debug(commandText);
sqlCommand.CommandText = commandText;
sqlCommand.CommandTimeout = 300;
int r = sqlCommand.ExecuteNonQuery();
log.DebugFormat("{0} rows affected", r);
}
}
catch (Exception ex)
{
log.Warn("Executing command failed", ex);
try
{
sqlConnection.Open();
}
catch (Exception ex2)
{
log.Error("Cannot reopen connection", ex2);
}
}
}
sqlConnection.Close();
}

How to point to the relative path of database c# wpf localdb

I trying to make backup and restore as a start i am trying to get backup database so write a code like this
try
{
string cbdfilename = "c:\\Bbcon.bak";
SqlConnection con = new SqlConnection("Data Source=(LocalDB)\\v11.0;AttachDbFilename=|DataDirectory|\\BbCon.mdf;Integrated Security=True;Connect Timeout=30;");
string sql = "Backup database #DBNAME to Disk = #FILENAME with Format";
SqlConnection.ClearAllPools();
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("#DBNAME", "BbCon");
cmd.Parameters.AddWithValue("#FILENAME", cbdfilename);
con.Open();
try
{
cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
MessageBox.Show("Backup DB failed" + ex.ToString());
}
finally
{
con.Close();
con.Dispose();
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
}
but when i run this code i get an error database BbCon not exist check your database i don't know what is problem for sure but i think i have given wrong path to database I know the path od database correctly it is like
C:\Users\Mahdi Rashidi\AppData\Local\Apps\2.0\NOL11TLW.9XG\CZM702AQ.LPP\basu..tion_939730333fb6fcc8_0001.0002_fd707bbb3c97f8d3
but this project is for some other clients so when i install this software to other computer path will change so i will get an error so i am begging you all to help finding me a better solution for creating a backup programattically
I recommend you to create an app.config file and put the backup target path there
OR
What I did some time ago (to load assemblies dynamically, but this piece of code allows u to retrieve the path location based on the assembly that you're running) it was something like:
(Don't forget to add System.Reflection to your using list)
// get the current assembly from cache
var currentAssembly = Assembly.GetEntryAssembly();
// if current assembly is null
if (currentAssembly == null)
{
// get the current assembly from stack trace
currentAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
}
// get the assemblies path (from returned assembly)
assembliesPath = Path.GetDirectoryName(currentAssembly.Location);
From that point now you can concatenate you "Data Path" and save your data there.
Hope it helps.

Filepath changing while executing sql query from c#

I have a sql database where i am string filepath and file name of some files. I am using Visual Studio 2008 as IDE and SQL Server 2005 for development.
If I am trying to execute a SQL query to get filepath it returns correct result. But when I am executing SQL query from windows application in c#, it is returning Filepath in which all \ are changed to //.
Here is the SQL query I executed from SQL Server Management Studio:
select FilePath FROM dbo.[tbl_name] WHERE SerialNo = 2;
It results in FilePath being C:\Program Files\Test\Mydoc.pdf
But when I am trying through C# windows forms code as mentioned below. I am getting a wrong value for FilePath: C://Program Files//Test//Mydoc.pdf
try
{
using (connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("SELECT FilePath FROM dbo.[tbl_name] WHERE SerialNo LIKE #Sno", connection))
{
command.Parameters.Add(new SqlParameter("Sno", Serial));
FiletoOpen = command.ExecuteScalar().ToString();
Process.Start(FiletoOpen );
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Exception has occured!", MessageBoxButtons.OK);
}
finally
{
connection.Close ();
}
What may be the problem?
I guess you are seeing this path in your debugger. Debugger is just escaping the path and nothing else. If you write it somewhere, like console, you will get the original path (with single backslashes).

Categories