Я уверен, что на этот вопрос уже был дан ответ, однако мне не удалось найти ответ с помощью инструмента поиска.
Используя С #, я хотел бы запустить файл .sql. Файл sql содержит несколько операторов sql, некоторые из которых разбиты на несколько строк. Я попытался прочитать файл и попытался выполнить файл с помощью ODP.NET ... однако я не думаю, что ExecuteNonQuery действительно предназначен для этого.
Поэтому я попытался использовать sqlplus, создав процесс ... однако, если я не запустил процесс с UseShellExecute, установленным в true, sqlplus зависнет и никогда не завершится. Вот код, который НЕ РАБОТАЕТ.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "sqlplus";
p.StartInfo.Arguments = string.Format("xx/xx@{0} @{1}", in_database, s);
p.StartInfo.CreateNoWindow = true;
bool started = p.Start();
p.WaitForExit();
WaitForExit никогда не возвращает .... Если я не установил UseShellExecute в true. Побочный эффект UseShellExecute заключается в том, что вы не можете захватить перенаправленный вывод.
Ответы:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Common; using System.IO; using System.Data.SqlClient; public partial class ExcuteScript : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string sqlConnectionString = @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=ccwebgrity;Data Source=SURAJIT\SQLEXPRESS"; string script = File.ReadAllText(@"E:\Project Docs\MX462-PD\MX756_ModMappings1.sql"); SqlConnection conn = new SqlConnection(sqlConnectionString); Server server = new Server(new ServerConnection(conn)); server.ConnectionContext.ExecuteNonQuery(script); } }
источник
<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> </startup>
Я пробовал это решение с Microsoft.SqlServer.Management, но оно не работало с .NET 4.0, поэтому я написал другое решение, используя только платформу .NET libs.
string script = File.ReadAllText(@"E:\someSqlScript.sql"); // split script on GO command IEnumerable<string> commandStrings = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase); Connection.Open(); foreach (string commandString in commandStrings) { if (!string.IsNullOrWhiteSpace(commandString.Trim())) { using(var command = new SqlCommand(commandString, Connection)) { command.ExecuteNonQuery(); } } } Connection.Close();
источник
Это работает на Framework 4.0 или выше. Поддерживает «GO». Также покажите сообщение об ошибке, строку и команду sql.
using System.Data.SqlClient; private bool runSqlScriptFile(string pathStoreProceduresFile, string connectionString) { try { string script = File.ReadAllText(pathStoreProceduresFile); // split script on GO command System.Collections.Generic.IEnumerable<string> commandStrings = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase); using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); foreach (string commandString in commandStrings) { if (commandString.Trim() != "") { using (var command = new SqlCommand(commandString, connection)) { try { command.ExecuteNonQuery(); } catch (SqlException ex) { string spError = commandString.Length > 100 ? commandString.Substring(0, 100) + " ...\n..." : commandString; MessageBox.Show(string.Format("Please check the SqlServer script.\nFile: {0} \nLine: {1} \nError: {2} \nSQL Command: \n{3}", pathStoreProceduresFile, ex.LineNumber, ex.Message, spError), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } } } } connection.Close(); } return true; } catch (Exception ex) { MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } }
источник
connection.Close()
соединение будет закрытоusing
вы обвил его.Поместите команду для выполнения сценария sql в пакетный файл, затем запустите приведенный ниже код
string batchFileName = @"c:\batosql.bat"; string sqlFileName = @"c:\MySqlScripts.sql"; Process proc = new Process(); proc.StartInfo.FileName = batchFileName; proc.StartInfo.Arguments = sqlFileName; proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; proc.StartInfo.ErrorDialog = false; proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(batchFileName); proc.Start(); proc.WaitForExit(); if ( proc.ExitCode!= 0 )
в командном файле напишите что-то вроде этого (образец для sql server)
osql -E -i %1
источник
Это работает для меня:
public void updatedatabase() { SqlConnection conn = new SqlConnection("Data Source=" + txtserver.Text.Trim() + ";Initial Catalog=" + txtdatabase.Text.Trim() + ";User ID=" + txtuserid.Text.Trim() + ";Password=" + txtpwd.Text.Trim() + ""); try { conn.Open(); string script = File.ReadAllText(Server.MapPath("~/Script/DatingDemo.sql")); // split script on GO command IEnumerable<string> commandStrings = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase); foreach (string commandString in commandStrings) { if (commandString.Trim() != "") { new SqlCommand(commandString, conn).ExecuteNonQuery(); } } lblmsg.Text = "Database updated successfully."; } catch (SqlException er) { lblmsg.Text = er.Message; lblmsg.ForeColor = Color.Red; } finally { conn.Close(); } }
источник
Добавлены дополнительные улучшения в ответ сураджитов:
using System; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Common; using System.IO; using System.Data.SqlClient; namespace MyNamespace { public partial class RunSqlScript : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { var connectionString = @"your-connection-string"; var pathToScriptFile = Server.MapPath("~/sql-scripts/") + "sql-script.sql"; var sqlScript = File.ReadAllText(pathToScriptFile); using (var connection = new SqlConnection(connectionString)) { var server = new Server(new ServerConnection(connection)); server.ConnectionContext.ExecuteNonQuery(sqlScript); } } } }
Также мне пришлось добавить в свой проект следующие ссылки:
C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SqlServer.ConnectionInfo.dll
C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SqlServer.Smo.dll
Я понятия не имею, подходят ли эти dll: s для использования, поскольку в C: \ Program Files \ Microsoft SQL Server есть несколько папок, но в моем приложении эти две работают.
источник
Мне удалось найти ответ, прочитав инструкцию :)
Этот отрывок из MSDN
Превращает код в это;
Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "sqlplus"; p.StartInfo.Arguments = string.Format("xxx/xxx@{0} @{1}", in_database, s); bool started = p.Start(); // important ... read stream input before waiting for exit. // this avoids deadlock. string output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); Console.WriteLine(output); if (p.ExitCode != 0) { Console.WriteLine( string.Format("*** Failed : {0} - {1}",s,p.ExitCode)); break; }
Что теперь выходит правильно.
источник
p.StandardOutput.ReadToEnd();
никогда не выходитСледует учитывать два момента.
1) Этот исходный код работал у меня:
private static string Execute(string credentials, string scriptDir, string scriptFilename) { Process process = new Process(); process.StartInfo.UseShellExecute = false; process.StartInfo.WorkingDirectory = scriptDir; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.FileName = "sqlplus"; process.StartInfo.Arguments = string.Format("{0} @{1}", credentials, scriptFilename); process.StartInfo.CreateNoWindow = true; process.Start(); string output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); return output; }
Я установил рабочий каталог в каталог сценария, чтобы вложенные сценарии в сценарии также работали.
Назовите это, например, как
Execute("usr/pwd@service", "c:\myscripts", "script.sql")
2) Вы должны завершить свой SQL-скрипт с помощью оператора
EXIT;
источник
Используя EntityFramework, вы можете пойти с таким решением. Я использую этот код для инициализации тестов e2e. Для предотвращения атак с использованием sql-инъекций убедитесь, что этот сценарий не создается на основе пользовательского ввода, и не используйте для этого параметры команды (см. Перегрузку ExecuteSqlCommand, которая принимает параметры).
public static void ExecuteSqlScript(string sqlScript) { using (MyEntities dataModel = new MyEntities()) { // split script on GO commands IEnumerable<string> commands = Regex.Split( sqlScript, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase); foreach (string command in commands) { if (command.Trim() != string.Empty) { dataModel.Database.ExecuteSqlCommand(command); } } } }
источник
Я не мог найти точного и действенного способа сделать это. Итак, после целого дня я пришел с этим смешанным кодом, полученным из разных источников и пытающимся выполнить свою работу.
Но он по-прежнему генерирует исключение,
ExecuteNonQuery: CommandText property has not been Initialized
даже если он успешно запускает файл сценария - в моем случае он успешно создает базу данных и вставляет данные при первом запуске.public partial class Form1 : MetroForm { SqlConnection cn; SqlCommand cm; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { if (!CheckDatabaseExist()) { GenerateDatabase(); } } private bool CheckDatabaseExist() { SqlConnection con = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=SalmanTradersDB;Integrated Security=true"); try { con.Open(); return true; } catch { return false; } } private void GenerateDatabase() { try { cn = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=master;Integrated Security=True"); StringBuilder sb = new StringBuilder(); sb.Append(string.Format("drop databse {0}", "SalmanTradersDB")); cm = new SqlCommand(sb.ToString() , cn); cn.Open(); cm.ExecuteNonQuery(); cn.Close(); } catch { } try { //Application.StartupPath is the location where the application is Installed //Here File Path Can Be Provided Via OpenFileDialog if (File.Exists(Application.StartupPath + "\\script.sql")) { string script = null; script = File.ReadAllText(Application.StartupPath + "\\script.sql"); string[] ScriptSplitter = script.Split(new string[] { "GO" }, StringSplitOptions.None); using (cn = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=master;Integrated Security=True")) { cn.Open(); foreach (string str in ScriptSplitter) { using (cm = cn.CreateCommand()) { cm.CommandText = str; cm.ExecuteNonQuery(); } } } } } catch { } } }
источник