Сильно типизированная таблица данных ADO.net, созданная вручную - может ли она быть чище? - PullRequest
1 голос
/ 30 июля 2009

Недавно я наткнулся на очень простой Typed DataTable (без использования .XSD) (я потерял URL автора, поэтому я не могу его кредитовать), но похоже, что там много дублированного кода (например, Add / Удалить / методы GetNewRow).

Я пытался поместить повторяющиеся методы в суперкласс, но у меня есть проблемы из-за того, что Сотрудник должен быть универсальным. Я надеялся заставить коллективный улей StackOverflow предложить некоторые идеи, чтобы очистить это? (Если это вообще возможно?)

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 Ответ

3 голосов
/ 30 июля 2009

Я считаю, что я ответил на мой вопрос, вроде. Мне пришлось использовать .net 4.0, чтобы получить результаты, на которые я надеялся, в частности, тип dynamic .

Таким образом, изменение существующего класса в вопросе:

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

А теперь вводим BaseModel, который наследует вышеприведенный класс


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

Что позволяет мне использовать класс, используя следующий код:


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

Я надеюсь развить эту дополнительную сверхурочную работу, поэтому будущие пользователи StackOverflow, если вы заинтересованы в этом небольшом проекте, взглянут на http://bitbucket.org/Mozketo/typeddataset/, где я надеюсь разместить код.

...