Read a large SQL script file in c# - c#

I am trying to read a large script, thus far I have tried two options:
Option 1:
We can't open large script files in SQL management studio because of the issue of out of memory space, so Initially I used sqlcmd to execute 160 mb SQL script file on remote host, after 55 minutes some rows were effected with this error, TCP Provider: An existing connection was forcibly closed by the remote host. , communication link failure.
Option 2:
Now I am trying using this example, the file size is 160 MB with lot of insert statements, but Visual Studio crashes
Code:
public ActionResult Index()
{
string scriptDirectory = "e:\\";
string sqlConnectionString = "Integrated Security=SSPI;" +
"Persist Security Info=True;Initial Catalog=TestDB;Data Source=localhost\\SQLEXPRESS";
DirectoryInfo di = new DirectoryInfo(scriptDirectory);
FileInfo[] rgFiles = di.GetFiles("*.sql");
foreach (FileInfo fi in rgFiles)
{
FileInfo fileInfo = new FileInfo(fi.FullName);
string script = fileInfo.OpenText().ReadToEnd(); // here visual studio crashes
SqlConnection connection = new SqlConnection(sqlConnectionString);
Server server = new Server(new ServerConnection(connection));
server.ConnectionContext.ExecuteNonQuery(script);
}
return View();
}
Screen Shot:

I would suggest executing the insert statements line by line optionally wrapped in a transaction:
public ActionResult Index()
{
string scriptDirectory = "e:\\";
string sqlConnectionString = "Integrated Security=SSPI;" +
"Persist Security Info=True;Initial Catalog=TestDB;Data Source=localhost\\SQLEXPRESS";
using(var connection = new SqlConnection(sqlConnectionString))
{
var transaction = connection.BeginTransaction();
using(var command = connection.CreateCommand())
{
ProcessFiles(command, scriptDirectory);
}
transaction.Commit();
}
return View();
}
private void ProcessFiles(SqlCommand command, string scriptDirectory)
{
foreach(var file in Directory.GetFiles(scriptDirectory,"*.sql"))
{
using(var reader = new StreamReader(file))
{
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
if(!line.StartsWith("GO"))
{
command.CommandText = line;
command.ExecuteNonQuery();
}
}
}
}
}
Keep in mind that this will put some pressure on the log file of the database.

Related

Run a sql script in c# (.asp net)

