2009-08-13 9 views
4

Ich habe den folgenden Code, wiederholt auf jedem Form, als Teil des Update-Prozesses. Wenn die Seite lädt die BLL kehrt ein DataSet, sagenEine effizientere Art, mit DataSets zu arbeiten

_personInfo = ConnectBLL.BLL.Person.GetPerson(personID); 

Ich speichere dass DataSet in einer Form Ebene Variable, die ich dann während des Validate/Update-Prozess auf Änderungen überprüfen gegen verwenden. Ich übergebe jeweils eine Zeile (, obwohl es nie mehr als eine Zeile gibt) an eine Function, die den Wert in einem Steuerelement übernimmt und es mit dem entsprechenden Spaltenwert in DataSet vergleicht. Wenn es anders ist, setzt es die Spalte = auf den neuen Wert und fügt den Namen zu einem List dessen, was geändert wurde.

// Load Person info 
     using (var tmpPersonDT = tmpPersonDS.Tables[0]) 
     { 
      if (tmpPersonDT.Rows.Count > 0) 
      { 
       foreach (DataRow row in tmpPersonDT.Rows) 
       { 
        CheckPersonData(row); 
       } 

      } 
     } 

// Snippet of the CheckPersonData() that is being called.... 
    if (!object.Equals(row["ResidencyCountyID"], lkuResidenceCounty.EditValue)) 
    { 
     row["ResidencyCountyID"] = lkuResidenceCounty.EditValue; 
     _whatChanged.Add("ResidencyCounty"); 
    } 

if (!object.Equals(row["ResponsibilityCountyID"], lkuResponsibleCounty.EditValue)) 
{ 
    row["ResponsibilityCountyID"] = lkuResponsibleCounty.EditValue; 
    _whatChanged.Add("ResponsibilityCounty"); 
} 

if (!object.Equals(row["HispanicOriginFlag"], chkHispanic.EditValue)) 
{ 
    row["HispanicOriginFlag"] = chkHispanic.EditValue; 
    _whatChanged.Add("HispanicOriginFlag"); 
} 

if (!object.Equals(row["CitizenFlag"], chkCitizen.EditValue)) 
{ 
    row["CitizenFlag"] = chkCitizen.EditValue; 
    _whatChanged.Add("CitizenFlag"); 
} 

if (!object.Equals(row["VeteranFlag"], chkVeteran.EditValue)) 
{ 
    row["VeteranFlag"] = chkVeteran.EditValue; 
    _whatChanged.Add("VeteranFlag"); 
} 

Was ich versuche, eine Antwort zu bekommen, ist dies wirklich der effizienteste Weg, um darüber zu gehen?

Wenn nichts anderes möchte ich eine Funktion erstellen, um das Vergleichen statt 30 mal zu wiederholen (pro Formular variiert), aber ich kann das nicht ganz herausfinden. Ich dachte, ich könnte vielleicht row []. ItemArray, aber das hat nur die Werte. Ich würde KNOW haben vor der Zeit, was die Elemente in und Bank waren um sich an ihnen nicht zu ändern ....

Bin ich etwas offensichtlich für fehlende Arbeit mit Datasets/Tables in einer CRUD app?


juliandewitt's post below is fantastic!

ich jetzt gerade, muß eine Richtung auf, wie das in der oben zu verwenden. Jegliche Links, auf die mich jemand verweisen kann, würden mir gefallen. Noch besser, wenn Sie ein Beispiel veröffentlichen können.

Gibt es Nachteile bei der Verwendung von DataRows?

+0

* puh * Ich denke, das ist meine größte Antwort immer :) Aber im Ernst, ich hoffe, zwischen den eingebauten Zustand Verfolgung, stark typisierte Datasets und Tableadapter und Databinding wir einige Türen geöffnet haben für Sie zu finden einige der RAD-Tools in Visual Studio sowie die Leistungsfähigkeit von ADO.NET. Das heißt, es ist keine Wunderwaffe und kein perfektes System; Es ist ein breites System, das seine Schwächen und Einschränkungen hat - aber es ist ein Eckpfeiler von .NET 1.0 - 2.0. .NET 3.0 und höher beginnen jedoch, sich von ADO.NET zu entfernen, und in 3.5 SP1 wird das Entity Framework angezeigt. Es ist alles noch immer wissenswert! – STW

Antwort

7

Es sieht so aus, als würden Sie eine Menge Handarbeit machen, die durch die direkte Anbindung Ihrer Steuerelemente an Ihren DataSet/Table gelindert werden könnte. Databinding führt Ihre Datenquelle (in diesem Fall Ihre Datenmenge/Tabelle) mit Ihrer Benutzeroberfläche zusammen. Wenn sich der Wert in der Benutzeroberfläche ändert, wird die Datenquelle aktualisiert.

