run .sql file over a collection of databases on an instance - c#

FileInfo file = new FileInfo("C:\\LS\\SmartStats.sql");
string script = file.OpenText().ReadToEnd();
SqlConnection conn = new SqlConnection(sqlConnectionString);
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(script);
I'm not sure where I pilfered this code from but it worked on a single database.
I'm new to C#.
I want to be able to call any .sql file from inside or outside the app. Can't I just string the .sql file and do a foreach over a collection of databases on any given instance?

//reference the following assemplyies of SMO
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Smo
// using Microsoft.SqlServer.Management.Common;
//using Microsoft.SqlServer.Management.Smo;
public static void ExecuteScript(string fname, List<string> databases)
{
string script = File.ReadAllText(fname);
ServerConnection conn = new ServerConnection("server-name/instance", "user", "password");
Server SMOServer = new Server(conn);
// foreach (Database db in SMOServer.Databases) //for all databases in server
foreach (var dbname in databases)
{
var db = SMOServer.Databases[dbname];
var ds = db.ExecuteWithResults(script); //if you want query result as a Dataset
//db.ExecuteNonQuery(script); // if you run non return query result, e.g update/insert/delete
}
conn.Disconnect();
}

I am going to assume that you have the list of databases somewhere that you need to iterate over and that you can figure that part out.
Once you do that, the secret to making this work is the SQL USE statement. You just need to add this dynamically at the top of the script and everything should work correctly.
For example:
FileInfo file = new FileInfo("C:\\LS\\SmartStats.sql");
string script = file.OpenText().ReadToEnd();
SqlConnection conn = new SqlConnection(sqlConnectionString);
Server server = new Server(new ServerConnection(conn));
var databaseNames = new List<String> {"database1", "database2"};
foreach (var databaseName in databaseNames)
{
server.ConnectionContext.ExecuteNonQuery("USE " + databaseName + Environment.NewLine + "GO" + Environment.NewLine + script);
}

Related

Programmatically Backup database from host in asp.net

I have a website and an SQL Server database on it. The control panel of my host is Plesk 12.5. Now, I want backup my database and store it on a special folder in my host. I've added permisson to save data to this special folder in my host control panel, and the function that I use it to create and save database backup is :
string CS = "server=localhost;database = Test;uid=***; password=***;";
string filename = "testDB.bak";
string folderPath = Server.MapPath("~/Backups/");
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
using (SqlConnection con = new SqlConnection(CS))
{
string SqlStmt = String.Format("Backup Database Test To Disk = '{0}'", folderPath + filename);
using (SqlCommand cm = new SqlCommand(SqlStmt, con))
{
try
{
con.Open();
cm.ExecuteNonQuery();
con.Close();
}
catch (Exception E)
{
Label1.Text = E.Message;
return;
}
}
}
'Backups' folder is created, but for backup, get this error: "Cannot open backup device 'C:***********.com\httpdocs\Backups\testDB.bak'. Operating system error 5(Access is denied.). BACKUP DATABASE is terminating abnormally."

Stored Procedure does not fire in Windows Service

