替换 DataReader 数据
Replace DataReader data
我正在开发 ASP.Net Web 窗体 Application.Currently SqlDataReaders 直接绑定到两个网格视图。我需要在将数据集绑定到网格视图之前更改数据集。有两个数据集来自存储过程(两个 select 查询)。在绑定到网格之前,我需要编辑它们并替换一些数据。实现此目的的最佳方法是什么?
private void BindTable()
{
LiteralMessage.Text = "";
RecentLiteralMessage.Text = "";
ErrorLiteralMessege.Text = "";
var isStandbySelected = SelectedDatabase.SelectedValue == "stats";
using (var db = new Database(isStandbySelected))
{
try
{
//db.BeginTransaction(IsolationLevel.Snapshot);
db.BeginTransaction(); //Need a transaction block to stop from closing connection
db.StoredProcedure = "dbo.NewExportList";
if (!string.IsNullOrEmpty(TextBoxNameFilter.Text))
db.AddParameter("@nameFilter", TextBoxNameFilter.Text);
db.AddParameter("@excludedExports", CheckBoxExcludedExports.Checked);
db.AddParameter("@RunOnReportingServer", SelectedDatabase.SelectedValue == "stats" );
if(CheckBoxRecentlyRun.Checked)
db.AddParameter("@recentExports", true);
System.Data.SqlClient.SqlDataReader reader = db.GetDataReader();
GridViewExports.DataSource = reader;
GridViewExports.DataBind();
if (GridViewExports.Rows.Count > 0)
{
GridViewExports.Visible = true;
}
else
{
GridViewExports.Visible = false;
LiteralMessage.Text = "No Results";
}
GridViewRecentExports.DataSource = null; //clear any exsisting data
if (reader.NextResult()) //Get the second data set if any
{
GridViewRecentExports.DataSource = reader;
}
GridViewRecentExports.DataBind();
if (GridViewRecentExports.Rows.Count > 0)
{
GridViewRecentExports.Visible = true;
}
else
{
GridViewRecentExports.Visible = false;
RecentLiteralMessage.Text = "No Results";
}
db.CloseConnection();
//db.CommitTransaction();
}
catch (Exception ex)
{
}
}
好的,这里有两种常用的方法。
首先,让我们拿一个示例 GV,并通过这里的两个常见方法来工作。
我们的简单标记:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Nights" HeaderText="Nights" ItemStyle-HorizontalAlign="Center" />
<asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:c2}"
ItemStyle-HorizontalAlign="Right" />
</Columns>
</asp:GridView>
好的,我们要加载的代码:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn)) {
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
好的,我们现在有这个:
所以,在上面,我们说要显示每行预订的总价。
所以,让我们在这里使用“通用”方法。我们首先将我们的额外控件添加到网格视图。让我们使用平面简文本框:
例如:这个:
<asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:c2}"
ItemStyle-HorizontalAlign="Right" />
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="lblTotal" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
所以,我们刚刚给 gv 添加了一个标签。
因此,我们使用的事件是行数据绑定事件。这甚至很棒,因为它为我们提供了一个数据行和一个网格视图行。此事件也非常适合更改行或文本框的颜色,当然还可以进行一些计算或设置 un-bound 控件的值 - 例如我们的标签
所以,现在在我们的行数据绑定事件中,我们可以这样做:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView gData = (DataRowView)e.Row.DataItem;
Label lblTotal = e.Row.FindControl("lblTotal") as Label;
decimal MyPrice = (int)gData["Nights"] * (decimal)gData["Price"];
lblTotal.Text = string.Format("{0:c2}", MyPrice);
}
}
现在我们的腰带是这样的:
好的,以上是常用的做法
然而,一个有趣的方法?
一旦您填写了数据 table,您就可以自由地处理该 table,甚至包括向 table 添加新列!!!
所以,让我们转储(删除)我们的数据绑定行事件。
让我们更改标签以使用来自 table 的绑定数据。所以,我们的标记现在是:
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="lblTotal" runat="server"
Text = '<%# string.Format("{0:c2}", Eval("MyTotal")) %>'
></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
现在,我们在数据 table 中没有名为 MyTotal 的列,对吗?
但是,我们可以在从查询或存储过程中获取 table 之后添加 table.
所以,我们的网格加载代码现在变成了这样:
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn)) {
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
rstData.Columns.Add("MyTotal", typeof(decimal));
foreach (DataRow MyRow in rstData.Rows)
{
MyRow["MyTotal"] = (int)MyRow["Nights"] * (decimal)MyRow["Price"];
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
请注意我们是如何添加一个新列,然后执行 table 流程循环来设置该值的。因此GV的结果是一样的。
最后一点?
很少有人意识到数据 table 支持表达式!!!
当您修改值等时,更新会自动进行。那么,代替上面的行处理循环?我们实际上可以这样做:
DataColumn MyCol = new DataColumn("MyTotal", typeof(decimal));
MyCol.Expression = "[Nights] * [Price]";
rstData.Columns.Add(MyCol);
GridView1.DataSource = rstData;
GridView1.DataBind();
所以,在大多数情况下,我经常只使用行数据绑定。而且这个事件很好,因为你不写循环,对于条件格式,比如行颜色变化,或者 column/cell 颜色格式等,或者新文本框的新设置?行数据绑定很好。
但是,您也可以如前所述,添加列,然后循环 + 处理数据 table,您甚至可以添加基于其他列的表达式的列。然后您将更新后的 pre-processed table 正常发送到 gridview。
另请注意,当我使用查询时,存储过程的工作方式相同:
例如:
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("MyStoreProcedure", conn)) {
cmdSQL.CommandType = CommandType.StoredProcedure;
cmdSQL.Parameters.Add("@Active", SqlDbType.Bit).Value = 1;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
DataColumn MyCol = new DataColumn("MyTotal", typeof(decimal));
MyCol.Expression = "[Nights] * [Price]";
rstData.Columns.Add(MyCol);
GridView1.DataSource = rstData;
GridView1.DataBind();
我正在开发 ASP.Net Web 窗体 Application.Currently SqlDataReaders 直接绑定到两个网格视图。我需要在将数据集绑定到网格视图之前更改数据集。有两个数据集来自存储过程(两个 select 查询)。在绑定到网格之前,我需要编辑它们并替换一些数据。实现此目的的最佳方法是什么?
private void BindTable()
{
LiteralMessage.Text = "";
RecentLiteralMessage.Text = "";
ErrorLiteralMessege.Text = "";
var isStandbySelected = SelectedDatabase.SelectedValue == "stats";
using (var db = new Database(isStandbySelected))
{
try
{
//db.BeginTransaction(IsolationLevel.Snapshot);
db.BeginTransaction(); //Need a transaction block to stop from closing connection
db.StoredProcedure = "dbo.NewExportList";
if (!string.IsNullOrEmpty(TextBoxNameFilter.Text))
db.AddParameter("@nameFilter", TextBoxNameFilter.Text);
db.AddParameter("@excludedExports", CheckBoxExcludedExports.Checked);
db.AddParameter("@RunOnReportingServer", SelectedDatabase.SelectedValue == "stats" );
if(CheckBoxRecentlyRun.Checked)
db.AddParameter("@recentExports", true);
System.Data.SqlClient.SqlDataReader reader = db.GetDataReader();
GridViewExports.DataSource = reader;
GridViewExports.DataBind();
if (GridViewExports.Rows.Count > 0)
{
GridViewExports.Visible = true;
}
else
{
GridViewExports.Visible = false;
LiteralMessage.Text = "No Results";
}
GridViewRecentExports.DataSource = null; //clear any exsisting data
if (reader.NextResult()) //Get the second data set if any
{
GridViewRecentExports.DataSource = reader;
}
GridViewRecentExports.DataBind();
if (GridViewRecentExports.Rows.Count > 0)
{
GridViewRecentExports.Visible = true;
}
else
{
GridViewRecentExports.Visible = false;
RecentLiteralMessage.Text = "No Results";
}
db.CloseConnection();
//db.CommitTransaction();
}
catch (Exception ex)
{
}
}
好的,这里有两种常用的方法。
首先,让我们拿一个示例 GV,并通过这里的两个常见方法来工作。
我们的简单标记:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Nights" HeaderText="Nights" ItemStyle-HorizontalAlign="Center" />
<asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:c2}"
ItemStyle-HorizontalAlign="Right" />
</Columns>
</asp:GridView>
好的,我们要加载的代码:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn)) {
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
好的,我们现在有这个:
所以,在上面,我们说要显示每行预订的总价。
所以,让我们在这里使用“通用”方法。我们首先将我们的额外控件添加到网格视图。让我们使用平面简文本框:
例如:这个:
<asp:BoundField DataField="Price" HeaderText="Price" DataFormatString="{0:c2}"
ItemStyle-HorizontalAlign="Right" />
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="lblTotal" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
所以,我们刚刚给 gv 添加了一个标签。
因此,我们使用的事件是行数据绑定事件。这甚至很棒,因为它为我们提供了一个数据行和一个网格视图行。此事件也非常适合更改行或文本框的颜色,当然还可以进行一些计算或设置 un-bound 控件的值 - 例如我们的标签
所以,现在在我们的行数据绑定事件中,我们可以这样做:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView gData = (DataRowView)e.Row.DataItem;
Label lblTotal = e.Row.FindControl("lblTotal") as Label;
decimal MyPrice = (int)gData["Nights"] * (decimal)gData["Price"];
lblTotal.Text = string.Format("{0:c2}", MyPrice);
}
}
现在我们的腰带是这样的:
好的,以上是常用的做法
然而,一个有趣的方法?
一旦您填写了数据 table,您就可以自由地处理该 table,甚至包括向 table 添加新列!!!
所以,让我们转储(删除)我们的数据绑定行事件。
让我们更改标签以使用来自 table 的绑定数据。所以,我们的标记现在是:
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="lblTotal" runat="server"
Text = '<%# string.Format("{0:c2}", Eval("MyTotal")) %>'
></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
现在,我们在数据 table 中没有名为 MyTotal 的列,对吗?
但是,我们可以在从查询或存储过程中获取 table 之后添加 table.
所以,我们的网格加载代码现在变成了这样:
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn)) {
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
rstData.Columns.Add("MyTotal", typeof(decimal));
foreach (DataRow MyRow in rstData.Rows)
{
MyRow["MyTotal"] = (int)MyRow["Nights"] * (decimal)MyRow["Price"];
}
GridView1.DataSource = rstData;
GridView1.DataBind();
}
请注意我们是如何添加一个新列,然后执行 table 流程循环来设置该值的。因此GV的结果是一样的。
最后一点?
很少有人意识到数据 table 支持表达式!!! 当您修改值等时,更新会自动进行。那么,代替上面的行处理循环?我们实际上可以这样做:
DataColumn MyCol = new DataColumn("MyTotal", typeof(decimal));
MyCol.Expression = "[Nights] * [Price]";
rstData.Columns.Add(MyCol);
GridView1.DataSource = rstData;
GridView1.DataBind();
所以,在大多数情况下,我经常只使用行数据绑定。而且这个事件很好,因为你不写循环,对于条件格式,比如行颜色变化,或者 column/cell 颜色格式等,或者新文本框的新设置?行数据绑定很好。
但是,您也可以如前所述,添加列,然后循环 + 处理数据 table,您甚至可以添加基于其他列的表达式的列。然后您将更新后的 pre-processed table 正常发送到 gridview。
另请注意,当我使用查询时,存储过程的工作方式相同:
例如:
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("MyStoreProcedure", conn)) {
cmdSQL.CommandType = CommandType.StoredProcedure;
cmdSQL.Parameters.Add("@Active", SqlDbType.Bit).Value = 1;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
DataColumn MyCol = new DataColumn("MyTotal", typeof(decimal));
MyCol.Expression = "[Nights] * [Price]";
rstData.Columns.Add(MyCol);
GridView1.DataSource = rstData;
GridView1.DataBind();