Delen via


Batch-updates uitvoeren (C#)

door Scott Mitchell

PDF downloaden

Meer informatie over het maken van een volledig bewerkbare DataList waarin alle items zich in de bewerkingsmodus bevinden en waarvan de waarden kunnen worden opgeslagen door op een knop Alles bijwerken op de pagina te klikken.

Introductie

In de voorgaande zelfstudie hebben we onderzocht hoe u een DataList op itemniveau maakt. Net als bij de standaard bewerkbare GridView bevat elk item in de DataList een knop Bewerken die, wanneer erop wordt geklikt, het item bewerkbaar maakt. Hoewel deze bewerking op itemniveau goed werkt voor gegevens die slechts af en toe worden bijgewerkt, moet de gebruiker in bepaalde use-casescenario's veel records bewerken. Als een gebruiker tientallen records moet bewerken en gedwongen wordt op Bewerken te klikken, de wijzigingen aan te brengen en voor elke record op Bijwerken te klikken, kan de hoeveelheid klikken haar productiviteit belemmeren. In dergelijke situaties is het beter om een volledig bewerkbare DataList te bieden, een waar alle items zich in de bewerkingsmodus bevinden en waarvan de waarden kunnen worden bewerkt door op een knop Alles bijwerken op de pagina te klikken (zie afbeelding 1).

Elk item in een volledig bewerkbare DataList kan worden gewijzigd

Afbeelding 1: Elk item in een volledig bewerkbare DataList kan worden gewijzigd (klik om de volledige afbeelding weer te geven)

In deze zelfstudie bekijken we hoe gebruikers adresgegevens van leveranciers kunnen bijwerken met behulp van een volledig bewerkbare DataList.

Stap 1: De bewerkbare gebruikersinterface maken in de DataList s ItemTemplate

In de vorige zelfstudie, waarin we een standaard, bewerkbare DataList op itemniveau maken, hebben we twee sjablonen gebruikt:

  • ItemTemplate bevat de alleen-lezen gebruikersinterface (de Label Web-besturingselementen voor het weergeven van de naam en prijs van elk product).
  • EditItemTemplate bevat de gebruikersinterface van de bewerkingsmodus (de twee besturingselementen voor het tekstvakweb).

De eigenschap DataList EditItemIndex bepaalt wat DataListItem (indien aanwezig) wordt weergegeven met behulp van de EditItemTemplate. Met name de DataListItem waarvan de ItemIndex waarde overeenkomt met de DataList-eigenschap EditItemIndex, wordt weergegeven met behulp van de EditItemTemplate. Dit model werkt goed wanneer slechts één item tegelijk kan worden bewerkt, maar uit elkaar valt bij het maken van een volledig bewerkbare DataList.

Voor een volledig bewerkbare DataList willen we dat alle s worden weergegeven met behulp van de bewerkbare interfaceDataListItem. De eenvoudigste manier om dit te bereiken is het definiëren van de bewerkbare interface in de ItemTemplate. Voor het wijzigen van de adresgegevens van leveranciers bevat de bewerkbare interface de naam van de leverancier als tekst en vervolgens tekstvakken voor de adres-, plaats- en land-/regiowaarden.

Begin met het openen van de BatchUpdate.aspx pagina, voeg een DataList-besturingselement toe en stel de eigenschap in ID op Suppliers. Kies er vanuit de infotag van DataList voor om een nieuw ObjectDataSource-besturingselement met de naam SuppliersDataSourcetoe te voegen.

Een nieuwe ObjectDataSource maken met de naam SuppliersDataSource

Afbeelding 2: Een nieuwe ObjectDataSource maken met de naam SuppliersDataSource (klik om de afbeelding op volledige grootte weer te geven)

Configureer de ObjectDataSource om gegevens op te halen met behulp van de SuppliersBLL klassemethode GetSuppliers() (zie afbeelding 3). Net als bij de voorgaande zelfstudie, in plaats van de leveranciersgegevens bij te werken via ObjectDataSource, werken we rechtstreeks met de bedrijfslogicalaag. Stel de vervolgkeuzelijst daarom in op (Geen) op het tabblad UPDATE (zie afbeelding 4).

Leveranciersinformatie ophalen met behulp van de methode GetSuppliers()

Afbeelding 3: Leveranciersgegevens ophalen met behulp van de GetSuppliers() methode (klik om de afbeelding op volledige grootte weer te geven)

De Drop-Down lijst instellen op (Geen) op het tabblad BIJWERKEN

Afbeelding 4: De Drop-Down lijst instellen op (geen) op het tabblad BIJWERKEN (klik om de volledige afbeelding weer te geven)

Nadat de wizard is voltooid, genereert Visual Studio automatisch de DataList ItemTemplate om elk gegevensveld weer te geven dat wordt geretourneerd door de gegevensbron in een Label Web Control. We moeten deze sjabloon wijzigen zodat deze in plaats daarvan de bewerkingsinterface biedt. U kunt ItemTemplate aanpassen via de Designer met behulp van de optie Sjablonen aanpassen vanuit de smart tag van de DataList of rechtstreeks via de declaratieve syntaxis.

Neem even de tijd om een bewerkingsinterface te maken waarin de naam van de leverancier als tekst wordt weergegeven, maar tekstvakken bevat voor de adres-, plaats- en land-/regiowaarden van de leverancier. Nadat u deze wijzigingen hebt aangebracht, moet de declaratieve syntaxis van uw pagina er ongeveer als volgt uitzien:

<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
    DataSourceID="SuppliersDataSource">
    <ItemTemplate>
        <h4><asp:Label ID="CompanyNameLabel" runat="server"
            Text='<%# Eval("CompanyName") %>' /></h4>
        <table border="0">
            <tr>
                <td class="SupplierPropertyLabel">Address:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Address" runat="server"
                        Text='<%# Eval("Address") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">City:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="City" runat="server"
                        Text='<%# Eval("City") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">Country:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Country" runat="server"
                        Text='<%# Eval("Country") %>' />
                </td>
            </tr>
        </table>
        <br />
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

Opmerking

Net als bij de vorige zelfstudie moet de DataList in deze zelfstudie zijn weergavestatus ingeschakeld hebben.

In de ItemTemplate gebruik ik twee nieuwe CSS-klassen, SupplierPropertyLabel en SupplierPropertyValue, die zijn toegevoegd aan de Styles.css-klasse en geconfigureerd om dezelfde stijlinstellingen te gebruiken als de ProductPropertyLabel en ProductPropertyValue CSS-klassen.

.ProductPropertyLabel, .SupplierPropertyLabel
{
    font-weight: bold;
    text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
    padding-right: 35px;
}

Nadat u deze wijzigingen hebt aangebracht, gaat u naar deze pagina via een browser. Zoals in afbeelding 5 wordt weergegeven, geeft elk DataList-item de naam van de leverancier weer als tekst en gebruikt tekstvakken om het adres, de plaats en het land/de regio weer te geven.

Elke leverancier in de DataList kan worden bewerkt

Afbeelding 5: Elke leverancier in de DataList kan worden bewerkt (klik om de afbeelding op volledige grootte weer te geven)

Stap 2: een knop Alles bijwerken toevoegen

Hoewel elke leverancier in afbeelding 5 de velden adres, plaats en land/regio heeft die worden weergegeven in een tekstvak, is er momenteel geen knop Bijwerken beschikbaar. In plaats van een knop Bijwerken per item, is er bij volledig bewerkbare DataLists meestal één knop Alles bijwerken op de pagina. Wanneer hierop wordt geklikt, worden alle records in de DataList bijgewerkt. Voor deze zelfstudie gaan we twee knoppen Alles bijwerken toevoegen: een boven aan de pagina en een aan de onderkant (hoewel het klikken op een van de knoppen hetzelfde effect heeft).

Voeg eerst een Webknop toe boven de DataList en stel de eigenschap van ID in op UpdateAll1. Voeg vervolgens het tweede webknopbesturingselement onder de DataList toe en stel deze in op ID. Stel de Text eigenschappen voor de twee knoppen in op Update All. Maak ten slotte gebeurtenis-handlers voor beide gebeurtenissen van de knoppen Click. In plaats van de updatelogica in elk van de gebeurtenis-handlers te dupliceren, kunt u die logica herstructureren naar een derde methode, UpdateAllSupplierAddresseswaarbij de gebeurtenis-handlers deze derde methode gewoon aanroepen.

protected void UpdateAll1_Click(object sender, EventArgs e)
{
    UpdateAllSupplierAddresses();
}
protected void UpdateAll2_Click(object sender, EventArgs e)
{
    UpdateAllSupplierAddresses();
}
private void UpdateAllSupplierAddresses()
{
    // TODO: Write code to update _all_ of the supplier addresses in the DataList
}

In afbeelding 6 ziet u de pagina nadat de knoppen Alles bijwerken zijn toegevoegd.

Twee 'Update All'-knoppen zijn aan de pagina toegevoegd

Afbeelding 6: Er zijn twee knoppen voor het bijwerken van alle knoppen toegevoegd aan de pagina (klik om de afbeelding op volledige grootte weer te geven)

Stap 3: alle adresgegevens van leveranciers bijwerken

Met alle datalist-items die de bewerkingsinterface weergeven en met de toevoeging van de knoppen Alles bijwerken, hoeft u alleen maar de code te schrijven om de batch-update uit te voeren. We moeten met name de DataList-items doorlopen en de SuppliersBLL klassemethode UpdateSupplierAddress voor elk item aanroepen.

De verzameling DataListItem exemplaren die de DataList vormen, kan worden benaderd via de eigenschap van de DataList Items. Met een verwijzing naar een DataListItem kunnen we de bijbehorende SupplierID uit de DataKeys-verzameling ophalen en programmatisch verwijzen naar de webbesturingselementen van het tekstvak binnen de ItemTemplate, zoals de volgende code illustreert:

private void UpdateAllSupplierAddresses()
{
    // Create an instance of the SuppliersBLL class
    SuppliersBLL suppliersAPI = new SuppliersBLL();
    // Iterate through the DataList's items
    foreach (DataListItem item in Suppliers.Items)
    {
        // Get the supplierID from the DataKeys collection
        int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);
        // Read in the user-entered values
        TextBox address = (TextBox)item.FindControl("Address");
        TextBox city = (TextBox)item.FindControl("City");
        TextBox country = (TextBox)item.FindControl("Country");
        string addressValue = null, cityValue = null, countryValue = null;
        if (address.Text.Trim().Length > 0)
            addressValue = address.Text.Trim();
        if (city.Text.Trim().Length > 0)
              cityValue = city.Text.Trim();
        if (country.Text.Trim().Length > 0)
            countryValue = country.Text.Trim();
        // Call the SuppliersBLL class's UpdateSupplierAddress method
        suppliersAPI.UpdateSupplierAddress
            (supplierID, addressValue, cityValue, countryValue);
    }
}