I created a Windows service with this code below. Not sure why it will not fire the last SQL Server stored procedure. If I have nothing in the code but the stored procedure than it fires ok. There are no errors.
using (SqlConnection SqlConnection = new SqlConnection(connectionString))
{
SqlConnection.Open();
using (SqlCommand cmdCreateITableSP = new SqlCommand("CreateSP", SqlConnection))
{
cmdCreateITableSP.CommandType = CommandType.StoredProcedure;
cmdCreateTableSP.ExecuteNonQuery();
}
string INTable = "IN";
string XMLPackagesDir = "D:\\Cle\\";
// Create a datatable with two columns:
DataTable INHReponseDT = new DataTable("INHReponseDT");
// Create Columns:
INHReponseDT.Columns.Add("XM");
INHReponseDT.Columns.Add("Cl");
INHReponseDT.Columns.Add("I");
INHReponseDT.Columns.Add("INH");
INHReponseDT.Columns.Add("IN");
DirectoryInfo DirInfo = new DirectoryInfo(XMLPackagesDir);
DataRow INHReponseRow = INHReponseDT.NewRow();
foreach (FileInfo fi in DirInfo.GetFiles("*.*", SearchOption.AllDirectories))
{
XmlSerializer serializer = new XmlSerializer(typeof(Response));
Response i;
FileStream fs = null;
fs = new FileStream(Path.Combine(XMLPackagesDir, fi.Name), FileMode.Open);
using (TextReader tr = new StreamReader(fs))
{
i = (Response)serializer.Deserialize(tr);
INHReponseRow = INHReponseDT.NewRow();
INHReponseRow["XM"] = fi.Name;
INHReponseRow["Cl"] = i.ClientCorrelationID;
INHReponseRow["I"] = i.StatusInformation.StatusItem.MessageText;
INHReponseRow["INH"] = i.ResponseStatus;
INHReponseRow["IN"] = i.RequestProcessedTime.ToString();
INHReponseDT.Rows.Add(INHReponseRow);
}
//Insert into SQL Table
using (SqlBulkCopy s = new SqlBulkCopy(SqlConnection))
{
s.DestinationTableName = INTable;
s.BatchSize = INHReponseDT.Rows.Count;
s.WriteToServer(INHReponseDT);
s.Close();
}
}
using (SqlCommand cmdUpdateCaseInformationINHResponseSP = new SqlCommand("UpdateCaseSP", SqlConnection))
{
cmdUpdateCaseInformationINHResponseSP.CommandType = CommandType.StoredProcedure;
cmdUpdateCaseInformationINHResponseSP.ExecuteNonQuery();
}
}
I had a similar issue with "extra code" in the middle of some SQL commands. While I couldn't immediately see it, there was indeed an error being thrown because of some of the code included between the SQL commands. Wrapping this in a try catch may help show this.
To fix this (and as a matter of good practices), you should create new connections for each SQL command and not reuse the same connection object and keep it open for so long between commands. If you need to ensure that they are handled as a transacted unit, wrap the call to this method in a new TransactionScope()

Cannot initialize the data source object of OLE DB provider "Microsoft.Jet.OLEDB.4.0" for linked server "(null)"

