更新具有未知名称/ params数量的sql语句

时间:2012-03-27 13:27:40

标签: c# asp.net .net sql

我有一个经典的ASP网站,我正在慢慢升级。我想创建一个函数来安全地更新SQL数据库,而无需手动指定参数。有点动态。

(我不想使用实体框架或Linq)

以下是目前的代码:

string updateSql = "UPDATE sometable" + "SET test1= @testData1 " + "WHERE a = @aData1";
SqlCommand UpdateCmd = new SqlCommand(updateSql, conn);
UpdateCmd.Parameters.Add("@testData1 ", SqlDbType.NVarChar, 10, "testData1 ");
UpdateCmd.Parameters.Add("@aData1", SqlDbType.NVarChar, 20, "aData1");
UpdateCmd.Parameters["@testData1 "].Value = "21515";
UpdateCmd.Parameters["@aData1"].Value = "32t3t";
UpdateCmd.ExecuteNonQuery();

伪代码(我希望实现的目标)

创建一个涵盖所有变量的Ilist {get; set:} [验证类型/长度]

对于包含值的每个变量(没有验证问题),创建sql update string。

执行它。

可能的问题: 我可以预见的唯一问题是列表可能有500个变量,但每个SQL更新可能只更新2或3列。这不高效吗?

3 个答案:

答案 0 :(得分:3)

你需要做这样的事情....显然需要更多编码......

 static void Main(string[] args)
    {
        var values = new Dictionary<string, object>( );

        values.Add( "name", "timmerz" );
        values.Add( "dob", DateTime.Now );
        values.Add( "sex", "m" );

        SqlUpdate( "sometable", values );
    }

    public static void SqlUpdate( string table, Dictionary<string,object> values, string where )
    {
        var equals      = new List<string>( );
        var parameters  = new List<SqlParameter>( );

        var i = 0;

        foreach( var item in values )
        {
            var pn = "@sp" + i.ToString( );

            equals.Add( string.Format( "{0}={1}", item.Key, pn ) );

            parameters.Add( new SqlParameter( pn, item.Value ) );

            i++;
        }

        string command = string.Format( "update {0} set {1} where {2}", table, string.Join( ", ", equals.ToArray( ) ), where );

        var sqlcommand = new SqlCommand(command);

        sqlcommand.Parameters.AddRange(parameters.ToArray( ) );

        sqlcommand.ExecuteNonQuery( );
    }

答案 1 :(得分:2)

我不确定我是否完全明白你要做的是什么,但这可能接近你正在寻找的东西。您可以创建任意长的参数列表和相应的值,然后从该列表中动态构建相应的UPDATE

//set up SqlCommand
SqlCommand UpdateCmd = new SqlCommand();
UpdateCmd.Connection = conn;

//build your dictionary (probably happens elsewhere in your code)
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("col1", "col1 value");
parameters.Add("col2", 42);
parameters.Add("col3", DateTime.Now);

//build a command string and add parameter values to your SqlCommand
StringBuilder builder = new StringBuilder("UPDATE sometable SET ");
foreach(KeyValuePair<string, object> parameter in parameters) {
    builder.Append(parameter.Key).Append(" = @").Append(parameter.Key).Append(",");
    UpdateCmd.Parameters.AddWithValue("@" + parameter.Key, parameter.Value);
}
builder.Remove(builder.Length - 1,1);

//set the command text and execute the command
UpdateCmd.CommandText = builder.ToString();
UpdateCmd.ExecuteNonQuery();

答案 2 :(得分:0)

如果您使用的是SQL Server 2008,则可以选择将参数及其值作为表传递给存储过程。 在存储过程内部,您可以使用传入的表来加入要更新的表。这可能比创建数百个sep更新语句更有效。 这是一个可能有用的链接http://msdn.microsoft.com/en-us/library/bb675163.aspx 这里有一些示例代码,基于您在问题中发布的代码

首先创建一个要使用的表并用一些数据填充它

CREATE TABLE [dbo].[sometable](
    [Test1] [nvarchar](100) NULL,
    [a] [nvarchar](100) NULL
) ON [PRIMARY]

Insert sometable Select 'rerere', '122342'
Insert sometable Select 'sfsfw', '343'
Insert sometable Select 'sfdrgss', '434545'
Insert sometable Select 'srgegrgeg', '3939932'

然后在SQL Server中创建类型

Create TYPE dbo.ParamsType AS TABLE
( Test1 nvarchar(100), a nvarchar(100) )

然后创建接受该类型作为参数的存储过程

    CREATE PROCEDURE usp_UpdateSomeTable 
@Parameters dbo.ParamsType READONLY
AS
BEGIN
    SET NOCOUNT ON;
UPDATE sometable
    SET sometable.Test1 = p.Test1
    FROM sometable INNER JOIN @Parameters as p
    ON sometable.a = p.a;
END
GO

要从SQL Server Management Studio进行测试,您可以运行

Declare @t as ParamsType
Insert @t Select 'newValue1', '122342'
Insert @t Select 'morenew ', '343'
Insert @t Select 'again', '434545'
Insert @t Select 'OnceMore', '3939932'

exec usp_UpdateSomeTable @Parameters=@t

从C#试试

        static void Main(string[] args)
        {
            System.Data.DataTable YourData = new DataTable("Parameters");
            DataColumn column;
            DataRow row;

            column = new DataColumn();
            column.DataType = System.Type.GetType("System.String");
            column.ColumnName = "Test1";
            YourData.Columns.Add(column);

            column = new DataColumn();
            column.DataType = System.Type.GetType("System.String");
            column.ColumnName = "a";

            YourData.Columns.Add(column);

            row = YourData.NewRow();
            row["Test1"] = "newValue1";
            row["a"] = "122342";
            YourData.Rows.Add(row);

            row = YourData.NewRow();
            row["Test1"] = "morenew";
            row["a"] = "343";
            YourData.Rows.Add(row);

            row = YourData.NewRow();
            row["Test1"] = "again";
            row["a"] = "434545";
            YourData.Rows.Add(row);

            SqlConnectionStringBuilder connString = new SqlConnectionStringBuilder();
            connString.DataSource = "127.0.0.1";
            connString.InitialCatalog = "SO";
            connString.IntegratedSecurity = true;

            using (SqlConnection conn = new SqlConnection())
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.CommandText = "usp_UpdateSomeTable";
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                SqlParameter p = cmd.Parameters.AddWithValue("@Parameters", YourData);
                p.SqlDbType = SqlDbType.Structured;
                p.TypeName = "dbo.ParamsType";

                cmd.Connection = conn;

                conn.ConnectionString = connString.ConnectionString;
                conn.Open();
                cmd.ExecuteNonQuery();
            }
        }