C# 返回SqlDataReader
我有以下代码:C# 返回SqlDataReader,c#,ado.net,C#,Ado.net,我有以下代码: public static SqlDataReader GetGeneralInformation ( int RecID ) { using ( var conn = new SqlConnection( GetConnectionString() ) ) using ( var cmd = conn.CreateCommand() ) { conn.Open(); cmd.CommandText = @"
public static SqlDataReader GetGeneralInformation ( int RecID )
{
using ( var conn = new SqlConnection( GetConnectionString() ) )
using ( var cmd = conn.CreateCommand() )
{
conn.Open();
cmd.CommandText =
@"SELECT cs.Status, cs.Completed
FROM NC_Steps s
INNER JOIN NC_ClientSteps cs
ON cs.RecID = s.RecID
WHERE cs.ClientID = 162
AND s.RecID = @value";
cmd.Parameters.AddWithValue( "@value", RecID );
using ( var reader = cmd.ExecuteReader() )
{
if ( reader.Read() )
{
return reader;
}
return null;
}
}
}
我如何引用这个
我试过了,但没用
SqlDataReader reader = GeneralFunctions.GetGeneralInformation();
还有,我如何从读者那里阅读
Reader.GetString( reader.GetOrdinal( "Status" ) )
编辑:
我现在得到以下错误:
异常详细信息:System.NullReferenceException:对象引用不存在
设置为对象的实例
以下是更新的代码:
public static IEnumerable<IDataRecord> GetGeneralInformation ( int ClientID )
{
using ( var conn = new SqlConnection( GetConnectionString() ) )
using ( var cmd = conn.CreateCommand() )
{
conn.Open();
cmd.CommandText =
@"SELECT i.GoLiveDate, i.FirstBonusRun, i.TechFName, i.TechLName, i.TechEmail, i.TechPhone, i.WebISPFName, i.WebISPLName,
i.WebISPEmail, i.WebISPPhone, i.FullFillFName, i.FullFillLName, i.FullFillEmail, i.FullFillPhone, d.FName,
d.LName, d.HomePhone, d.Email
FROM NC_Information i
INNER JOIN Distributor d
ON d.DistID = i.ClientID
WHERE clientID = @value";
cmd.Parameters.AddWithValue( "@value", ClientID );
using ( var reader = cmd.ExecuteReader() )
{
while ( reader.Read() )
{
yield return reader;
}
yield return null;
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
IEnumerable<IDataRecord> reader = GeneralFunctions.GetGeneralInformation( (int)Session[ "DistID" ] );
//string result = GeneralFunctions.GetGeneralInformation( Globals.GeneralInformation ).First()[ "Status" ].ToString();
}
公共静态IEnumerable GetGeneralInformation(int-ClientID)
{
使用(var conn=new SqlConnection(GetConnectionString()))
使用(var cmd=conn.CreateCommand())
{
conn.Open();
cmd.CommandText=
@“选择i.GoLiveDate、i.FirstBonusRun、i.TechFName、i.TechLName、i.TechEmail、i.TechPhone、i.WebISPFName、i.WebISPLName,
i、 WebISPEmail,i.WebISPPhone,i.FullFillFName,i.FullFillName,i.FullFillEmail,i.FullFillPhone,d.FName,
d、 L姓名,d.家庭电话,d.电子邮件
来自NC_信息i
内连接分配器d
在d.DistID=i.ClientID上
其中clientID=@value”;
cmd.Parameters.AddWithValue(“@value”,ClientID);
使用(var reader=cmd.ExecuteReader())
{
while(reader.Read())
{
回传阅读器;
}
收益返回空;
}
}
}
受保护的无效页面加载(对象发送方、事件参数e)
{
IEnumerable reader=GeneralFunctions.GetGeneralInformation((int)会话[“DistID]”);
//字符串结果=GeneralFunctions.GetGeneralInformation(Globals.GeneralInformation).First()[“Status”].ToString();
}
问题在于离开函数(通过返回语句)会将您踢出使用块的,因此您正在使用的SqlDataReader
和SqlConnections
会被释放。要解决此问题,请尝试如下更改函数签名:
public static IEnumerable<IDataRecord> GetGeneralInformation ( int RecID )
using ( var reader = cmd.ExecuteReader() )
{
while ( reader.Read() )
{
yield return reader;
}
}
int RecID = 12345;
string result = GetGeneralInformation(RecID).First()["Status"].ToString();
最后一部分“我如何从中阅读?”可能如下所示:
public static IEnumerable<IDataRecord> GetGeneralInformation ( int RecID )
using ( var reader = cmd.ExecuteReader() )
{
while ( reader.Read() )
{
yield return reader;
}
}
int RecID = 12345;
string result = GetGeneralInformation(RecID).First()["Status"].ToString();
根据定义,using
语句应该在调用对象后处理该对象
因此,在返回数据读取器后,它将被处理。问题是您正在方法中创建数据库连接
如果要在多个方法之间共享数据库资源,请将SqlConnection
移出此范围
这样,您可以从该函数返回读取器,读取器将保持不变
另外,不要在这个函数中.Read()
,只需返回对象。将连接字符串添加到app.config或web.config中的AppSettings部分
public string GetSqlConnection()
{
return System.Configuration.ConfigurationManager.AppSettings["SqlConnectionString"];
}
//函数返回SqlDataReader结果
public SqlDataReader executeReader(string sql, SqlParameter[] parameters=null)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = GetSqlConnection();
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
if (parameters != null)
{
cmd.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter p in parameters)
{
cmd.Parameters.Add(p);
}
}
else
{
cmd.CommandType = CommandType.Text;
}
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
}
要使用该功能,请执行以下操作:
string query = @"SELECT cs.Status, cs.Completed
FROM NC_Steps s
INNER JOIN NC_ClientSteps cs
ON cs.RecID = s.RecID
WHERE cs.ClientID = 162
AND s.RecID = @value";
//you can add more parameters by adding commas
var parameters = new SqlParameter[] {
new SqlParameter("@value", RecID )
};
SqlDataReader dr = executeReader(query, parameters);
while (dr.Read())
{
//fill your controls with data
}
dr.Close();
我认为值得一提。一个非常简单且易于使用的解决方案。为什么您不能像其他SqlDataReader一样阅读它?它失败了吗?如果是这样,那是因为您使用了语句。您正在使用读卡器之前关闭连接。您可以返回从读卡器填充的对象。你还没有说什么不起作用。@JamesWilson:我会重构它-将读取器“泄漏”到另一个方法(即使你能使它起作用)不是一个好的设计,只返回结果。我根本不会直接使用ADO.NET。我会使用实体框架或其他抽象层。我也会在一个单独的数据访问层类库中完成。您不应该在网页中直接访问数据(尽管我有时会对数据源控件进行例外)。@BrokenGlass-不喜欢使用列表保存数据库中的数据。。。他们忽略了使用datareader vs datatable/dataset的全部意义,即一次只在RAM中保存一条记录。您能帮我理解IEnumerable和yield的作用吗?如果没有,我可以查一下,不管怎样我都很感激你的答案。@BrokenGlass-试试看,效果很好。代码在后台被“提升”到一个单独的类中,直到枚举之后才到达dispose。@JamesWilson yield关键字创建了一个所谓的“迭代器”。它是一个知道如何在某种集合上循环的对象。IEnumerable是描述SqlDataReader重要部分的另一种方式。你可以在foreach(;)循环中使用它。然后你需要一种方法来解释它。。。但现在你有了一个全新的问题。@James:这就是我害怕的。从using语句返回时,读取器关闭。初始化一个自定义对象,如下面的回答所示:你在说什么?你不需要收益。去试试看。它可能不起作用,但肯定会编译。