Wanneer de gebruiker op een van de knoppen Alles bijwerken klikt, doorloopt de UpdateAllSupplierAddresses methode elk DataListItem in de Suppliers DataList en roept de SuppliersBLL klasse's UpdateSupplierAddress methode aan, waarbij de bijbehorende waarden worden doorgegeven. Een niet-opgegeven waarde voor adres, plaats of land/regio wordt een waarde van Nothing naar UpdateSupplierAddress (in plaats van een lege tekenreeks), wat resulteert in een database NULL voor de onderliggende recordvelden.

Opmerking

Als uitbreiding wilt u mogelijk een statuslabelweb besturingselement toevoegen aan de pagina die een bevestigingsbericht geeft nadat de batch-update is uitgevoerd.

Alleen de adressen bijwerken die zijn gewijzigd

Het batch-updatealgoritme dat voor deze zelfstudie wordt gebruikt, roept de UpdateSupplierAddress methode aan voor elke leverancier in de DataList, ongeacht of de adresgegevens zijn gewijzigd. Hoewel dergelijke blinde updates meestal geen prestatieprobleem zijn, kunnen ze leiden tot overbodige records als u wijzigingen in de databasetabel controleert. Als u bijvoorbeeld triggers gebruikt om alle UPDATE s in de Suppliers tabel op te nemen in een controletabel, wordt elke keer dat een gebruiker op de knop Alles bijwerken klikt een nieuwe controlerecord gemaakt voor elke leverancier in het systeem, ongeacht of de gebruiker wijzigingen heeft aangebracht.

