Одна веб-страница, LinqDataSource, GridView для редактирования нескольких таблиц данных - PullRequest
0 голосов
/ 16 августа 2011

Проблема в том, что - новое приложение, клиент хочет Linq, .NET 4.0, множество таблиц данных «категорий» и «типов» - простые таблицы данных, которые обычно представляют собой два поля: ID и имя (или описание)

Вместо создания веб-формы для редактирования каждой из этих таблиц данных - было бы неплохо, чтобы для их редактирования понадобилась только одна веб-страница, и вы просто выбираете таблицу данных, которую хотите редактировать. (Кстати - где «шаблонные наркоманы». Разве это не шаблон? Где шаблонный шаблон кода .NET для этого?)

Я играю с базой данных Northwinds. Я добавил таблицу с именем DropDownConfiguration:

USE [Northwind]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[DropDownConfiguration](
[DropDownConfigurationID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[TableName] [nvarchar](50) NOT NULL,
[PrimaryKeyName] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_DropDownConfiguration] PRIMARY KEY CLUSTERED 
(
[DropDownConfigurationID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Затем я заполнил эту таблицу данными следующими данными:

DropDownConfigurationID   Name         TableName    PrimaryKeyName
1                       Categories     Categories   CategoryID
2                       Regions         Regions RegionID

Веб-страница asp.net выглядит следующим образом:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="EditMultiTable.aspx.vb"
Inherits="EditMultiTable" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
    <asp:LinqDataSource ID="LinqDataSourceMultiTable" runat="server" ContextTypeName="DataClassesDataContext"
        EnableInsert="True" EnableUpdate="True" EntityTypeName="" TableName="Categories">
    </asp:LinqDataSource>
    <asp:DropDownList ID="ddlDropDownConfigurations" runat="server" AutoPostBack="True">
    </asp:DropDownList>
    <asp:GridView ID="GridViewMultiTable" runat="server" DataKeyNames="CategoryID" DataSourceID="LinqDataSourceMultiTable">
        <Columns>
            <asp:CommandField ShowEditButton="True" />
        </Columns>
    </asp:GridView>
</div>
</form>
</body>
</html>

Код выглядит следующим образом:

Option Explicit On
Option Strict On

Partial Class EditMultiTable
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    If Not Page.IsPostBack Then
        ' Tell the drop down what data tables we want to be able to edit
        myDropDownConfigurationList = GetDropDownConfigurations()
        ddlDropDownConfigurations.DataSource = myDropDownConfigurationList
        ddlDropDownConfigurations.DataTextField = "Name"
        ddlDropDownConfigurations.DataValueField = "DropDownConfigurationID"
        ddlDropDownConfigurations.DataBind()
    End If
End Sub

Protected Sub ddlDropDownConfigurations_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlDropDownConfigurations.SelectedIndexChanged
    Dim myDropDownConfiguration As DropDownConfiguration
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    If ddlDropDownConfigurations.SelectedIndex > -1 Then
        ' clear out the old data bindings between the LinqDataSource and the GridView
        GridViewMultiTable.DataSourceID = Nothing
        GridViewMultiTable.DataSource = Nothing
        GridViewMultiTable.DataKeyNames = Nothing
        GridViewMultiTable.DataMember = Nothing
        GridViewMultiTable.AutoGenerateColumns = False
        GridViewMultiTable.AutoGenerateEditButton = False
        GridViewMultiTable.DataBind()
        GridViewMultiTable.Columns.Clear()


        ' Set up the LinqDataSource for the new table
        myDropDownConfigurationList = GetDropDownConfigurations()
        myDropDownConfiguration = (From ddc In myDropDownConfigurationList Where ddc.DropDownConfigurationID = Long.Parse(ddlDropDownConfigurations.SelectedValue) Select ddc).FirstOrDefault()
        LinqDataSourceMultiTable.TableName = myDropDownConfiguration.TableName
        LinqDataSourceMultiTable.EntityTypeName = String.Empty
        LinqDataSourceMultiTable.EnableInsert = True
        LinqDataSourceMultiTable.EnableUpdate = True
        LinqDataSourceMultiTable.DataBind()

        ' bind the GridView to the LinqDataSource with the new data table
        GridViewMultiTable.DataSourceID = "LinqDataSourceMultiTable"
        GridViewMultiTable.DataKeyNames = New String() {myDropDownConfiguration.PrimaryKeyName}
        GridViewMultiTable.AutoGenerateColumns = True
        GridViewMultiTable.AutoGenerateEditButton = True
        GridViewMultiTable.DataBind()
    End If

End Sub

' Get my data table that lists the data tables that I want to configure
Function GetDropDownConfigurations() As List(Of DropDownConfiguration)
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    Using myDataClassesDataContext As New DataClassesDataContext
        myDropDownConfigurationList = (From ddc In myDataClassesDataContext.DropDownConfigurations Select ddc).ToList()
    End Using
    Return myDropDownConfigurationList
End Function
End Class

Моя проблема в том, что LinqDataSource или GridView не очищаются. Это своего рода использование половины одной таблицы данных и половины другой. Вот почему в моем коде - я попытался очистить LinqDataSource и GridView всеми возможными способами. Если я запускаю программу, выбираю «Регионы» в выпадающем списке и затем пытаюсь отредактировать первый ряд «регионов», я получаю следующую ошибку:

Привязка данных: «Категория» не содержит свойства с именем «RegionID». Описание: во время выполнения текущего веб-запроса произошло необработанное исключение. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: System.Web.HttpException: DataBinding: «Категория» не содержит свойства с именем «RegionID».

Ответы [ 2 ]

1 голос
/ 16 августа 2011

Когда вы нажимаете «Изменить» в gridview, запускается событие Page_Load, и вы видите, что LinqDataSourceMultiTable.TableName - это «Категории», потому что это то, что вы в последний раз связали. Вам следует повторно связать свой источник данных, если вы хотите выполнить действия с данными, отображаемыми в gridview. Я считаю, что нет необходимости делать весь этот раздел очистки.

0 голосов
/ 17 августа 2011

Черт возьми. Проблема была настолько очевидна - мне стыдно это признать. Моя проблема заключалась в том, что я не делал стандартные обработчики событий gridview - при редактировании, при обновлении, при отмене редактирования. Разместим новый код для тех, кто хочет использовать этот код:

Option Explicit On
Option Strict On

Partial Class EditMultiTable
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    If Not Page.IsPostBack Then
        ' Tell the drop down what data tables we want to be able to edit
        myDropDownConfigurationList = GetDropDownConfigurations()
        ddlDropDownConfigurations.DataSource = myDropDownConfigurationList
        ddlDropDownConfigurations.DataTextField = "Name"
        ddlDropDownConfigurations.DataValueField = "DropDownConfigurationID"
        ddlDropDownConfigurations.DataBind()
    End If
End Sub

Protected Sub ddlDropDownConfigurations_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlDropDownConfigurations.SelectedIndexChanged
    If ddlDropDownConfigurations.SelectedIndex > -1 Then
        BindData()
    End If
End Sub

Sub BindData()
    Dim myDropDownConfiguration As DropDownConfiguration
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    ' Set up the LinqDataSource for the new table
    myDropDownConfigurationList = GetDropDownConfigurations()
    myDropDownConfiguration = (From ddc In myDropDownConfigurationList Where ddc.DropDownConfigurationID = Long.Parse(ddlDropDownConfigurations.SelectedValue) Select ddc).FirstOrDefault()
    LinqDataSourceMultiTable.TableName = myDropDownConfiguration.TableName

    ' bind the GridView to the LinqDataSource with the new data table
    GridViewMultiTable.DataKeyNames = New String() {myDropDownConfiguration.PrimaryKeyName}
    GridViewMultiTable.DataBind()
End Sub

' Get my data table that lists the data tables that I want to configure
Function GetDropDownConfigurations() As List(Of DropDownConfiguration)
    Dim myDropDownConfigurationList As List(Of DropDownConfiguration)

    Using myDataClassesDataContext As New DataClassesDataContext
        myDropDownConfigurationList = (From ddc In myDataClassesDataContext.DropDownConfigurations Select ddc).ToList()
    End Using
    Return myDropDownConfigurationList
End Function

Protected Sub GridViewMultiTable_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridViewMultiTable.RowEditing
    GridViewMultiTable.EditIndex = e.NewEditIndex
    BindData()
End Sub

Protected Sub GridViewMultiTable_RowCancelingEdit(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles GridViewMultiTable.RowCancelingEdit
    GridViewMultiTable.EditIndex = -1
    BindData()
End Sub

Protected Sub GridViewMultiTable_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridViewMultiTable.RowUpdating
    GridViewMultiTable.EditIndex = -1
    BindData()
End Sub

Конечный класс

...