假设您有一些简单的sprocs,例如
AddXYZ(param1,param 2 ... etc)
getAllXYZ()
getXYZ(ID)
从“db layer”
调用这些sprocs的“最佳实践”方法是什么?我不想使用linq。关于如何做到这一点的简单c#静态方法。
即时使用sqlserver。
答案 0 :(得分:8)
我认为你并不真正意味着static
方法,因为这样做是非常非OO的方式,而且C#中没有这样的设施。但是,有一些标准的ADO.NET类可以让你在没有任何ORM包装或使用DataSet
之类的情况下执行此操作.-
如果您真的想要手动调用存储过程并在没有任何ORM或标准化存储机制的情况下获取一组结果,那么这将是您最好的选择:
using(System.Data.IDbConnection conn = /*create your connection here*/)
{
using(System.Data.IDbCommand cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "AddXYZ";
// add your parameters here using cmd.CreateParameter() and cmd.Parameters.Add()
using(System.Data.IDbDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
// read your results row-by-row
}
}
}
}
您没有指定要连接的数据库引擎,因此我使用了通用接口来抽象您。如果你愿意(虽然我通常不会对执行此操作的代码感到不满),你可以使用特定于平台的类,使事情变得更加容易,至少在添加参数方面(代码不像基于接口的方法那样冗长)< / p>
答案 1 :(得分:5)
这是你在找什么?
SqlCommand cmd = new SqlCommand("AddXYZ", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@param1", someValue));
答案 2 :(得分:1)
首先,在数据层中创建一个用于获取连接信息的位置。如果您的数据层仅限于单个类,则可能是私有成员;如果图层包含整个程序集,则可能是内部项。它可以返回一个连接字符串或一个实际的连接对象本身,但主要的是它根本没有暴露在数据层之外:
private static ConnectionString { get { // read from config file once.... return ""; } }
private SqlConnection getConnection()
{
SqlConnection result = new SqlConnection(ConnectionString);
result.Open(); // I like to open it in advance, but that's less common
return result; // you'll want some error handling code in here as well
}
然后,您在数据层中提供与要提供给业务层的接口匹配的公共方法。在一个设计良好的应用程序中,这通常会与存储过程相匹配,这听起来就像你想要的那样,但有时它并不能很好地工作。例如,您可能需要从一个方法调用多个过程。
无论您做什么,该方法都应接受强类型参数值,以便在调用过程时使用。关于该方法是应该返回业务对象还是数据记录存在争议。就个人而言,我倾向于返回一个datarecord,但提供一个额外的“层”,其中datarecords被转换为强类型的业务对象:
public IDataRecord GetXYZ(int id)
{
DataTable dt = new DataTable();
using (var cn = getConnection())
using (var cmd = new SqlCommand("getXYZ"))
{
cmd.CommandType = CommandTypes.StoredProcedure;
cmd.Parameters.Add("@ID", SqlDbType.Int).Value = id;
using (var rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
}
//obviously put a little more work into your error handling
if (dt.Rows.Count <= 0)
throw new Exception("oops");
return dt.Rows[0];
}
public class XYZFactory
{
public static XZY Create(IDataRecord row)
{
XYZ result = new XYZ();
result.id = row["ID"];
result.otherfield = row["otherfield"];
return result;
}
}
答案 3 :(得分:0)
通常,您需要查看SQLConnection和SQLCommand类(假设您正在连接到SQL db,当然)。您将SQLCommand.CommandText属性设置为“EXEC AddXYZ @X,@ Y,@ Z”,然后对@X,@ Y和@Z使用SQLCommand.Parameters.AddWithValue()。
然后,您将调用SQLCommand的相应执行方法(NonQuery,Scalar或Reader)。
答案 4 :(得分:0)
托马斯的榜样是标准方式。我建议您查看以下内容以获得进一步的帮助:
http://msdn.microsoft.com/en-us/library/aa902662.aspx
就个人而言,我编写了一个静态类(DataHelper),它公开了一些你可能会使用的方法,例如那些在你的存储过程返回东西时返回IDataReader对象的方法,以及它们何时返回的void方法不是,以及一些在out参数中返回Connection对象的东西,所以你可以保持它打开。
该类只是将ADO.NET代码包装在try catch块中,用于常见问题检查和日志记录/跟踪(DNS关闭,服务器关闭,svc关闭),并使用using语句确保不浪费资源。我还包装了一个使用ConnectionStringBuilder返回连接字符串的方法,因此我不必继续编写该代码。
我确实发现,对于一个大项目,编码所有实体'提供者'是重复的,我应该设计一个更可重用的配置驱动模型。
如果我有绿地,我会看看使用EDM。
http://msdn.microsoft.com/en-us/library/aa697428(VS.80).aspx