DataBinding ist ein BIG Thema, das Forschung und Tests rechtfertigt. Es gibt einige Probleme mit der Datenbindung an eine DataTable/Set (die Zeilenänderungen werden erst dann commited, wenn sich die aktuelle Zeile ändert, was in Ihrem Fall nur mit einer einzelnen Zeile zu arbeiten nervt - aber es gibt Workarounds).

Umgeschrieben: Eine andere Sache, die zu berücksichtigen ist, ist die Verwendung von Geschäftsobjekten, um die Daten in Ihren Sets/Tabellen darzustellen. ORM (objektrelationale Mapper) können das für Sie erledigen, aber sie sind große und sehr mächtige Frameworks, die nicht einfach zu beherrschen sind. Es ist ein völlig anderes Paradigma als die Arbeit mit DataSets/Tables auf der UI-Ebene und ist eher auf objektorientierte Programmierung ausgerichtet. DataSets und Tabellen eignen sich sehr gut für die Arbeit mit Tabellendaten, eignen sich aber nicht besonders gut für die Arbeit mit Entitäten.Zum Beispiel würden arbeiten Sie für eine Instanz eines Person Objekt mit Eigenschaften wie IsHispanic und IsCitizen rahtner als im Wesentlichen arbeitet gegen Zellen in einer Tabelle (nicht mehr * myPersonTable [0] [ „HispanicOriginFlag“] ... .).

Weiter: Nicht verwandt mit Ihrer Frage, aber relevant für CRUD-Vorgänge, die sich um ADO.NET drehen: Es lohnt sich, sich mit der in ein DataTable/DataSet integrierten Statusverfolgung vertraut zu machen. Es gibt viele in ADO.NET zu bauen, um diese Anwendungen einfach zusammen zu kleben, die Tonnen Code wie Sie gezeigt hätten, zu reinigen.

Wie immer haben RAD-Tools den Nachteil, dass Sie die Kontrolle über die Produktivität aufgeben müssen - aber wenn Sie sie abschreiben, ohne sie zu verstehen, garantieren Sie, dass Sie Ihre Tage damit verbringen, Code zu schreiben, wie Sie ihn gezeigt haben.

Mehr noch: bauen weiter auf meine vorherigen Weiteren, wenn Sie die Fähigkeit entdecken Visual Studio DataSet Generator mit der eingebauten in RowState Verfolgung von Datentabellen zu verbinden und Änderungsverfolgung von Datensatz ist es sehr sein kann einfach ein komplettes CRUD-System in kurzer Zeit zu schreiben.

Hier ist ein kurzer Überblick nach unten auf einige der Schritte beteiligt: ​​

  1. Richten Sie Ihre Datenbank-Schema
  2. In Visual Studio fügen Sie einen neuen Datensatz Element an einem Projekt
  3. den Explorer Server finden (unter View)
  4. Fügen Sie Ihren SQL Server als Datenverbindung hinzu
  5. Ziehen Sie Ihre Tabelle/gespeicherte proc/View in den Designer des DataSet.
  6. Klicken Sie mit der rechten Maustaste auf den "TableAdapter", den Visual Studio für Sie erstellt hat; gehen konfigurieren
  7. Konfigurieren Sie die CRUD Befehle für den Datensatz (die Select, Insert, Update, Delete-Befehle)

Damit Sie eine erstellt haben stark typisierte DataSet. Das DataSet enthält eine DataTable-Eigenschaft, die nach der Tabelle/view/gespeicherten Prozedur benannt ist, die zum Generieren des DataSet verwendet wird. Diese Table-Eigenschaft enthält stark typisierte Zeilen, mit denen Sie auf die Zellen innerhalb dieser Zeile als Eigenschaften und nicht als nicht typisierte Elemente in einem Objektarray zugreifen können.

Also, wenn Sie einen neuen Datensatz namens generiert haben MyDbTables, mit einer Tabelle mit dem Namen tblCustomer die einige Spalten wie enthält CustomerId, Namen, etc ... dann kann man damit wie folgt arbeiten : - Blick in die Methoden und besonders in den Table Klasse

einige der häufigsten verwendeten Methoden für CRUD Arbeit zeigt

Dies ist eine Vielzahl Beispiele in ein, gerollt

Beachten Sie auch die RejectChanges() - und AcceptChanges() -Methoden von DataSets und DataTables.Sie teilen Ihrem Dataset im Wesentlichen mit, dass es keine Änderungen gibt (entweder durch Zurückweisen aller Änderungen oder durch "Commit" aller Änderungen). Beachten Sie jedoch, dass das Aufrufen von AcceptChanges() und das Durchführen einer Aktualisierung keine Auswirkungen haben - das DataSet hat verloren Verfolgung von Änderungen und nimmt an, dass es eine genaue Reflexion der Datenbank ist.

