Arbeiten mit berechneten Spalten (C#)
von Scott Mitchell
Beim Erstellen einer Datenbanktabelle können Sie mit Microsoft SQL Server eine berechnete Spalte definieren, deren Wert aus einem Ausdruck berechnet wird, der in der Regel auf andere Werte im selben Datenbankdatensatz verweist. Solche Werte sind in der Datenbank schreibgeschützt, was bei der Arbeit mit TableAdapters besondere Überlegungen erfordert. In diesem Lernprogramm erfahren Sie, wie Sie die Herausforderungen von berechneten Spalten bewältigen können.
Einführung
Microsoft SQL Server ermöglicht berechnete Spalten, bei denen es sich um Spalten handelt, deren Werte aus einem Ausdruck berechnet werden, der in der Regel auf die Werte aus anderen Spalten in derselben Tabelle verweist. Ein Datenmodell für die Zeitverfolgung kann beispielsweise eine Tabelle ServiceLog
mit Spalten wie ServicePerformed
, , EmployeeID
, Rate
und , u Duration
. a. enthalten. Während der fällige Betrag pro Dienstelement (wobei die Rate mit der Dauer multipliziert wird) über eine Webseite oder eine andere programmgesteuerte Schnittstelle berechnet werden kann, kann es praktisch sein, eine Spalte in die Tabelle AmountDue
einzuschließen, die ServiceLog
diese Informationen gemeldet hat. Diese Spalte könnte als normale Spalte erstellt werden, muss aber bei jeder Änderung der Rate
Duration
Spaltenwerte aktualisiert werden. Ein besserer Ansatz wäre, die AmountDue
Spalte mithilfe des Ausdrucks Rate * Duration
zu einer berechneten Spalte zu machen. Dies würde dazu führen, dass SQL Server den AmountDue
Spaltenwert automatisch berechnet, wenn in einer Abfrage darauf verwiesen wurde.
Da ein berechneter Spaltenwert durch einen Ausdruck bestimmt wird, sind solche Spalten schreibgeschützt und können daher keine Werte enthalten, die ihnen in INSERT
oder UPDATE
Anweisungen zugewiesen werden. Wenn berechnete Spalten jedoch Teil der Hauptabfrage für einen TableAdapter sind, der Ad-hoc-SQL-Anweisungen verwendet, werden sie automatisch in die automatisch generierten INSERT
und UPDATE
Anweisungen einbezogen. Folglich müssen die TableAdapter-Elemente INSERT
und -Abfragen und UPDATE
InsertCommand
UpdateCommand
-Eigenschaften aktualisiert werden, um Verweise auf berechnete Spalten zu entfernen.
Eine Herausforderung bei der Verwendung berechneter Spalten mit einem TableAdapter, der Ad-hoc-SQL-Anweisungen verwendet, besteht darin, dass die TableAdapter-Elemente INSERT
und UPDATE
-Abfragen bei Abschluss des TableAdapter-Konfigurations-Assistenten automatisch neu generiert werden. Daher werden die berechneten Spalten, die manuell aus den INSERT
und UPDATE
Abfragen entfernt werden, wieder angezeigt, wenn der Assistent erneut ausgeführt wird. Obwohl TableAdapters, die gespeicherte Prozeduren verwenden, nicht unter dieser Sprödigkeit leiden, haben sie ihre eigenen Eigenheiten, die wir in Schritt 3 behandeln werden.
In diesem Lernprogramm fügen wir der Tabelle in der Suppliers
Northwind-Datenbank eine berechnete Spalte hinzu und erstellen dann einen entsprechenden TableAdapter für die Arbeit mit dieser Tabelle und deren berechnete Spalte. Wir verwenden gespeicherte Prozeduren anstelle von Ad-hoc-SQL-Anweisungen, damit unsere Anpassungen beim Verwenden des TableAdapter-Konfigurations-Assistenten nicht verloren gehen.
Los geht's!
Schritt 1: Hinzufügen einer berechneten Spalte zurSuppliers
Tabelle
Die Northwind-Datenbank verfügt nicht über berechnete Spalten, daher müssen wir eines selbst hinzufügen. In diesem Lernprogramm fügen wir der Tabelle eine berechnete Spalte hinzu, die Suppliers
den Namen, den Titel und das Unternehmen zurückgibt, für das sie im folgenden Format arbeiten: ContactName
(ContactTitle
, CompanyName
).FullContactName
Diese berechnete Spalte kann in Berichten verwendet werden, wenn Informationen zu Lieferanten angezeigt werden.
Öffnen Sie zunächst die Suppliers
Tabellendefinition, indem Sie im Server-Explorer mit der rechten Maustaste auf die Suppliers
Tabelle klicken und im Kontextmenü "Tabellendefinition öffnen" auswählen. Dadurch werden die Spalten der Tabelle und deren Eigenschaften angezeigt, z. B. deren Datentyp, ob sie zulassen NULL
usw. Wenn Sie eine berechnete Spalte hinzufügen möchten, geben Sie zunächst den Namen der Spalte in die Tabellendefinition ein. Geben Sie als Nächstes ihren Ausdruck in das Textfeld (Formel) unter dem Abschnitt "Berechnete Spaltenspezifikation" in der Spalte Eigenschaftenfenster ein (siehe Abbildung 1). Benennen Sie die berechnete Spalte FullContactName
, und verwenden Sie den folgenden Ausdruck:
ContactName + ' (' + CASE WHEN ContactTitle IS NOT NULL THEN
ContactTitle + ', ' ELSE '' END + CompanyName + ')'
Beachten Sie, dass Zeichenfolgen mithilfe des +
Operators in SQL verkettet werden können. Die CASE
Anweisung kann wie eine Bedingung in einer herkömmlichen Programmiersprache verwendet werden. Im obigen Ausdruck kann die CASE
Anweisung wie folgt gelesen werden: Wenn ContactTitle
der Wert nicht NULL
ausgegeben wird, der ContactTitle
mit einem Komma verkettet ist, andernfalls wird nichts ausgegeben. Weitere Informationen zur Nützlichkeit der CASE
Anweisung finden Sie unter SQL-AnweisungenCASE
.
Hinweis
Statt hier eine CASE
Aussage zu verwenden, könnten wir alternativ verwendet ISNULL(ContactTitle, '')
werden. ISNULL(checkExpression, replacementValue)
gibt checkExpression zurück, wenn es nicht NULL ist, andernfalls wird replacementValue zurückgegeben. Zwar funktioniert dies ISNULL
CASE
in dieser Instanz, es gibt jedoch komplexere Szenarien, in denen die Flexibilität der CASE
Anweisung nicht abgeglichen ISNULL
werden kann.
Nachdem Sie diese berechnete Spalte hinzugefügt haben, sollte ihr Bildschirm wie der Screenshot in Abbildung 1 aussehen.
Abbildung 1: Hinzufügen einer berechneten Spalte namens FullContactName
" Suppliers
Tabelle" (Zum Anzeigen des Bilds mit voller Größe klicken)
Nachdem Sie die berechnete Spalte benannt und ihren Ausdruck eingegeben haben, speichern Sie die Änderungen in der Tabelle, indem Sie auf das Symbol "Speichern" auf der Symbolleiste klicken, indem Sie STRG+S drücken oder zum Menü "Datei" wechseln und "Speichern Suppliers
" auswählen.
Beim Speichern der Tabelle sollte der Server-Explorer aktualisiert werden, einschließlich der gerade hinzugefügten Spalte in der Spaltenliste der Suppliers
Tabelle. Darüber hinaus wird der in das Textfeld (Formel) eingegebene Ausdruck automatisch an einen entsprechenden Ausdruck angepasst, der unnötige Leerzeichen entfernt, Spaltennamen in eckige Klammern ([]
) einschließt und Klammern enthält, um die Reihenfolge der Vorgänge explizit anzuzeigen:
(((([ContactName]+' (')+case when [ContactTitle] IS NOT NULL
then [ContactTitle]+', ' else '' end)+[CompanyName])+')')
Weitere Informationen zu berechneten Spalten in Microsoft SQL Server finden Sie in der technischen Dokumentation. Sehen Sie sich außerdem die Vorgehensweise an: Angeben berechneter Spalten für eine schrittweise exemplarische Vorgehensweise zum Erstellen berechneter Spalten.
Hinweis
Berechnete Spalten werden standardmäßig nicht physisch in der Tabelle gespeichert, sondern bei jedem Verweis in einer Abfrage neu berechnet. Durch Aktivieren des Kontrollkästchens "Beibehalten" können Sie SQL Server jedoch anweisen, die berechnete Spalte in der Tabelle physisch zu speichern. Auf diese Weise kann ein Index in der berechneten Spalte erstellt werden, wodurch die Leistung von Abfragen verbessert werden kann, die den berechneten Spaltenwert in ihren WHERE
Klauseln verwenden. Weitere Informationen finden Sie unter Erstellen von Indizes für berechnete Spalten .
Schritt 2: Anzeigen der berechneten Spaltenwerte
Bevor wir mit der Arbeit mit der Datenzugriffsschicht beginnen, nehmen wir uns eine Minute Zeit, um die FullContactName
Werte anzuzeigen. Klicken Sie im Server-Explorer mit der rechten Maustaste auf den Suppliers
Tabellennamen, und wählen Sie im Kontextmenü "Neue Abfrage" aus. Dadurch wird ein Abfragefenster angezeigt, in dem wir aufgefordert werden, auszuwählen, welche Tabellen in die Abfrage einbezogen werden sollen. Fügen Sie die Suppliers
Tabelle hinzu, und klicken Sie auf "Schließen". Überprüfen Sie als Nächstes die CompanyName
Tabellen "Lieferanten" und ContactName
ContactTitle
FullContactName
"Spalten". Klicken Sie abschließend auf das rote Ausrufezeichensymbol in der Symbolleiste, um die Abfrage auszuführen und die Ergebnisse anzuzeigen.
Wie in Abbildung 2 dargestellt, sind die Ergebnisse enthalten FullContactName
, in denen die CompanyName
Spalten ContactName
und ContactTitle
das Format ldquo;ContactName
(ContactTitle
, CompanyName
) aufgeführt sind.
Abbildung 2: Verwendet FullContactName
das Format ContactName
(ContactTitle
, CompanyName
) (Klicken, um das Bild in voller Größe anzuzeigen)
Schritt 3: Hinzufügen derSuppliersTableAdapter
Datenzugriffsebene
Um mit den Lieferanteninformationen in unserer Anwendung zu arbeiten, müssen wir zuerst eine TableAdapter und DataTable in unserer DAL erstellen. Im Idealfall wäre dies mit den gleichen einfachen Schritten zu erreichen, die in früheren Lernprogrammen untersucht wurden. Die Arbeit mit berechneten Spalten führt jedoch zu einigen Falten, die diskussionswürdig sind.
Wenn Sie ein TableAdapter verwenden, das Ad-hoc-SQL-Anweisungen verwendet, können Sie einfach die berechnete Spalte in die TableAdapter-Hauptabfrage über den TableAdapter-Konfigurations-Assistenten einschließen. Dies wird jedoch automatisch generiert INSERT
und UPDATE
Anweisungen, die die berechnete Spalte enthalten. Wenn Sie versuchen, eine dieser Methoden auszuführen, kann die SqlException
Meldung "ColumnName" nicht geändert werden, da es sich entweder um eine berechnete Spalte handelt oder das Ergebnis eines UNION-Operators ausgelöst wird. Während die INSERT
Und-Anweisung UPDATE
manuell über die TableAdapter s InsertCommand
und UpdateCommand
Eigenschaften angepasst werden kann, gehen diese Anpassungen verloren, wenn der TableAdapter-Konfigurations-Assistent erneut ausgeführt wird.
Aufgrund der Sprödigkeit von TableAdapters, die Ad-hoc-SQL-Anweisungen verwenden, wird empfohlen, gespeicherte Prozeduren beim Arbeiten mit berechneten Spalten zu verwenden. Wenn Sie vorhandene gespeicherte Prozeduren verwenden, konfigurieren Sie einfach den TableAdapter, wie im Lernprogramm "Using Existing Stored Procedures for The Typed DataSet s TableAdapters " beschrieben. Wenn Sie den TableAdapter-Assistenten zum Erstellen der gespeicherten Prozeduren für Sie haben, ist es jedoch wichtig, zunächst alle berechneten Spalten aus der Hauptabfrage auszulassen. Wenn Sie eine berechnete Spalte in die Hauptabfrage einschließen, informiert Sie der Konfigurations-Assistent von TableAdapter nach Abschluss, dass die entsprechenden gespeicherten Prozeduren nicht erstellt werden können. Kurz gesagt müssen wir zunächst den TableAdapter mithilfe einer berechneten spaltenfreien Hauptabfrage konfigurieren und dann die entsprechende gespeicherte Prozedur und die TableAdapter s SelectCommand
manuell aktualisieren, um die berechnete Spalte einzuschließen. Dieser Ansatz ähnelt dem Ansatz, der im Lernprogramm "TableAdapter to UseJOIN
s" verwendet wird.
Für dieses Lernprogramm fügen wir ein neues TableAdapter hinzu und lassen Sie es automatisch die gespeicherten Prozeduren für uns erstellen. Daher müssen wir zunächst die FullContactName
berechnete Spalte aus der Hauptabfrage weglassen.
Öffnen Sie zunächst das NorthwindWithSprocs
DataSet im ~/App_Code/DAL
Ordner. Klicken Sie im Designer mit der rechten Maustaste, und wählen Sie im Kontextmenü ein neues TableAdapter-Objekt aus. Dadurch wird der Konfigurations-Assistent "TableAdapter" gestartet. Geben Sie die Datenbank an, aus der Daten abgerufen werden sollen (NORTHWNDConnectionString
aus Web.config
) und klicken Sie auf Weiter. Da wir noch keine gespeicherten Prozeduren zum Abfragen oder Ändern der Suppliers
Tabelle erstellt haben, wählen Sie die Option "Neue gespeicherte Prozeduren erstellen" aus, damit der Assistent sie für uns erstellt und auf "Weiter" klickt.
Abbildung 3: Auswählen der Option "Neue gespeicherte Prozeduren erstellen" (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Der folgende Schritt fordert uns zur Hauptabfrage auf. Geben Sie die folgende Abfrage ein, die die SupplierID
Spalten CompanyName
, , ContactName
und ContactTitle
die Spalten für jeden Lieferanten zurückgibt. Beachten Sie, dass diese Abfrage die berechnete Spalte (FullContactName
) absichtlich ausgelassen. Wir aktualisieren die entsprechende gespeicherte Prozedur so, dass sie diese Spalte in Schritt 4 einschließt.
SELECT SupplierID, CompanyName, ContactName, ContactTitle
FROM Suppliers
Nachdem Sie die Hauptabfrage eingegeben und auf "Weiter" geklickt haben, kann der Assistent die vier gespeicherten Prozeduren benennen, die generiert werden. Nennen Sie diese gespeicherten Prozeduren Suppliers_Select
, Suppliers_Insert
, Suppliers_Update
und Suppliers_Delete
, wie in Abbildung 4 dargestellt.
Abbildung 4: Anpassen der Namen der automatisch generierten gespeicherten Prozeduren (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Im nächsten Assistentenschritt können wir die TableAdapter-Methoden benennen und die Muster angeben, die für den Zugriff auf und die Aktualisierung von Daten verwendet werden. Lassen Sie alle drei Kontrollkästchen aktiviert, benennen Sie die GetData
Methode GetSuppliers
jedoch in . Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen.
Abbildung 5: Umbenennen der GetData
Methode in GetSuppliers
(Klicken, um das Bild in voller Größe anzuzeigen)
Wenn Sie auf "Fertig stellen" klicken, erstellt der Assistent die vier gespeicherten Prozeduren und fügt das TableAdapter und die entsprechende DataTable zum typierten DataSet hinzu.
Schritt 4: Einschließen der berechneten Spalte in die TableAdapter-Hauptabfrage
Wir müssen nun das in Schritt 3 erstellte TableAdapter- und DataTable-Objekt aktualisieren, um die FullContactName
berechnete Spalte einzuschließen. Dies umfasst zwei Schritte:
- Aktualisieren der
Suppliers_Select
gespeicherten Prozedur, um dieFullContactName
berechnete Spalte zurückzugeben, und - Aktualisieren der DataTable, um eine entsprechende
FullContactName
Spalte einzuschließen.
Navigieren Sie zunächst zum Server-Explorer, und führen Sie einen Drilldown in den Ordner "Gespeicherte Prozeduren" durch. Öffnen Sie die Suppliers_Select
gespeicherte Prozedur, und aktualisieren Sie die SELECT
Abfrage so, dass sie die FullContactName
berechnete Spalte enthält:
SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers
Speichern Sie die Änderungen an der gespeicherten Prozedur, indem Sie auf das Symbol "Speichern" in der Symbolleiste klicken, indem Sie STRG+S drücken oder im Menü "Datei" die Option "Speichern Suppliers_Select
" auswählen.
Kehren Sie als Nächstes zum DataSet-Designer zurück, klicken Sie mit der SuppliersTableAdapter
rechten Maustaste darauf, und wählen Sie im Kontextmenü "Konfigurieren" aus. Beachten Sie, dass die Suppliers_Select
Spalte jetzt die Spalte in der FullContactName
Datenspaltenauflistung enthält.
Abbildung 6: Ausführen des Konfigurations-Assistenten für TableAdapter zum Aktualisieren der Datentabellenspalten (Klicken, um das Bild in voller Größe anzuzeigen)
Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen. Dadurch wird automatisch eine entsprechende Spalte hinzugefügt.SuppliersDataTable
Der TableAdapter-Assistent ist intelligent genug, um zu erkennen, dass die FullContactName
Spalte eine berechnete Spalte und daher schreibgeschützt ist. Folglich wird die Eigenschaft der Spalte ReadOnly
auf true
. Um dies zu überprüfen, wählen Sie die Spalte aus, SuppliersDataTable
und wechseln Sie dann zum Eigenschaftenfenster (siehe Abbildung 7). Beachten Sie, dass die FullContactName
Spalten DataType
und MaxLength
Eigenschaften ebenfalls entsprechend festgelegt werden.
Abbildung 7: Die FullContactName
Spalte ist als schreibgeschützt markiert (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schritt 5: Hinzufügen einerGetSupplierBySupplierID
Methode zum TableAdapter
In diesem Lernprogramm erstellen wir eine ASP.NET Seite, auf der die Lieferanten in einem aktualisierbaren Raster angezeigt werden. In früheren Lernprogrammen haben wir einen einzelnen Datensatz aus der Geschäftslogikebene aktualisiert, indem wir diesen bestimmten Datensatz aus der DAL als stark typierte DataTable abrufen, seine Eigenschaften aktualisieren und dann die aktualisierte DataTable zurück an den DAL senden, um die Änderungen an die Datenbank zu verteilen. Um diesen ersten Schritt zu erreichen – abrufen des Datensatzes, der aus dem DAL aktualisiert wird – müssen wir zuerst eine GetSupplierBySupplierID(supplierID)
Methode zum DAL hinzufügen.
Klicken Sie mit der rechten Maustaste auf das SuppliersTableAdapter
DataSet-Design, und wählen Sie im Kontextmenü die Option "Abfrage hinzufügen" aus. Wie in Schritt 3 beschrieben, lassen Sie den Assistenten eine neue gespeicherte Prozedur für uns generieren, indem Sie die Option "Neue gespeicherte Prozedur erstellen" auswählen (siehe Abbildung 3 für einen Screenshot dieses Assistentenschritts). Da diese Methode einen Datensatz mit mehreren Spalten zurückgibt, geben Sie an, dass wir eine SQL-Abfrage verwenden möchten, die eine SELECT ist, die Zeilen zurückgibt, und klicken Sie auf Weiter.
Abbildung 8: Auswählen der SELECT-Option, die die Zeilenoption zurückgibt (Klicken, um das Bild in voller Größe anzuzeigen)
Der folgende Schritt fordert uns auf, die Abfrage für diese Methode zu verwenden. Geben Sie Folgendes ein, das dieselben Datenfelder wie die Hauptabfrage, aber für einen bestimmten Lieferanten zurückgibt.
SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers
WHERE SupplierID = @SupplierID
Im nächsten Bildschirm werden wir aufgefordert, die gespeicherte Prozedur zu benennen, die automatisch generiert wird. Benennen Sie diese gespeicherte Prozedur Suppliers_SelectBySupplierID
, und klicken Sie auf Weiter.
Abbildung 9: Benennen der gespeicherten Prozedur Suppliers_SelectBySupplierID
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Schließlich fordert der Assistent uns auf, die Datenzugriffsmuster und Methodennamen für den TableAdapter zu verwenden. Lassen Sie beide Kontrollkästchen aktiviert, benennen Sie die FillBy
Methoden GetDataBy
FillBySupplierID
jedoch in bzw GetSupplierBySupplierID
. um.
Abbildung 10: Benennen der TableAdapter-Methoden FillBySupplierID
und GetSupplierBySupplierID
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen.
Schritt 6: Erstellen der Geschäftslogikebene
Bevor wir eine ASP.NET Seite erstellen, die die in Schritt 1 erstellte berechnete Spalte verwendet, müssen wir zuerst die entsprechenden Methoden in der BLL hinzufügen. Auf unserer ASP.NET-Seite, die wir in Schritt 7 erstellen, können Benutzer Lieferanten anzeigen und bearbeiten. Daher benötigen wir unsere BLL, um mindestens eine Methode bereitzustellen, um alle Lieferanten und eine andere zu erhalten, um einen bestimmten Lieferanten zu aktualisieren.
Erstellen Sie eine neue Klassendatei namens SuppliersBLLWithSprocs
im ~/App_Code/BLL
Ordner, und fügen Sie den folgenden Code hinzu:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class SuppliersBLLWithSprocs
{
private SuppliersTableAdapter _suppliersAdapter = null;
protected SuppliersTableAdapter Adapter
{
get
{
if (_suppliersAdapter == null)
_suppliersAdapter = new SuppliersTableAdapter();
return _suppliersAdapter;
}
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, true)]
public NorthwindWithSprocs.SuppliersDataTable GetSuppliers()
{
return Adapter.GetSuppliers();
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Update, true)]
public bool UpdateSupplier(string companyName, string contactName,
string contactTitle, int supplierID)
{
NorthwindWithSprocs.SuppliersDataTable suppliers =
Adapter.GetSupplierBySupplierID(supplierID);
if (suppliers.Count == 0)
// no matching record found, return false
return false;
NorthwindWithSprocs.SuppliersRow supplier = suppliers[0];
supplier.CompanyName = companyName;
if (contactName == null)
supplier.SetContactNameNull();
else
supplier.ContactName = contactName;
if (contactTitle == null)
supplier.SetContactTitleNull();
else
supplier.ContactTitle = contactTitle;
// Update the product record
int rowsAffected = Adapter.Update(supplier);
// Return true if precisely one row was updated, otherwise false
return rowsAffected == 1;
}
}
Wie bei den anderen BLL-Klassen gibt es eine Adapter
protected
Eigenschaft, SuppliersBLLWithSprocs
die eine Instanz der SuppliersTableAdapter
Klasse zusammen mit zwei public
Methoden zurückgibt: GetSuppliers
und UpdateSupplier
. Die GetSuppliers
Methode ruft die SuppliersDataTable
von der entsprechenden GetSupplier
Methode in der Datenzugriffsschicht zurückgegebene Methode auf und gibt sie zurück. Die UpdateSupplier
Methode ruft Informationen über den jeweiligen Lieferanten ab, der über einen Aufruf der DAL s-Methode GetSupplierBySupplierID(supplierID)
aktualisiert wird. Anschließend werden die Änderungen an der CategoryName
Datenbank aktualisiert und ContactTitle
durch Aufrufen der Data Access Layer-Methode Update
und übergeben sie das geänderte SuppliersRow
ContactName
Objekt.
Hinweis
Mit Ausnahme und SupplierID
CompanyName
, dass alle Spalten in der Tabelle "Lieferanten" Werte zulassen NULL
. Wenn also die übergebenen contactName
oder contactTitle
Parameter übergeben werden null
, müssen wir die entsprechenden ContactName
Eigenschaften ContactTitle
bzw. Eigenschaften auf einen NULL
Datenbankwert festlegen, der bzw. die SetContactNameNull
SetContactTitleNull
methoden verwendet wird.
Schritt 7: Arbeiten mit der berechneten Spalte aus der Präsentationsebene
Nachdem die berechnete Spalte der Suppliers
Tabelle hinzugefügt wurde und die DAL und BLL entsprechend aktualisiert wurden, können wir eine ASP.NET Seite erstellen, die mit der FullContactName
berechneten Spalte funktioniert. Öffnen Sie zunächst die ComputedColumns.aspx
Seite im AdvancedDAL
Ordner, und ziehen Sie eine GridView aus der Toolbox auf den Designer. Legen Sie die GridView-Eigenschaft ID
auf und binden Sie sie von ihrem Smarttag an Suppliers
eine neue ObjectDataSource mit dem Namen SuppliersDataSource
. Konfigurieren Sie die ObjectDataSource so, dass sie die Klasse verwendet, die SuppliersBLLWithSprocs
wir in Schritt 6 wieder hinzugefügt haben, und klicken Sie auf "Weiter".
Abbildung 11: Konfigurieren der ObjectDataSource für die Verwendung der Klasse (Zum Anzeigen des SuppliersBLLWithSprocs
Bilds mit voller Größe klicken)
In der SuppliersBLLWithSprocs
Klasse sind nur zwei Methoden definiert: GetSuppliers
und UpdateSupplier
. Stellen Sie sicher, dass diese beiden Methoden auf den Registerkarten SELECT und UPDATE angegeben sind, und klicken Sie auf "Fertig stellen", um die Konfiguration der ObjectDataSource abzuschließen.
Nach Abschluss des Assistenten für die Datenquellenkonfiguration fügt Visual Studio für jedes der zurückgegebenen Datenfelder ein BoundField hinzu. Entfernen Sie das SupplierID
BoundField, und ändern Sie die HeaderText
Eigenschaften von " CompanyName
, ContactName
" , ContactTitle
" und FullContactName
"BoundFields" in "Company", "Contact Name", "Title" bzw. "Vollständiger Kontaktname". Aktivieren Sie im Smarttag das Kontrollkästchen "Bearbeitung aktivieren", um die integrierten Bearbeitungsfunktionen von GridView zu aktivieren.
Neben dem Hinzufügen von BoundFields zur GridView bewirkt der Abschluss des Datenquellen-Assistenten auch, dass Visual Studio die ObjectDataSource-Eigenschaft OldValuesParameterFormatString
auf original_{0} festgelegt. Setzen Sie diese Einstellung auf den Standardwert zurück. {0}
Nachdem Sie diese Änderungen an GridView und ObjectDataSource vorgenommen haben, sollte ihr deklaratives Markup wie folgt aussehen:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="CompanyName"
HeaderText="Company"
SortExpression="CompanyName" />
<asp:BoundField DataField="ContactName"
HeaderText="Contact Name"
SortExpression="ContactName" />
<asp:BoundField DataField="ContactTitle"
HeaderText="Title"
SortExpression="ContactTitle" />
<asp:BoundField DataField="FullContactName"
HeaderText="Full Contact Name"
SortExpression="FullContactName"
ReadOnly="True" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
SelectMethod="GetSuppliers" TypeName="SuppliersBLLWithSprocs"
UpdateMethod="UpdateSupplier">
<UpdateParameters>
<asp:Parameter Name="companyName" Type="String" />
<asp:Parameter Name="contactName" Type="String" />
<asp:Parameter Name="contactTitle" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
Besuchen Sie als Nächstes diese Seite über einen Browser. Wie in Abbildung 12 dargestellt, wird jeder Lieferant in einem Raster aufgeführt, das die FullContactName
Spalte enthält, deren Wert einfach die Verkettung der anderen drei Spalten ist, die als ContactName
(ContactTitle
, CompanyName
) formatiert sind.
Abbildung 12: Jeder Lieferant ist im Raster aufgelistet (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Durch Klicken auf die Schaltfläche "Bearbeiten" für einen bestimmten Lieferanten wird ein Postback verursacht und die Zeile in der Bearbeitungsoberfläche gerendert (siehe Abbildung 13). Die ersten drei Spalten werden in der Standardbearbeitungsschnittstelle gerendert – ein TextBox-Steuerelement, dessen Text
Eigenschaft auf den Wert des Datenfelds festgelegt ist. Die FullContactName
Spalte bleibt jedoch als Text. Wenn die BoundFields nach Abschluss des Assistenten für die Datenquellenkonfiguration der GridView hinzugefügt wurden, wurde die FullContactName
BoundField-Eigenschaft ReadOnly
so festgelegt true
, dass die entsprechende FullContactName
Spalte in der SuppliersDataTable
Eigenschaft auf true
ist. Wie in Schritt 4 erwähnt, wurde die FullContactName
s-Eigenschaft ReadOnly
so festgelegt true
, dass das TableAdapter festgestellt hat, dass die Spalte eine berechnete Spalte war.
Abbildung 13: Die FullContactName
Spalte ist nicht bearbeitbar (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Fahren Sie fort, und aktualisieren Sie den Wert einer oder mehrerer bearbeitbarer Spalten, und klicken Sie auf "Aktualisieren". Beachten Sie, wie der FullContactName
Wert automatisch aktualisiert wird, um die Änderung widerzuspiegeln.
Hinweis
GridView verwendet derzeit BoundFields für die bearbeitbaren Felder, was zu der Standardbearbeitungsschnittstelle führt. Da das CompanyName
Feld erforderlich ist, sollte es in ein TemplateField konvertiert werden, das ein RequiredFieldValidator enthält. Ich belässt dies als Übung für den interessierten Leser. Lesen Sie das Lernprogramm zum Hinzufügen von Gültigkeitsprüfungssteuerelementen zum Lernprogramm zum Bearbeiten und Einfügen von Schnittstellen , um schrittweise Anleitungen zum Konvertieren eines BoundField-Steuerelements in ein TemplateField und zum Hinzufügen von Überprüfungssteuerelementen zu erhalten.
Zusammenfassung
Beim Definieren des Schemas für eine Tabelle ermöglicht Microsoft SQL Server die Aufnahme berechneter Spalten. Dies sind Spalten, deren Werte aus einem Ausdruck berechnet werden, der in der Regel auf die Werte aus anderen Spalten im selben Datensatz verweist. Da die Werte für berechnete Spalten auf einem Ausdruck basieren, sind sie schreibgeschützt und können einem Wert in einer INSERT
Oder-Anweisung UPDATE
nicht zugewiesen werden. Dies führt zu Herausforderungen bei der Verwendung einer berechneten Spalte in der Hauptabfrage eines TableAdapters, die versucht, automatisch entsprechende INSERT
, und UPDATE
DELETE
Anweisungen zu generieren.
In diesem Lernprogramm haben wir Techniken zur Umgehung der Herausforderungen durch berechnete Spalten erörtert. Insbesondere haben wir gespeicherte Prozeduren in unserem TableAdapter verwendet, um die Inhärenz von TableAdapters zu überwinden, die Ad-hoc-SQL-Anweisungen verwenden. Wenn der TableAdapter-Assistent neue gespeicherte Prozeduren erstellt hat, ist es wichtig, dass die Hauptabfrage zunächst berechnete Spalten weglassen muss, da deren Anwesenheit verhindert, dass die gespeicherten Prozeduren für die Datenänderung generiert werden. Nachdem das TableAdapter-Objekt ursprünglich konfiguriert wurde, kann die SelectCommand
gespeicherte Prozedur umgerüstet werden, um berechnete Spalten einzuschließen.
Glückliche Programmierung!
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann über mitchell@4GuysFromRolla.com seinen Blog erreicht werden, der unter .http://ScottOnWriting.NET
Besonderer Dank an
Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Lernprogramm waren Hilton Geisenow und Teresa Murphy. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn dies der Fall ist, legen Sie mir eine Zeile bei mitchell@4GuysFromRolla.com.