De klassen ADO.NET DataTable en DataAdapter zijn ontworpen ter ondersteuning van batchupdates waarbij alleen gewijzigde, verwijderde en nieuwe records tot databasecommunicatie leidt. Elke rij in de gegevenstabel heeft een RowState eigenschap die aangeeft of de rij is toegevoegd aan de gegevenstabel, ervan is verwijderd, gewijzigd of ongewijzigd blijft. Wanneer een gegevenstabel in eerste instantie is ingevuld, worden alle rijen als ongewijzigd gemarkeerd. Als u de waarde van een van de rijkolommen wijzigt, wordt de rij gemarkeerd als gewijzigd.

In de SuppliersBLL klasse werken we de opgegeven adresgegevens van de leverancier bij door eerst in de record van één leverancier te lezen in een SuppliersDataTable en vervolgens de Address, Cityen Country kolomwaarden in te stellen met behulp van de volgende code:

public bool UpdateSupplierAddress
    (int supplierID, string address, string city, string country)
{
    Northwind.SuppliersDataTable suppliers =
        Adapter.GetSupplierBySupplierID(supplierID);
    if (suppliers.Count == 0)
        // no matching record found, return false
        return false;
    else
    {
        Northwind.SuppliersRow supplier = suppliers[0];
        if (address == null)
            supplier.SetAddressNull();
        else
            supplier.Address = address;
        if (city == null)
            supplier.SetCityNull();
        else
            supplier.City = city;
        if (country == null)
            supplier.SetCountryNull();
        else
            supplier.Country = country;
        // Update the supplier Address-related information
        int rowsAffected = Adapter.Update(supplier);
        // Return true if precisely one row was updated,
        // otherwise false
        return rowsAffected == 1;
    }
}