I got an error like this
'Cannot initialize the data source object of OLE DB provider "Microsoft.Jet.OLEDB.4.0" for linked server "(null)".
OLE DB provider "Microsoft.Jet.OLEDB.4.0" for linked server "(null)" returned message "Could not find installable ISAM.".' while transferring database from msaccess to SQL
I have written this code
try
{
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
DataTable userTables = null;
using (connection)
{
string mappath = dataGridView1.CurrentRow.Cells["Path"].Value.ToString();
string[] filePaths = Directory.GetFiles(#"" + mappath + "", "*.mdb", SearchOption.TopDirectoryOnly);
// c:\test\test.mdb
foreach (string tr in filePaths)
{
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + tr + "";
string[] restrictions = new string[4];
restrictions[3] = "Table";
connection.Open();
userTables = connection.GetSchema("Tables", restrictions);
List<string> tableNames = new List<string>();
for (int i = 0; i < userTables.Rows.Count; i++)
tableNames.Add(userTables.Rows[i][2].ToString());
try
{
foreach (string tableName in tableNames)
{
cn1 = new SqlConnection(con);
if (cn1.State != ConnectionState.Open) { cn1.Open(); }
SqlCommand cmd = new SqlCommand("select * into [" + tableName + "] from OPENROWSET('Microsoft.Jet.OLEDB.4.0','" + tr + "',[" + tableName + "])");
cmd.Connection = cn1;
cmd.ExecuteNonQuery();---Got error Here
}
}
catch (Exception Ex) { connection.Close(); }
connection.Close();
}
}
}
catch (Exception Ex) { }
Would you pls solve this error
I have made a simple test on my local environment and the following works like a charm (this is from a C# console application):
static void Main(string[] args)
{
string accessConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Temp\\StackOverflowDemo\\MyAccessDb.mdb;User Id=admin;Password =; ";
using (DbConnection accessConnection = new OleDbConnection(accessConnectionString))
{
accessConnection.Open();
using (DbCommand accessCommand = new OleDbCommand())
{
string accessQuery =
"SELECT * INTO [MySqlTable] IN '' [ODBC;Driver={SQL Server};Server=(local);Database=MySqlDb;Uid=username;Pwd=password;] FROM [MyAccessTable]";
accessCommand.CommandText = accessQuery;
accessCommand.Connection = accessConnection;
accessCommand.ExecuteNonQuery();
}
}
}
I have tested this with a MS Access 2002 database as my source and a SQL Server 2014 database as my target.
Hope this helps.
It looks like you are trying to use the wrong connectionstring to connect to the SQL server (I am assuming you are trying to copy information from MS Access to MS SQL Server).
A valid MS SQL Server connection string would look something like this: Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;
For more information about connectionstrings please have a look at: http://www.connectionstrings.com

creating a local database in a C#

I am writing a C# application
It is an offline test application
It imports a large data file in the form of a .csv file
This file is chosen by the user using a form
I then want to store the information contained in this .csv file in the form of a local database such that I can perform sql queries
I am using Visual Studio 2012
I have never setup an sql database before and only have limited experience using sql on existing databases
My attempt so far is:
Solution explorer > Add new file > Local Database (.sdf file)
Database Explorer > Tables > Create Table
I have then added column names for all the fields setting one as my primary key
I have attempted to add a single dataset to my data table with no luck
string dbfile = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\MyDatabase.sdf";
SqlCeConnection sqlConnection = new SqlCeConnection("datasource=" + dbfile);
SqlCeDataAdapter sqlAdapter = new SqlCeDataAdapter("select * from MyTable", sqlConnection);
AMCCoreSignalsDBDataSet sqlData = new AMCCoreSignalsDBDataSet();
sqlAdapter.Fill(sqlData);
string strCSVDataLine = "1,2,3,four"
sqlData.Tables[0].Rows.Add(new object[] { strCSVDataLine });
sqlAdapter.Update(sqlData);
sqlConnection.Close();
This code fails to work
How can I use C# to populate my database with the .csv data?
Is my method incorrect/incomplete?
Is there a better way to do this?
The reason I would like to use sql is because there is a lot of data. I could create a class structure to contain the data however it would also mean creating many different filter functions. Which SQL already contains...
Problems were due to blank values occurring in the .csv file
This was my fix
public void Import(string csvfname)
{
string password;
string cacheDatabase;
string connectionString;
System.IO.StreamReader objFile;
string strCommand;
string lineHeader;
string line;
string[] arrLineData;
cacheDatabase = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\MyDatabase.sdf"; ;
password = "";
connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", this.cacheDatabase, this.password);
objFile = new System.IO.StreamReader(csvfname);
lineHeader = objFile.ReadLine();
while (!objFile.EndOfStream)
{
line = objFile.ReadLine();
arrLineData = line.Split(',');
try
{
sqlConnection = new SqlCeConnection(connectionString());
strCommand = "INSERT INTO MyTable VALUES ('" + arrLineData[0] + "', '" + arrLineData[1] + "', '" + arrLineData[2] + "')";
SqlCeCommand sqlCommand = new SqlCeCommand(strCommand, sqlConnection);
sqlCommand.ExecuteNonQuery();
sqlConnection.Close();
}
catch (Exception exc)
{
MessageBox.Show("Error in Import(): " + exc.Message);
}
}
}

Postgresql - Create Database & Table dynamically

This code is not working. Can anyone direct me where I can find examples of creating a Postgresql database and table on the fly with C#?
const string connStr = "Server=localhost;Port=5432;
User Id=postgres;Password=enter;Database=postgres";
var m_conn = new NpgsqlConnection(connStr);
// creating a database in Postgresql
m_createdb_cmd = new NpgsqlCommand("CREATE DATABASE IF NOT EXISTS \"testDb\" " +
"WITH OWNER = \"postgres\" " +
"ENCODING = 'UTF8' " +
"CONNECTION LIMIT = -1;", m_conn);
// creating a table in Postgresql
m_createtbl_cmd = new NpgsqlCommand(
"CREATE TABLE MyTable(CompanyName VARCHAR(150))";
m_conn.Open();
m_createdb_cmd.ExecuteNonQuery();
m_createtbl_cmd.Connection = m_conn;
m_conn.Close();
The db is created but I get a silent fail on creating the table.
I would do this:
string connStr = "Server=localhost;Port=5432;User Id=postgres;Password=enter;";
var m_conn = new NpgsqlConnection(connStr);
var m_createdb_cmd = new NpgsqlCommand(#"
CREATE DATABASE IF NOT EXISTS testDb
WITH OWNER = postgres
ENCODING = 'UTF8'
CONNECTION LIMIT = -1;
", m_conn);
m_conn.Open();
m_createdb_cmd.ExecuteNonQuery();
m_conn.Close();
connStr = "Server=localhost;Port=5432;User Id=postgres;Password=enter;Database=testDb";
m_conn = new NpgsqlConnection(connStr);
m_createtbl_cmd = new NpgsqlCommand(
"CREATE TABLE table1(ID CHAR(256) CONSTRAINT id PRIMARY KEY, Title CHAR)"
, m_conn);
m_conn.Open();
m_createtbl_cmd.ExecuteNonQuery();
m_conn.Close();
The use of var here is not recommended. I used it as I don't know what are the returned types but you should.
Notice the use of a raw string (#). It makes string building simple.
Do not use identifiers surrounded by double quotes in Postgresql unless the identifier is otherwise illegal. It will make you life much harder.
seems like you simply forget to invoke ExecuteNonQuery method of m_createtbl_cmd:
m_createtbl_cmd.ExecuteNonQuery();
Also you can simplify it using DynORM library: http://dynorm.codeplex.com/
Hope it helps!
This is what worked for me to verify the existence of any Postgres database with C#:
private bool chkDBExists(string connectionStr, string dbname)
{
using (NpgsqlConnection conn = new NpgsqlConnection(connectionStr))
{
using (NpgsqlCommand command = new NpgsqlCommand
($"SELECT DATNAME FROM pg_catalog.pg_database WHERE DATNAME = '{dbname}'", conn))
{
try
{
conn.Open();
var i = command.ExecuteScalar();
conn.Close();
if (i.ToString().Equals(dbname)) //always 'true' (if it exists) or 'null' (if it doesn't)
return true;
else return false;
}
catch (Exception e) { return false; }
}
}
}
** The if used in the try-catch statement could simply check if the return of the ExecuteScalar is null for non-existent DB and not-null if it exists.
You can pass the ConnectionString to this function :
private static string GetConnectionString(string postgreSqlConnectionString)
{
NpgsqlConnectionStringBuilder connBuilder = new()
{
ConnectionString = postgreSqlConnectionString
};
string dbName = connBuilder.Database;
var masterConnection = postgreSqlConnectionString.Replace(dbName, "postgres");
using (NpgsqlConnection connection = new(masterConnection))
{
connection.Open();
using var checkIfExistsCommand = new NpgsqlCommand($"SELECT 1 FROM pg_catalog.pg_database WHERE datname = '{dbName}'", connection);
var result = checkIfExistsCommand.ExecuteScalar();
if (result == null)
{
using var command = new NpgsqlCommand($"CREATE DATABASE \"{dbName}\"", connection);
command.ExecuteNonQuery();
}
}
postgreSqlConnectionString = masterConnection.Replace("postgres", dbName);
return postgreSqlConnectionString;
}
This will retrieve dbname from ConnectionString then checks if it already exists or not. if it didn't exist it will create one with the given dbname.
You should use above function in ConfigureServices of Startup class like this :
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
{
options.UseNpgsql(GetConnectionString(Configuration["YourConnectionString"]));
});
}
Solution:
// 1. Connect to server to create database:
const string connStr = "Server=localhost;Port=5432;User Id=postgres;Password=enter;";
// 2. Connect to server to create table:
const string connStr2 = "Server=localhost;Port=5432;User Id=postgres;Password=enter;Database=testDb";
var m_conn = new NpgsqlConnection(connStr); // db connction
var m_conn2 = new NpgsqlConnection(connStr2); // table connection
// creating a database in Postgresql
m_createdb_cmd = new NpgsqlCommand("CREATE DATABASE IF NOT EXISTS \"testDb\" " +
"WITH OWNER = \"postgres\" " +
"ENCODING = 'UTF8' " +
"CONNECTION LIMIT = -1;", m_conn);
// creating a table in Postgresql
m_createtbl_cmd = new NpgsqlCommand
{
CommandText ="CREATE TABLE table1(ID CHAR(256) CONSTRAINT id PRIMARY KEY, Title CHAR)"
};
m_createtbl_cmd.Connection = m_conn2;
// 3.. Make connection and create
// open connection to create DB
m_conn.Open();
m_createdb_cmd.ExecuteNonQuery();
m_conn.Close();
// open connection to create table
m_conn2.Open();
m_createtbl_cmd.ExecuteNonQuery();
m_conn2.Close();
This works but is there a shorter way to do this? I had to create two Npgsql connections. I don't know, just doesn't look very elegant to me.

Categories

Resources