我确定此问题已经得到解答,但我无法使用搜索工具找到答案。
使用c#我想运行一个.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的副作用是您无法捕获重定向的输出。
答案 0 :(得分:164)
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);
}
}
答案 1 :(得分:97)
我使用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 (commandString.Trim() != "")
{
using(var command = new SqlCommand(commandString, Connection))
{
command.ExecuteNonQuery();
}
}
}
Connection.Close();
答案 2 :(得分:9)
这适用于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;
}
}
答案 3 :(得分:8)
将命令执行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
答案 4 :(得分:4)
我设法通过阅读手册来解决问题:)
来自MSDN的摘录
代码示例避免了死锁 通过电话来条件 p.StandardOutput.ReadToEnd之前 p.WaitForExit。死锁情况 如果父进程调用,则会导致 p.WaitForExit之前 p.StandardOutput.ReadToEnd和 子进程写入足够的文本 填充重定向的流。父母 过程会无限期地等待 子进程退出。孩子 过程会无限期地等待 父母要完整阅读 StandardOutput流。
阅读时有类似的问题 所有文本都来自标准输出 和标准错误流。对于 例如,以下C#代码 对两者执行读操作 流。
将代码转换为此内容;
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;
}
现在正确退出。
答案 5 :(得分:4)
对surajits回答添加了其他改进:
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中有多个文件夹,但在我的应用程序中这两个工作。
答案 6 :(得分:3)
这对我有用:
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();
}
}
答案 7 :(得分:1)
使用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);
}
}
}
}
答案 8 :(得分:-1)
我找不到任何准确有效的方法来执行此操作。因此,整整一天之后,我带来了从不同来源获得的混合代码,并试图完成工作。
但是,即使它成功运行了脚本文件,它仍然会生成异常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
{
}
}
}