Deze code kent zonder onderscheid de doorgegeven adres-, plaats- en land-/regiowaarden toe aan de SuppliersRow binnen de SuppliersDataTable, ongeacht of de waarden zijn gewijzigd. Deze wijzigingen zorgen ervoor dat de SuppliersRow eigenschap s RowState wordt gemarkeerd als gewijzigd. Wanneer de methode Data Access Layer Update wordt aangeroepen, ziet deze dat de SupplierRow methode is gewijzigd en daarom een UPDATE opdracht naar de database wordt verzonden.

Stel dat we code aan deze methode hebben toegevoegd om alleen de doorgegeven adres-, plaats- en land-/regiowaarden toe te wijzen als deze verschillen van de SuppliersRow bestaande waarden. In het geval dat het adres, de plaats en het land/de regio hetzelfde zijn als de bestaande gegevens, worden er geen wijzigingen aangebracht en worden de SupplierRow s RowState gemarkeerd als ongewijzigd. Het nettoresultaat is dat wanneer de DAL-methode Update wordt aangeroepen, er geen database-aanroep wordt uitgevoerd omdat de SuppliersRow methode niet is gewijzigd.

Als u deze wijziging wilt uitvoeren, vervangt u de instructies waarmee de doorgegeven adres-, plaats- en land-/regiowaarden blind worden toegewezen door de volgende code:

