2009-08-31 72 views
1

我有以下方法应该是我的应用程序的通用“保存到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 ????? somethign?但我迷失了。任何帮助?

编辑:为了简单起见,我们假设我的数据库中有一个名为“ABC”的存储过程。我怎么能将它与我的代码中的SqlCommand“Command”相关联?

回答

3

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会为字符串传递NVARCHAR类型的参数,而不是VARCHAR,并且使用临时SQL可能会导致VARCHAR列上的索引SARG能力问题(因为转换始终是从VARCHAR到NVARCHAR,而不是反之亦然)。但是,使用存储过程不是这样的问题,因为过程具有类型参数,因此如果过程是使用参数类型VARCHAR创建的,则会对VARCHAR发生强制强制。

您也将有大约传递NULL参数,问题所以你需要做这样的事情,参数必须是DBNull.Valuenull

Command.Parameters.AddWithValue(name, Parametros[name] ?? DBNull.Value); 

在高性能系统中这种方法也污染了执行不必要地缓存,因为AddWithValue将传递NVARCHAR(<exact length of the string>)类型的参数,而不是NVARCHAR(<length of the database type>)。因此,Paramaters.AddWithValue("@name", "John")Parameters.AddwithValue("@name", "Doe")将在缓存中创建两个不同的计划,因为一个是使用NVARCHAR(4)类型的参数调用的,另一个使用参数NVARCHAR(3),并且它们被SQL计划缓存视为不同类型。这对简单的项目不是问题,但对于更复杂和更高性能的项目,建议您明确设置参数类型。

我的建议是避免使用这种通用的一劳永逸的过程,而是用适当的类型参数为每个数据库过程编写一个带有显式C#包装的数据访问层。强类型数据集实际上可以做到这一点,另一种选择(我最喜欢的和我总是使用的)是使用创建C#包装器的XSLT样式表从XML文件生成整个数据访问员。源XML当然是从数据库元数据本身提取的。

+0

他们只是普通的对象。我的计划是将一堆东西(int,string,bool)加载到object []数组中,然后使用foreach加载参数。这将工作正确吗? :) – 2009-08-31 03:20:28

+0

不,您需要传递参数名称 - 值的字典并为每个参数分配名称。 – 2009-08-31 03:22:25

+0

您的存储过程规定了可以添加到命令对象的参数。 – 2009-08-31 03:22:33

0
Command.ComandText = "storedProcName"; 
0

Command.CommandText = "ProcedimientoAlmacenado";之前或之后Command.CommandType = CommandType.StoredProcedure;这不是强制性的,但那个是我做的方式。

0

设置SqlCommand对象的CommandText属性到您的存储过程的名称:

Command.CommandText = "MyStoredProcedureName";