Handcrafted Strongly Typed ADO.net DataTable - Can it be cleaner?

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I have recently come across a very simple Typed DataTable (without using a .XSD)(I've lost author's URL so I can't credit him) but it looks like there's a lot of duplicated code (Such as the Add/Remove/GetNewRow methods).

I've tried to push the repetitive methods into a super class, but I have issues due to the Employee needing to be generic. I was hoping to get StackOverflow's collective hive mind to suggest some ideas to clean this up? (If it's even possible at all?)

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:

I believe that I've answered my question, kind of. I've had to use .net 4.0 to get the results that I was hoping for specificially the dynamic type.

So changing the existing class in the question:

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; }     }   } } 

And now introducing BaseModel that the above class inherits


BaseModel.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);         }     } } 

Which allows me to consume the class using the following code:


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); } 

I hope to evolve this further overtime so future StackOverflow users if you're interested in this little project take a look at http://bitbucket.org/Mozketo/typeddataset/ where I hope to host the code.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!