无法将“System.Data.Common.DataRecordInternal”类型的对象转换为“System.Data.DataRowView”类型

问题描述 投票:0回答:1

我正在尝试使用中继器检索所有订单数据。 因此,我面临这个问题,但我以前从未发生过这种错误,因为它可以照常工作。

我的代码:

protected void OrderRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        //Assign status to page variable
        status = (Label)e.Item.FindControl("lblStatus");


        // Get the current order's data
        **DataRowView orderData = (DataRowView)e.Item.DataItem;**
        int orderID = orderData.Row.Field<int>("OrderID");

        // Filter the DataTable to get items for the current order
        DataTable itemsForOrder = ((DataView)TrackingSource.Select(DataSourceSelectArguments.Empty))
            .Table
            .Select($"OrderID= {orderID}")
            .OrderByDescending(x => x.Field<DateTime>("OrderDate"))
            .CopyToDataTable();
        itemsForOrder.DefaultView.Sort = "OrderDate DESC";

        CalculateEstimatedShippingDate(e.Item);
    }
    else
    {
        lblFail.Text = "You have no purchased records.";
    }
}

来源错误: DataRowView orderData = (DataRowView)e.Item.DataItem;

enter image description here

我认为,由于我使用的是 Visual Studio 2022,因此在编译过程中可能会出现一些错误。它可能会关闭整个窗口并再次打开它。这样就可以正常运行了。这是我的期望。谢谢你。

c# asp.net visual-studio-2022
1个回答
0
投票

我应该指出,只有在数据绑定事件期间,数据源项(行)才可用。这当然意味着即使未包含在标记中的列(在本例中为转发器)也可以自由使用和获取。但是,一旦数据绑定完成,数据项(行项)就会超出范围。

因此,请记住,要使上述工作正常进行,您提供给 GridView、ListView 或在本例中为 Repeater 的数据必须是 IEnumerable 数据列表。

这意味着,如果您使用阅读器向控件提供数据,那么 Repeater、ListView 等将起作用,但如果您尝试获取用于绑定的数据行,则它们将不起作用。

所以,拿这个简单的中继器:

    <asp:Repeater ID="Repeater1" runat="server" 
        OnItemDataBound="Repeater1_ItemDataBound">
        <ItemTemplate>
            <h4 id="myH3" runat="server"><%# Eval("HotelName") %> </h4>
            <br />
            <hr />
        </ItemTemplate>
    </asp:Repeater>

以及加载此中继器的代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();
    }

    void LoadData()
    {

        string strSQL = 
            @"SELECT * FROM tblHotelsA
             ORDER BY HotelName";

        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            using (SqlCommand cmdSQL = new SqlCommand(strSQL,conn))
            {
                conn.Open();
                Repeater1.DataSource = cmdSQL.ExecuteReader();
                Repeater1.DataBind();
            }
        }

    }

    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {

        // if active column = true, highligt in blue

        if ((e.Item.ItemType == ListItemType.Item) ||
            (e.Item.ItemType == ListItemType.AlternatingItem))
        {
            DataRowView MyDataRow = (DataRowView)e.Item.DataItem;

            if ((bool)MyDataRow["Active"] == true)
            {

                HtmlGenericControl H3 = (HtmlGenericControl)e.Item.FindControl("myH3");
                H3.Style.Add("background-color", "skyblue");


            }
        }
    }

现在,如果我们不尝试使用上面的代码就可以工作:

   DataRowView MyDataRow = (DataRowView)e.Item.DataItem;

因此,为了使 e.Item.DataItem 合法,控件的数据源必须是 IEnumerable,而阅读器则不是。那么,是否可以将 GridView、Repeater 等与非 IEnumerable 的数据源(例如数据转发器)绑定?

是的,你可以!但是,如果这不允许使用 e.Item.DataItem。

因此,为了使上述代码正常工作,我们必须向数据绑定控件提供一个 IEnumberale 列表。

因此,这段代码现在可以工作了:

    void LoadData()
    {

        string strSQL = 
            @"SELECT * FROM tblHotelsA
             ORDER BY HotelName";

        DataTable dtHotels = new DataTable();

        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            using (SqlCommand cmdSQL = new SqlCommand(strSQL,conn))
            {
                conn.Open();
                dtHotels.Load(cmdSQL.ExecuteReader());  
            }
        }

        Repeater1.DataSource = dtHotels;
        Repeater1.DataBind();

    }

结果现在是这样的:

因此,如果我们不使用 e.Item.DataItem,第一个代码示例将起作用,因为您可以将此类数据感知控件提供给中继器。

但是,当使用 e.Item.DataItem 时,数据源不能是“读取器”,因为它不会生成 IEnumerable 列表 - 允许重复使用每一行的列表,而不是一次逐行读取的读取器使用超出范围。

您没有显示加载中继器数据源的代码,但一个常见的问题是向读取器提供数据控件可以工作,但如果您尝试在行数据绑定中使用 e.Item.DataItem,则它不起作用活动。

所以,对于上面的代码

© www.soinside.com 2019 - 2024. All rights reserved.