I just want the directory to open to "project_name\Scripts(sub_folder)\merge.sql"
I can't get rid of 'C:' and I cant get the actually data file to appear.
I received an"System.io.directorynotfoundexcpetion".
Here's my code:
private void MergeQuery()
{
//might need to change C: drive directory
//string derefQuery = #"\.\mergeSQL.sql";
using (SqlConnection mer = new SqlConnection(#"Data Source = address_name; Initial Catalog = catalog_name; Integrated Security=SSPI"))
{
{
mer.Open();
string path = Path.GetDirectoryName("\\project_name\\Scripts\\mergeSQL.sql ");
string mergeScript = System.IO.File.ReadAllText(path);
System.Collections.Generic.IEnumerable<string> commandStrings = Regex.Split(mergeScript, #"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
foreach (string commandString in commandStrings)
{
if (commandString.Trim() != "")
{
using (var command = new SqlCommand(commandString, mer))
{
command.ExecuteNonQuery();
}
Label2.Text = "Query merged";
}
}
}
}
first, there is an error in line
string path = Path.GetDirectoryName("\\project_name\\Scripts\\mergeSQL.sql ");
In that line you're getting directory path from file path, so path variable becomes \\project_name\\Scripts\\ or something similar. On next line you're trying to read file from that path variable, not from file.
What you need is to get path relative to web site root and then read file, like this
string path = HostingEnvironment.MapPath("~/Scripts/mergeSQL.sql ");
string mergeScript = System.IO.File.ReadAllText(path);
this way asp.net will get correct path from your website root's subfolder.

Running a command although the connection is close adomd

I have read the Mirosoft Document.When we open a connection and then close it, it is possible to use the session.
I have written this block of code to run a command but I get an error message, which says there is no connection. Do you have any Idee how can I close the connection, but use the session to run a cammand:
try
{
using (AdomdConnection adomdConnection = new AdomdConnection("MY Connection String"))
{
adomdConnection.Open();
adomdConnection.Close(false);
while (true)
{
String query = #"EVALUATE { BLANK()}";
AdomdCommand adomdCommand = new AdomdCommand(query);
Console.WriteLine(adomdConnection.SessionID.ToString() + " " + DateTime.Now.ToString());
AdomdDataReader reader = adomdCommand.ExecuteReader();
reader.Close();
System.Threading.Thread.Sleep(30000);
}
}
}
catch(AdomdConnectionException ex)
{
Console.WriteLine(ex.Message.ToString());
}
In the examples shown in the document you list, it has:
/*First, try to connect to the specified data source.
If the connection string is not valid, or if the specified
provider does not support sessions, an exception is thrown. */
objConnection.ConnectionString = connectionString;
objConnection.Open();
// Now that the connection is open, retrieve the new
// active session ID.
strSessionID = objConnection.SessionID;
// Close the connection, but leave the session open.
objConnection.Close(false);
return strSessionID;
And in your code specifically, you have:
adomdConnection.Open();
adomdConnection.Close(false);
while (true)
{
String query = #"EVALUATE { BLANK()}";
AdomdCommand adomdCommand = new AdomdCommand(query);
Console.WriteLine(adomdConnection.SessionID.ToString() + " " +
DateTime.Now.ToString());
AdomdDataReader reader = adomdCommand.ExecuteReader();
reader.Close();
System.Threading.Thread.Sleep(30000);
}
Wouldn't you want to have this instead (based on the example given)?
adomdConnection.Open();
while (true)
{
String query = #"EVALUATE { BLANK()}";
AdomdCommand adomdCommand = new AdomdCommand(query);
Console.WriteLine(adomdConnection.SessionID.ToString() + " " +
DateTime.Now.ToString());
AdomdDataReader reader = adomdCommand.ExecuteReader();
reader.Close();
System.Threading.Thread.Sleep(30000);
}
adomdConnection.Close(false);
It seems as though it's complaining because you're closing the connection before you even use it, according to the order in which your code looks to be operating. Try moving the adomdConnection.Close(false); after your while loop.

Using MySqlBulkLoader to upload a DataSet content : Issue with the filename

I'd like to try the performance of MySqlBulkLoader knowing that the Adapter.update() method i'm using is taking roughly 30 mn to run.
I understand you have to go through a file to do it so here is my code :
private void button14_Click(object sender, EventArgs e)
{
string fileName = #"C:\Users\Utilisateur\ds.txt";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
using (StreamWriter sw = File.CreateText(fileName))
{
foreach (DataRow row in Globals.ds.Tables[0].Rows)
{
foreach (object item in row.ItemArray)
{
string itemstr = item.ToString();
sw.Write((string)itemstr + "\t");
}
sw.WriteLine();
}
}
using (var conn = new MySqlConnection(Globals.connString))
{
conn.Open();
MySqlCommand comm = new MySqlCommand("TRUNCATE Song",conn);
comm.ExecuteNonQuery();
var bl = new MySqlBulkLoader(conn)
{
TableName = Globals.ds.Tables[0].ToString(),
Timeout = 600,
FieldTerminator = "\t",
LineTerminator = "\n",
FileName = fileName
};
var numberOfInsertedRows = bl.Load();
Console.WriteLine(numberOfInsertedRows);
}
}
The file is generated ok. but at the var numberOfInsertedRows = bl.Load(); line, i have the following error at run time :
MySql.Data.MySqlClient.MySqlException: 'Can't get stat of '/var/packages/MariaDB10/target/mysql/disk/C:\Users\Utilisateur\ds.txt' (Errcode: 2 "No such file or directory")'
I tried to put "/" instead of "\" in the fileName but it's the same error.
I have no idea what's going on, anyone can help ?
Thanks
By default, MySqlBulkLoader loads a file from the server's file system. To use a local file, set bl.Local = true; before calling bl.Load().
To enable this, you will need to set AllowLoadLocalInfile = True in your connection string; see https://mysqlconnector.net/troubleshooting/load-data-local-infile/
Finally, if you switch to MySqlConnector, you can use its MySqlBulkCopy API to load data directly from a DataTable, instead of first saving it to a local CSV file, then loading that file.

Relative path not working while accessing a sqlite Database through C#

I am creating a Excel Addin through which i want to access a database. code is as follows
[ExcelFunction("My First Excel-DNA Function")]
public static string GreetFunction(string name)
{
GetConnection();
return "Hello" + " " + name;
}
public static void GetConnection()
{
//db = new SQLiteConnection("Data Source="+System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)+"\\Database\\XLSQLiteDemo.sqlite");
db = new SQLiteConnection("Data Source=Database/XLSQLiteDemo.sqlite");
try
{
db.Open();
cmd = db.CreateCommand();
System.Windows.MessageBox.Show("Connection created");
}
catch (SQLiteException ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
}
so when i give absolute path like c:/test/firstlibrary.../XLSQLiteDemo.sqlite it works.
but when i use relative path like db = new SQLiteConnection("Data Source=Database/XLSQLiteDemo.sqlite");
it throws an exception: unable to open database file error code 14.
the code which is in comment i.e.
//db = new SQLiteConnection("Data Source="+System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)+"\\Database\\XLSQLiteDemo.sqlite");
also doesn't work i.e. it calculates the absolute path but when i tried to debug; debugging is automatically terminated after db.Open();
and output in excel sheet is also #Value which indicates some error.
#adrino may be the "file" word in your string is the problem.remove it.
string relativePath = #"Database\XLSQLiteDemo.sqlite";
string currentPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
string absolutePath = System.IO.Path.Combine(currentPath, relativePath);
absolutePath=absolutePath.Remove(0, 6);//this code is written to remove file word from absolute path
string connectionString = string.Format("Data Source={0}", absolutePath);
this works on my machine.tell me if its correct.

Backup a database mdf & Entity Framework

I have a database (mdf file) which I'm approaching with the Entity Framework. Is it possible to make a backup of the MDF file.
I tried already but SMO but the problem is because I'm using a mdf file the database name is empty. I've read that it's autogenerated.
Piece of my backup code:
String destinationPath = "C:\\";
Backup sqlBackup = new Backup();
sqlBackup.Action = BackupActionType.Database;
sqlBackup.BackupSetDescription = "ArchiveDataBase:" + DateTime.Now.ToShortDateString();
sqlBackup.BackupSetName = "Archive";
BackupDeviceItem deviceItem = new BackupDeviceItem(destinationPath, DeviceType.File);
ServerConnection connection = new ServerConnection(".\\SQLEXPRESS");
Server sqlServer = new Server(connection);
StringCollection sc = new StringCollection();
sc.Add(Environment.CurrentDirectory + "\\db\\Xmain.mdf"); //Bin directory
sc.Add(Environment.CurrentDirectory + "\\db\\Xmain_log.ldf");
sqlServer.AttachDatabase("Xmain", sc);
Database db = sqlServer.Databases["Xmain"];
sqlBackup.Initialize = true;
sqlBackup.Checksum = true;
sqlBackup.ContinueAfterError = true;
sqlBackup.Devices.Add(deviceItem);
sqlBackup.Incremental = false;
sqlBackup.ExpirationDate = DateTime.Now.AddDays(3);
sqlBackup.LogTruncation = BackupTruncateLogType.Truncate;
sqlBackup.FormatMedia = false;
sqlBackup.SqlBackup(sqlServer);
I am missing something here and need more context, but I will rant on for a second and see if anything is helpful.
Do you mean actually back up the file, not the data? If so, the easy answer is no. The problem is SQL Server will lock the file when it is attached to the database server (SQL Express in this case). You can detatch and copy and then attach, but the application will be down during that time. This can also be done manually.
If you want to backup the data, I would consider scheduling it within SQL Server rather than programmatic, unless you cannot do it that way. Backup is more of a maintenance function than a part of the program.
As for your database name being empty, that is impossible. In fact, it looks like you are trying to set up a database called XMain.
You must set initial catalog in connection string in app.config:
<add name="SalaryAndBenefitsEntities" connectionString="metadata=res://*/SalaryAndBenefitsModel.csdl|res://*/SalaryAndBenefitsModel.ssdl|res://*/SalaryAndBenefitsModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;attachdbfilename=|DataDirectory|SalaryAndBenefits.mdf;Initial Catalog=SalaryAndBenefit;user instance=true;password=ca;integrated security=SSPI;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
For backUp Follow below:
create sql command content
public string BackUpCommand(string databaseName, string fileAddress)
{
string command = #"BACKUP DATABASE " + databaseName + #"
TO DISK = '" + fileAddress + "' WITH FORMAT";
return command;
}
Write Backup Method:
public class ActionResult
{
public bool Result { get; set; }
public string Message { get; set; }
}
public ActionResult BackUpDatabase(string filePath)
{
ActionResult res = new ActionResult { Result = true };
using (SalaryAndBenefitsEntities _context = new SalaryAndBenefitsEntities())
{
string command = "select db_name()";
string databaseName = _context.Database.SqlQuery(typeof(string), command).ToListAsync().Result.FirstOrDefault().ToString();
string backUpQuery = BackUpCommand(databaseName, filePath);
var result = _context.Database.SqlQuery<List<string>>(backUpQuery).ToList();
if (result.Count() > 0)
{
res.Result = false;
result.ForEach(x =>
{
res.Message += x.ToString();
});
}
return res;
}
}
if return true database backup is successful else not
For restore Follow below:
create sql command content
public string RestoreCommand(string databaseName, string fileAddress)
{
string command = #"use [master]
ALTER DATABASE " + databaseName + #"
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
RESTORE DATABASE " + databaseName + #"
FROM DISK = N'" + fileAddress + "'";
return command;
}
Write Restore Method:
public ActionResult RestoreDatabase(string filePath)
{
ActionResult res = new ActionResult { Result = true };
using (SalaryAndBenefitsEntities _context = new SalaryAndBenefitsEntities())
{
string command = "select db_name()";
string databaseName = _context.Database.SqlQuery(typeof(string), command).ToListAsync().Result.FirstOrDefault().ToString();
string restoreQuery = RestoreCommand(databaseName, filePath);
var result = _context.Database.SqlQuery<List<string>>(restoreQuery).ToList();
if (result.Count() > 0)
{
res.Result = false;
result.ForEach(x =>
{
res.Message += x.ToString();
});
}
return res;
}
}
if return true database restore is successful else not
the filePath Like: C:\Temp\backup.bak
the Directory of filePath (C:\Temp) must created manually before use of this methods

Categories

Resources