我的以下方法应该是我的应用程序的通用“保存到SQL”方法。
protected void EjecutarGuardar(string ProcedimientoAlmacenado, object[] Parametros) { SqlConnection Connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString); SqlCommand Command = Connection.CreateCommand(); Command.CommandType = CommandType.StoredProcedure; foreach (object X in Parametros) { Command.Parameters.Add(X); } Connection.Open(); Command.ExecuteNonQuery(); Connection.Close(); Connection.Dispose(); }
我必须传递StoredProcedure的名称和一个填充有参数的数组。在这一点上,我有点迷茫。我应该在哪里使用存储过程“ ProcedimientoAlmacenado”的名称?
我在想Command.Command ????? 但是我迷路了。有什么帮助吗?
编辑:为简单起见,假设我在数据库中有一个名为“ ABC”的存储过程。如何在我的代码中将其与SqlCommand“ Command”关联?
Command.CommandText= ProcedimientoAlmacenado
Command.CommandText
= ProcedimientoAlmacenado
参数也必须具有名称。Parametros数组包含SqlParameter对象还是通用C#对象?
如果参数是通用C#对象,则最好传入名称和值的字典:
protected void EjecutarGuardar(string ProcedimientoAlmacenado, Dictionary<string, object> Parametros) { using (SqlConnection Connection = new SqlConnection(...)) { Connection.Open(); SqlCommand Command = Connection.CreateCommand() Command.CommandText = ProcedimientoAlmacenado; Command.Connection = Connection; Command.CommandType = CommandType.StoredProcedure; foreach (string name in Parametros.Keys) { Command.Parameters.AddWithValue(name, Parametros[name] ?? DBNull.Value); } Command.ExecuteNonQuery(); } }
这是一种快速而肮脏的方法。请注意,这种方法通常会出现问题,因为AddWithValue会为字符串而不是VARCHAR传递NVARCHAR类型的参数,并且使用临时SQL可能会在VARCHAR列上导致索引SARG- ability问题(因为转换始终是从VARCHAR进行的)改为NVARCHAR,反之亦然)。但是,使用存储过程不是这样的问题,因为过程具有参数类型,因此,如果使用参数类型VARCHAR创建过程,则会对VARCHAR产生强制转换。
您还会在传递NULL参数方面遇到问题,因此您需要执行类似的操作,该参数必须DBNull.Value不是null:
DBNull.Value
null
Command.Parameters.AddWithValue(name, Parametros[name] ?? DBNull.Value);
在高性能系统上,此方法还会不必要地污染执行缓存,因为AddWithValue将传递类型为NVARCHAR(<exact length of the string>)not的参数NVARCHAR(<length of the database type>)。因此Paramaters.AddWithValue("@name", "John"),Parameters.AddwithValue("@name", "Doe")它将在缓存中创建两个不同的计划,因为一个计划是使用参数NVARCHAR(4)调用的,另一个计划是使用参数NVARCHAR(3)调用的,并且在SQL计划缓存中将它们视为 不同的类型 。在简单的项目上这不是问题,但是在更复杂和高性能的项目上,建议显式设置参数类型。
NVARCHAR(<exact length of the string>)
NVARCHAR(<length of the database type>)
Paramaters.AddWithValue("@name", "John")
Parameters.AddwithValue("@name", "Doe")
我的建议是避免这种通用的“一刀切”过程,而应为每个数据库过程编写带有显式C#包装器的数据访问层,并使用适当的类型参数。强类型数据集实际上可以做到这一点,另一种选择(我最喜欢的,也是我一直使用的)是使用创建C#包装程序的XSLT样式表从XML文件生成整个数据访问权限。当然,源XML是从数据库元数据本身中提取的。