// Only assign the values to the SupplierRow's column values if they differ
if (address == null && !supplier.IsAddressNull())
    supplier.SetAddressNull();
else if ((address != null && supplier.IsAddressNull()) ||
         (!supplier.IsAddressNull() &&
         string.Compare(supplier.Address, address) != 0))
    supplier.Address = address;
if (city == null && !supplier.IsCityNull())
    supplier.SetCityNull();
else if ((city != null && supplier.IsCityNull()) ||
         (!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0))
    supplier.City = city;
if (country == null && !supplier.IsCountryNull())
    supplier.SetCountryNull();
else if ((country != null && supplier.IsCountryNull()) ||
         (!supplier.IsCountryNull() &&
         string.Compare(supplier.Country, country) != 0))
    supplier.Country = country;

Met deze toegevoegde code verzendt de DAL-methode Update een UPDATE instructie naar de database voor alleen de records waarvan de adresgerelateerde waarden zijn gewijzigd.

We kunnen ook bijhouden of er verschillen zijn tussen de doorgegeven adresvelden en de databasegegevens en, als er geen zijn, de aanroep naar de DAL-methode Update overslaan. Deze aanpak werkt goed als u de directe db-methode gebruikt, omdat de directe db-methode niet aan een SuppliersRow exemplaar wordt doorgegeven waarvan RowState kan worden gecontroleerd om te bepalen of een databaseaanroep daadwerkelijk nodig is.

Opmerking

Telkens wanneer de UpdateSupplierAddress methode wordt aangeroepen, wordt er een aanroep naar de database uitgevoerd om informatie over de bijgewerkte record op te halen. Als er vervolgens wijzigingen in de gegevens zijn, wordt een andere aanroep naar de database gemaakt om de tabelrij bij te werken. Deze werkstroom kan worden geoptimaliseerd door een overbelasting van een UpdateSupplierAddress methode te maken die een EmployeesDataTable exemplaar accepteert dat alle wijzigingen van de BatchUpdate.aspx pagina bevat. Vervolgens kan er één aanroep naar de database worden uitgevoerd om alle records uit de Suppliers tabel op te halen. De twee resultatensets kunnen vervolgens worden geïnventariseerd en alleen de records waar wijzigingen zijn opgetreden, kunnen worden bijgewerkt.

Samenvatting

In deze zelfstudie hebben we gezien hoe u een volledig bewerkbare DataList maakt, zodat een gebruiker snel de adresgegevens voor meerdere leveranciers kan wijzigen. We zijn begonnen met het definiëren van de bewerkingsinterface van een tekstvakwebbesturing voor de adres-, plaats- en land-/regiowaarden van de leverancier in de DataList s ItemTemplate. Vervolgens hebben we Update All-knoppen toegevoegd boven en onder de DataList. Nadat een gebruiker zijn wijzigingen heeft aangebracht en op een van de knoppen Alles bijwerken heeft geklikt, worden de DataListItem s geïnventariseerd en wordt een aanroep naar de methode van de SuppliersBLL klasse UpdateSupplierAddress gemaakt.

Veel plezier met programmeren!

Over de auteur

Scott Mitchell, auteur van zeven ASP/ASP.NET-boeken en oprichter van 4GuysFromRolla.com, werkt sinds 1998 met Microsoft-webtechnologieën. Scott werkt als onafhankelijk consultant, trainer en schrijver. Zijn laatste boek is Sams Teach Yourself ASP.NET 2.0 in 24 uur. Hij kan worden bereikt op mitchell@4GuysFromRolla.com.

Speciale dank aan

Deze tutorialreeks is beoordeeld door veel behulpzame beoordelers. Hoofdbeoordelaars voor deze tutorial waren Zack Jones en Ken Pespisa. Bent u geïnteresseerd in het bekijken van mijn aanstaande MSDN-artikelen? Zo ja, laat iets van je horen via mitchell@4GuysFromRolla.com.