gpt4 book ai didi

c# - 如何在数据访问层管理 SqlDataReader?

转载 作者:太空宇宙 更新时间:2023-11-03 20:45:44 24 4
gpt4 key购买 nike

我正在尝试更好地处理代码解耦、代码重用等问题。

每次我想阅读一些行时,我都厌倦了输入以下内容:

using(SqlConnection conn = new SqlConnection(myConnString))
{
using(SqlCommand cmd = new SqlCommand(cmdTxt, conn))
{
conn.Open();
using(SqlDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
/* do something with rows */
}
}
}
}

我知道有 LINQ to SQL(我不喜欢它)和 Entity Framework(还是婴儿)。我不必输入查询就没有问题,我只是不想每次都输入命令构造、行迭代器等。

我环顾四周,发现了一些我认为对我有用的东西,并尝试实现它以使事情对我来说更容易。正如您在评论中看到的,我收到一条错误消息,指出 SqlDataReader 已关闭。我猜这可能是因为 DataFactory.ExecuteReader() 方法中的 using 语句。当读取器返回时,将对我的 SqlConnection 和 SqlCommand 变量调用 dispose 方法。我在那里吗?如果是这样,应该如何管理连接和命令变量?

编辑:我更新了我的代码示例以更好地反射(reflect)我在做什么。

public class DataFactory
{
public DataFactory()
{}

public DataFactory(string connectionString)
{
_connectionString = connectionString;
}

protected _connectionString = "Data Source=Localhost, etc, etc";
private string ConnectionString
{
get{return _connectionString;}
}

public SqlConnection GetSqlConnection()
{
return new SqlConnection(ConnectionString);
}

public SqlDataReader ExecuteReader(string cmdTxt)
{
using(SqlConnection conn = new SqlConnection(ConnectionString))
{
using(SqlCommand cmd = new SqlCommand(cmdTxt, conn))
{
conn.Open();
return cmd.ExecuteReader();
}
}
}
}

public IRepository<T>
{
T GetById(int id);
}

public MyTypeRepository: IRepository<MyType>
{
private static DataFactory _df = new DataFactory();

public MyType GetById(int id)
{
string cmdTxt = String.Format("SELECT Name FROM MyTable WHERE ID = {0}", id);

using(SqlDataReader rdr = _df.ExecuteReader(cmdTxt))
{
if(rdr.Read()) /* I get an error that the reader is already closed here */
{
return new MyType(
Convert.ToInt32(rdr["Id"]),
rdr["Name"]);
}
else
{
return null;
}
}
}
}




public class MyType
{
public MyType(int id, string name)
{
_id = id;
_name = name;
}

private string _name;
public string Name
{
get{return _name;}
}

private int _id;
public int Id
{
get{return _id;}
}

public override void ToString()
{
return string.Format("Name: {0}, Id: {1}", Name, Id);
}
}

public class Program
{
private static MyTypeRepository _mtRepo = new MyTypeRepository();

static void Main()
{
MyType myType = _mtRepo.GetById(1);

Console.WriteLine(myType.ToString());
}
}

我还想知道我正在做的事情是否有意义,或者,如果没有,如何实现类似的东西,这样我就不必经常输入连接创建等。

最佳答案

您的方法 ExecuteReader 将在返回 Reader 之前关闭连接。相反,它应该像这样实现:

public IDataReader ExecuteReader(string cmdTxt)    
{
SqlConnection conn = new SqlConnection(...);
try
{
SqlCommand cmd = new SqlCommand(cmdTxt, conn);
conn.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
conn.Close();
throw;
}
}

ExecuteReader 方法的调用者需要处理 IDataReader:

using(IDataReader reader = ExecuteReader(commandText))
{
...
} // reader will be disposed here and will close the connection.

请注意,上面没有调用 SqlCommand 对象上的 Dispose。根据我的经验以及通过使用 Reflector 查看 SqlCommand,只要 SqlConnection 被处置,就没有必要。但我相信如果你确实想处理它,以下方法会起作用:

public IDataReader ExecuteReader(string cmdTxt)    
{
SqlConnection conn = new SqlConnection(...);
SqlCommand cmd = null;
try
{
cmd = new SqlCommand(cmdTxt, conn);
conn.Open();
IDataReader reader =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Dispose();
return reader;
}
catch
{
if (cmd != null) cmd.Dispose();
conn.Close();
throw;
}
}

关于c# - 如何在数据访问层管理 SqlDataReader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/941126/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com