我想知道将一些代码抽象成一个简单的DAL是一种更好的方法。目前,我只是修补代码,没有时间或者现在还不需要使用EF,Linq2Sql或任何ORM。
public string GetMySpecId(string dataId)
{
using (SqlConnection conn = new SqlConnection(this.MyConnectionString))
{
conn.Open();
// Declare the parameter in the query string
using (SqlCommand command = new SqlCommand(@"select ""specId"" from ""MyTable"" where ""dataId"" = :dataId", conn))
{
// Now add the parameter to the parameter collection of the command specifying its type.
command.Parameters.Add(new SqlParameter("dataId", SqlDbType.Text));
command.Prepare();
// Now, add a value to it and later execute the command as usual.
command.Parameters[0].Value = dataId;
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
specId = dr[0].ToString();
}
}
}
}
return specId;
}
从GetMySpecId()中提取连接,命令等等是一个很好的干净方法,因为我将拥有大量这些函数,并且不想一遍又一遍地使用.... / p>
答案 0 :(得分:2)
好吧,您可以编写自己的自定义数据访问助手,封装所有内容并返回DataTable:
public string GetMySpecId(string dataId)
{
DataTable result = _dbHelper.ExecuteQuery(
@"select ""specId"" from ""MyTable"" where ""dataId"" = :dataId",
new SqlParameter("dataId", dataId);
return result.Rows[0][0].ToString();
}
或者如果你坚持使用DataReader的想法,你可以将一个委托传递给helper,它在using语句中被调用:
public string GetMySpecId(string dataId)
{
return _dbHelper.ExecuteQuery(
dr =>
{
if(dr.Read())
{
return dr[0].ToString();
}
// do whatever makes sense here.
},
@"select ""specId"" from ""MyTable"" where ""dataId"" = :dataId",
new SqlParameter("dataId", dataId));
}
您还可以使用像Dapper这样的轻量级工具来简化某些语法,并负责映射到您的数据类型。 (你仍然需要处理打开连接等问题。)
以下是如何编写第二个示例中使用的ExecuteQuery方法的示例:
public T ExecuteQuery<T>(
Func<IDataReader, T> getResult,
string query,
params IDataParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(this.MyConnectionString))
{
conn.Open();
// Declare the parameter in the query string
using (SqlCommand command = new SqlCommand(query, conn))
{
foreach(var parameter in parameters)
{
command.Parameters.Add(parameter);
}
command.Prepare();
using (SqlDataReader dr = command.ExecuteReader())
{
return getResult(dr);
}
}
}
}
答案 1 :(得分:1)
您可以使用yield return语句,以便使用语句保持连接,命令和读取器对象。
public class ScalarReader<T>
{
const string MyConnectionString = "...";
private string _returnColumn, _table, _whereCond;
private object[] _condParams;
public ScalarReader(string returnColumn, string table, string whereCond,
params object[] condParams)
{
_returnColumn = returnColumn;
_table = table;
_whereCond = whereCond;
_condParams = condParams;
}
public IEnumerator<T> GetEnumerator()
{
using (SqlConnection conn = new SqlConnection(MyConnectionString)) {
conn.Open();
string select = String.Format(@"SELECT ""{0}"" FROM ""{1}"" WHERE {2}",
_returnColumn, _table, _whereCond);
using (SqlCommand command = new SqlCommand(select, conn)) {
for (int p = 0; p < _condParams.Length; p++) {
command.Parameters.AddWithValue("@" + (p+1), _condParams[p]);
}
using (SqlDataReader dr = command.ExecuteReader()) {
while (dr.Read()) {
if (dr.IsDBNull(0)) {
yield return default(T);
} else {
yield return (T)dr[0];
}
}
}
}
}
}
}
你会这样称呼它
var reader = new ScalarReader<string>("specId", "MyTable", "dataId=@1", "x");
foreach (string id in reader) {
Console.WriteLine(id);
}
请注意,我正在使用参数名称的约定。它们被命名为@1, @2, @3 ...
。
var reader =
new ScalarReader<DateTime>("date", "MyTable", "num=@1 AND name=@2", 77, "joe");
答案 2 :(得分:0)
您需要从using语句的中间返回一个IDataReader,一旦这样做,您将失去连接和数据。你不能真正做你想做的事。
答案 3 :(得分:0)
你可以做这样的事情,抱歉没有实际的代码,但它会给你这个想法。当然,必须小心地将object []转换回有用的东西,但是你已经在使用specId = dr [0] .ToString();
class MyDb
{
public MyDb()
{
}
public void Initialize()
{
// open the connection
}
public void Finalize()
{
// close the connection
}
public List<object[]> Query(string command, List<SqlParameter> params)
{
// prepare command
// execute reader
// read all values into List of object[], and return it
}
}
答案 4 :(得分:0)
您可以创建一个基本抽象类,它将具有一些基本函数,包含所有使用和基本代码,如下所示:
public abstract class BaseClass
{
public abstract void myFunc(SqlConnection conn);
public void BaseFunc()
{
using (SqlConnection conn = new SqlConnection(this.MyConnectionString))
{
conn.Open();
myFunc(conn);
..any other base implementation...
}
}
}
每个派生类都将使用BaseClass并使用特定查询和每个派生类的所有特定内容实现抽象MyFunc。您将从外部抽象类的BaseFunc函数外部调用。