Und noch mehr! Hier ist eine überarbeitete Version von Ihrem Beispiel einige der RowState Tracking-Funktionen zeigt, vorausgesetzt, Sie sind meine Schritte befolgt haben zu erstellen stark typisierte Datasets/Tabellen/Zeilen

public void CheckRows() 
    { 
     MyPersonDS tmpPersonDS = new MyPersonDS(); 

     // Load Person info 
     using (var tmpPersonDT = tmpPersonDS.PersonDT) 
     { 
      foreach (MyPersonRow row in tmpPersonDT.Rows) 
      { 
       CheckPersonData(row); 
      } 
     } 

    } 

    public void CheckPersonData(MyPersonRow row) 
    { 
     // If DataBinding is used, then show if the row is unchanged/modified/new... 
     System.Diagnostics.Debug.WriteLine("Row State: " + row.RowState.ToString()); 

     System.Diagnostics.Debug.WriteLine("Row Changes:"); 
     System.Diagnostics.Debug.WriteLine(BuildRowChangeSummary(row)); 

     // If not DataBound then update the strongly-types Row properties 
     row.ResidencyCountyID = lkuResidencyCountyId.EditValue; 


    } 

    public string BuildRowChangeSummary(DataRow row) 
    { 
     System.Text.StringBuilder result = new System.Text.StringBuilder(); 

     int rowColumnCount = row.Table.Columns.Count; 
     for (int index = 0; index < rowColumnCount; ++index) 
     { 
      result.Append(string.Format("Original value of {0}: {1}\r\n", row.Table.Columns[index].ColumnName, row[index, DataRowVersion.Original])); 
      result.Append(string.Format("Current value of {0}: {1}\r\n", row.Table.Columns[index].ColumnName, row[index, DataRowVersion.Current])); 

      if (index < rowColumnCount - 1) { result.Append("\r\n"); } 
     } 

     return result.ToString(); 
    } 
+0

Sehen Sie die Dev's, die ich geerbt habe, sagte mir, ich solle mich von MS Databinding fernhalten ... –

+1

Sie sollten diesen Entwicklern einen hässlichen Brief schicken. –

+0

@Refracted: Es hat einige Vorbehalte und funktioniert nicht immer so, wie Sie vermuten - aber es ist die Art von .NET und definitiv die Art von WPF. Sei ein Meister davon und lerne zumindest seine Fähigkeiten/Schwächen. – STW

2

Wenn Sie eine einheitliche Namenskonvention für die Verwendung Eigenschaften, die den Datensatzspaltennamen zugeordnet werden, würde die Reflektion die einzelne wiederverwendbare Methode ermöglichen. Sie müssen es jedoch testen, um sicherzustellen, dass es nicht zu einem Leistungsproblem kommt.

Um dies zu tun, durchlaufen Sie die Columns-Auflistung aus der Tabelle. Verwenden Sie dann für jede Spalte die Reflektion, um die "übereinstimmende" Eigenschaft für das Objekt zu finden, das mit der Zeile verglichen wird. (Sie wollen auf der Propertyinfo-Klasse von obj.GetType zurück zu konzentrieren(). GetProperties (...).)

2

Auch die datarow automatisch den Überblick über Änderungen hält ..

DataRow _personInfo = ConnectBLL.BLL.Person.GetPerson(personID); 
// _personInfo.RowState = DataRowState.Unchanged 
_personInfo["columnName"] = "value"; 
_personInfo["columnName2"] = "value2"; 
_personInfo.EndEdit(); 
// _personInfo.RowState = DataRowState.Modified 

Jetzt können Sie die geänderten Werte erhalten, indem die RowState fragen und Werte überprüfen, wie

var org = fRow["columnName", DataRowVersion.Original]; 
var new = fRow["columnName",DataRowVersion.Current]; 

Änderungen zu erkennen folgt Sie auch an der Column Veranstaltung hören.

fTable.ColumnChanged += new DataColumnChangeEventHandler(delegate(object sender, DataColumnChangeEventArgs e) 
{ 
    Console.WriteLine(e.Column.ColumnName); 
} 
); 
+0

Wie ist es, ich neuere neue dies !!! Ich muss noch die Änderungen trotzdem vornehmen (* an die DB *), richtig? Ich denke, was ich bekomme ist, wo '_personInfo.AcceptChanges() 'und' _personInfo.BeginEdit() 'ins Spiel kommen; Wenn überhaupt? –

+0

BeginEdit(), um die Zeile in den Bearbeitungsmodus zu versetzen. Ich denke, es ist auch, wenn Sie einen Wert ändern.
AcceptChanges, wenn Sie die Änderungen an der Datenbank festgeschrieben haben und neu beginnen möchten. (Der ursprüngliche Wert wird zum aktuellen Wert). –

Verwandte Themen