C# 手工制作的强类型ADO.net DataTable-它能更干净吗?

C# 手工制作的强类型ADO.net DataTable-它能更干净吗?,c#,strongly-typed-dataset,C#,Strongly Typed Dataset,我最近遇到了一个非常简单的类型化数据表(没有使用.XSD)(我丢失了作者的URL,所以我不能相信他),但看起来有很多重复的代码(比如Add/Remove/GetNewRow方法) 我试图将重复的方法推到一个超类中,但由于员工需要泛型,我遇到了一些问题。我想让StackOverflow的集体蜂群思维提出一些想法来清理这个?(如果有可能的话?) 我相信我已经回答了我的问题。我不得不使用.NET4.0来获得我所希望的结果,特别是动态类型 因此,更改问题中的现有类: Employee.cs using

我最近遇到了一个非常简单的类型化数据表(没有使用.XSD)(我丢失了作者的URL,所以我不能相信他),但看起来有很多重复的代码(比如Add/Remove/GetNewRow方法)

我试图将重复的方法推到一个超类中,但由于员工需要泛型,我遇到了一些问题。我想让StackOverflow的集体蜂群思维提出一些想法来清理这个?(如果有可能的话?)


我相信我已经回答了我的问题。我不得不使用.NET4.0来获得我所希望的结果,特别是动态类型

因此,更改问题中的现有类:

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

我希望随着时间的推移进一步发展,这样,如果您对这个小项目感兴趣,未来的StackOverflow用户可以看看我希望在哪里托管代码。

如果您使用的是.net fwk 2.0或更高版本,您可以使用泛型。你的问题到底是什么?您想要实现什么?我正在使用.NET2.0。我不是100%确定如何用泛型实现这一点。我想要实现的是使用泛型和/或继承模型编写代码,这样当我创建更多的TypedDataset(如Employee、Product、Category等)时,我就不必将代码(Add()/Remove()/…)复制并粘贴到这些其他类中。但是可以创建一个新的“Product”类,该类免费随这些方法一起提供。当我以这种方式创建其他类型的数据表时看到重复,比如雇主类,我觉得一定有一种不那么重复的方式。谢谢@Ben Clark Robinson。我在我的一个项目中使用了您的BaseModel实现。我面临的一个副作用是,它会在VisualStudio2012中中断编辑并继续。您是否面临同样的问题以及如何解决它?另外,是否不可能将NewRowFromBuilder()移动到BaseModel?为什么使用“dynamic”而不是“T”泛型类型参数?此外,我们是否应该验证数据加载中是否确实存在所需的列名,以便确保像base[“Firstname”]这样的调用返回正确的值?
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);
        }
    }
}
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);
}