2009-07-30 5 views
2

Ich bin kürzlich auf eine sehr einfache Typed DataTable gestoßen (ohne eine .XSD) (Ich habe die URL des Autors verloren, also kann ich ihn nicht gutschreiben), aber es sieht so aus, als gäbe es viel doppelten Code (wie das Add/Entfernen/GetNewRow-Methoden).Handgefertigte stark typisierte ADO.net DataTable - Kann es sauberer sein?

Ich habe versucht, die repetitiven Methoden in eine super Klasse zu schieben, aber ich habe Probleme aufgrund der Mitarbeiter müssen generisch sein. Ich hatte gehofft, StackOverflow's kollektiven Bienenstock Verstand zu bekommen, um einige Ideen vorzuschlagen, um das aufzuräumen? (Wenn es sogar möglich?)

using System; 
using System.Data; 
using System.Collections; 
using System.Data.SqlClient; 

namespace TypedDataSet { 

    public class Employees : DataTable { 
    protected SqlDataAdapter _adapter; 

    public Employees() { 
     string connectionString = TypedDataSet.Properties.Settings.Default.ConnectionString; 
     _adapter = new System.Data.SqlClient.SqlDataAdapter("SELECT Id, Firstname, Surname FROM Employee", connectionString); 
     _adapter.Fill(this); 
    } 

    public Employee this[int index] { 
     get { return (Employee)Rows[index]; } 
    } 

    public void Add(Employee row) { 
     Rows.Add(row); 
    } 

    public void Remove(Employee row) { 
     Rows.Remove(row); 
    } 

    public Employee GetNewRow() { 
     Employee row = (Employee)NewRow(); 
     return row; 
    } 

    protected override DataRow NewRowFromBuilder(DataRowBuilder builder) { 
     return new Employee(builder); 
    } 

    public IEnumerator GetEnumerator() { 
     return Rows.GetEnumerator(); 
    } 

    protected override Type GetRowType() { 
     return typeof(Employee); 
    } 
    } 

    public class Employee : DataRow { 
    internal Employee(DataRowBuilder builder) 
     : base(builder) { 
    } 

    public Int64 Id { 
     get { return (Int64)base["Id"]; } 
     set { base["Id"] = value; } 
    } 

    public string FirstName { 
     get { return (string)base["Firstname"]; } 
     set { base["Firstname"] = value; } 
    } 

    public string Surname { 
     get { return (string)base["Surname"]; } 
     set { base["Surname"] = value; } 
    } 
    } 
} 
+1

Wenn Sie .net fwk 2.0 oder höher verwenden, können Sie Generika verwenden. Was ist deine Frage wirklich? Was willst du erreichen? – shahkalpesh

+0

Ich verwende .net 2.0. Ich bin mir nicht 100% ig sicher, wie ich das mit Generika umsetzen kann. Was ich erreichen möchte ist, dass ich Code für die Verwendung von generischen und/oder Vererbungsmodellen verwende. Wenn ich also mehr TypeDataSets (wie zB Employee, Product, Category, etc) erstelle, muss ich keinen Code kopieren und einfügen (Add()/Entferne()/...) in diese anderen Klassen. Aber in der Lage sein, eine neue "Produkt" -Klasse, die mit diesen Methoden kommt, kostenlos zu erstellen. Wenn ich Wiederholungen wie die Employer-Klasse beim Erstellen anderer Typed DataTables auf diese Weise sehe, denke ich, dass es eine weniger repetitive Art geben muss. –

Antwort

3

Ich glaube, dass ich meine Frage beantwortet haben, Art. Ich musste .net 4.0 verwenden, um die Ergebnisse zu erhalten, die ich spezifisch für den dynamischen Typ erhoffte.

die vorhandene Klasse in der Frage So verändert sich:

Employee.cs

using System; 
using System.Data; 
using System.Collections; 
using System.Data.Common; 

namespace TypedDataSet { 

    public class Employees : BaseModel<Employee> { 

    public Employees(bool loadAll) { 
     DbDataAdapter adapter = base.Adapter("SELECT * FROM Employees"); 
     adapter.Fill(this); 
    } 

    protected override DataRow NewRowFromBuilder(DataRowBuilder builder) { 
     return new Employee(builder); 
    } 
    } 

    public class Employee : DataRow { 
    internal Employee(DataRowBuilder builder) 
     : base(builder) { 
    } 

    public Int64 Id { 
     get { return (Int64)base["Id"]; } 
     set { base["Id"] = value; } 
    } 

    public string FirstName { 
     get { return (string)base["Firstname"]; } 
     set { base["Firstname"] = value; } 
    } 

    public string Surname { 
     get { return (string)base["Surname"]; } 
     set { base["Surname"] = value; } 
    } 
    } 
} 

Und nun Basemodel Einführung, dass die obige Klasse


Basemodel erbt .cs

using System; 
using System.Data; 
using System.Collections; 
using System.Data.Common; 
using System.Data.SqlClient; 

namespace TypedDataSet { 

    public class BaseModel<T> : DataTable { 
     protected DbDataAdapter _adapter; 
     protected string _connectionString = TypedDataSet.Properties.Settings.Default.ConnectionString; 

     public BaseModel() { 
     } 

     protected DbDataAdapter Adapter(string sql) { 
      _adapter = new System.Data.SqlClient.SqlDataAdapter(sql, _connectionString); 
      SqlCommandBuilder cb = new SqlCommandBuilder((SqlDataAdapter)_adapter); 
      return _adapter; 
     } 

     public dynamic this[int index] { 
      get { return Rows[index]; } 
     } 

     public void Add(dynamic row) { 
      Rows.Add(row); 
     } 

     public void Remove(dynamic row) { 
      Rows.Remove(row); 
     } 

     public void Save() { 
      _adapter.Update(this); 
      this.AcceptChanges(); 
     } 

     public dynamic GetNewRow() { 
      dynamic row = (dynamic)NewRow(); 
      return row; 
     } 

     public IEnumerator GetEnumerator() { 
      return Rows.GetEnumerator(); 
     } 

     protected override Type GetRowType() { 
      return typeof(T); 
     } 
    } 
} 

die mir die Klasse mit dem folgenden Code zu verbrauchen erlaubt:


Employees employees = new Employees(true); 

Employee employee = employees.GetNewRow(); 
employee.FirstName = "Greg"; 
employee.Surname = "Focker"; 
employees.Add(employee); 

employees.Save(); 

foreach (Employee e in employees) { 
    Console.WriteLine(e.FirstName + ' ' + e.Surname); 
} 

Ich hoffe, dass diese weiteren Überstunden entwickeln so Zukunft Stackoverflow Benutzer, wenn Sie daran interessiert sind, Dieses kleine Projekt werfen Sie einen Blick auf http://bitbucket.org/Mozketo/typeddataset/, wo ich hoffe, den Code zu hosten.

+1

Wirklich interessante Antwort, aber mit einem gebrochenen bitbucket Verbindung ... – rohancragg

+0

Dank @Ben Clark-Robinson. Ich habe Ihre BaseModel-Implementierung in einem meiner Projekte verwendet. Ein Nebeneffekt, den ich erhalte, ist, dass es in Visual Studio 2012 die Funktionen Bearbeiten und Fortfahren unterbricht. Haben Sie das gleiche Problem gesehen und wie haben Sie es gelöst? – AllSolutions

+0

Ist es auch nicht möglich, NewRowFromBuilder() in das BaseModel zu verschieben? – AllSolutions

Verwandte Themen