dotSITE
Форумы Work in Murano Software. Учебник по C#
новости материалы решения форумы группы настройки/о проекте
Логин/Регистрация
Логин:
Пароль:
Запомнить вас:
Регистрация
Забыли пароль?

Комментарии

Объектно-компонентная платформа создания приложений БД.

Примеры реализации объектного подхода к созданию приложений БД.

BD.ZIP
image001.gif
image002.gif
image003.gif

Введение

Во время работы над созданием приложений баз данных, работа, так или иначе, идет с некими объектами - сущностями.
Сущность ничто иное, как набор таблиц (впрочем, может быть и одна таблица), связанных между собой, и моделирующих некий объект реального мира.
Сущности могут иметь следующую функциональность:

  • посмотреть/показать список (всех экземпляров данной сущности);
  • добавить (экземпляр сущности);
  • сформировать отчет (ы);
  • отредактировать (экземпляр сущности);
  • удалить (экземпляр сущности);
  • и др.

Заметим, что некоторые методы (реализующие ту или иную функциональность) сущности, требуют задания параметров, например, для удаления, нужно задать ключ, для метода обновления данных, кроме ключа неплохо бы задать и другие параметры (характеризующие сущность).

Кодинг

Определим интерфейс сущности (исходные тексты приведены на C#):

 
public interface IDBEntity
{
  object List ();
  object Add (CDBEntityParameters dbEntityparameters);
  object Report (CDBEntityParameters dbEntityparameters);
  object Edit (CDBEntityParameters dbEntityparameters);
  object Delete (CDBEntityParameters dbEntityparameters);
}

Угу, правильно, забыли вписать в него свойство, идентифицирующее сущность, попросту говоря, наименование самой сущности, сразу же впишем и строку соединения с БД (все равно понадобится):

 
public interface IDBEntity
{
  string EntityName
  { get; }
  string ConnectionString
  { get; }
  object List ();
  object Add (CDBEntityParameters dbEntityParameters);
  object Report (CDBEntityParameters dbEntityParameters);
  object Edit (CDBEntityParameters dbEntityParameters);
  object Delete (CDBEntityParameters dbEntityParameters);
}

То есть теперь, мы можем написать, примерно такой код (с учетом определенного выше интерфейса и где-то, наверняка определенного класса CDBEntity, реализующего интерфейс IDBEntity):

 
CDBEntity Entity = new CDBEntity(“companies”, connectionString);
Entity.List();

Что должно произойти, при выполнении данного кода? Неплохо было бы, если б данный метод вернул содержимое того, что мы подразумеваем под сущностью “companies”, в данном случае, это могла бы быть таблица Entity.dbo.Companies (точно, угадали, все sql-скрипты, что могут быть приведены в данной статье, будут на T-SQL).

 
CDBEntity Entity = new CDBEntity(“companies”);
DataTable entityTable = Entity.List();
foreach( DataRow row in entityTable.Rows )
{
// а здесь мог бы быть код работы с таблицей
}

Думаем

Откуда класс CDEntity, мог бы узнать о том, что для сущности “companies” надо что-то делать (читать, удалять, обновлять, формировать набор данных для отчета) именно с таблицей Entity.dbo.Companies?

Метаданные

Многие из Вас, их уже когда-нибудь, как-нибудь, где-нибудь да использовали. Первый раз, я такое использовал году, эдак в 1996, когда писал автоматизированные рабочие места, попросту АРМы, на FoxPro 2.0/2.6 for DOS.
Определимся, что нам нужно для того, что бы наш класс CDBEntity, реализующий интерфейс IDBEntity, действительно мог бы реализовать методы работы с сущностями.
Определимся так же, что нам может потребоваться от такого класса, кроме как реализация очевидных методов работы с сущностью. Например, поддержка разграничения прав доступа пользователей (не каждому пользователю будет разрешено выполнять операцию удалить или добавить, а многим будет разрешено только смотреть).
Немного опережая события, замечу, что некоторые пользователи, не зная великий и могучий русский язык, захотят работать с приложениями, разработанными на основе описываемой архитектуры, но на других великих и могучих языках.

А теперь глянем на схему:


рис.1 (схема таблиц метаданных)

Посмотрим на содержимое некоторых таблиц:


рис.2 (table Entities)


рис.3 (table EntitySQLCommands)

А теперь глянем на реализацию метода, например, Edit:

 
public virtual void Edit (CDBEntityParameter[] dbEntityParameters)
{
  if (AllowDelete)
  {
    if ((FConnectionString != "") & (FEntityName != ""))
    {
      SqlConnection sqlCon = new SqlConnection( FConnectionString );
      try
      {
        sqlCon.Open(); 
      SqlCommand sqlComUpdate = new SqlCommand (FSqlExpressionUpdate, sqlCon);
        foreach (CDBEntityParameter par in dbEntityParameters)
        {
          if (FSqlExpressionUpdate.IndexOf(par.ParameterName  ) > 0)
  sqlComUpdate.Parameters.Add(par.ParameterName, par.ParameterType).Value = par.ParameterValue;
      }
        sqlComUpdate.ExecuteNonQuery();
    }
      catch ( SqlException ex )
    {
        Console.WriteLine( ex.Message );
      }
      finally
      {
        sqlCon.Close(); 
    }
}
  }
  else
  {
     throw( new Exception("You do not have permission to edit : " + FentityName)); 
  }
}      

Переменная FSqlExpressionUpdate может содержать, например, такое выражение: “exec Entity.dbo.UpdateCompany @id, @nameCompany”, а сама процедура Entity.dbo.UpdateCompany, может выглядеть, например, так:

 
create procedure dbo.UpdateCompany (@id int, @nameCompany nvarchar(50))
as
  set nocount on
  update Entity.dbo.Companies
    set nameCompany = @nameCompany
  where id = @id
go

А переменная FAllowUpdate содержит true, если текущий пользователь имеет право на редактирование данной сущности.

Думаем

Пожалуй, для реализации класса работающего с сущностями БД, используя метаданные, мы написали достаточно.
Теперь, надо бы подумать и о визуализации данных. То есть поговорим о контролах.
Для этого неплохо было бы, если бы, контрол знал о существовании сущности, с которой он работает, то есть:

 
public interface IDBControl
{
  IDBEntity Entity
  { get; set; }
}

Посмотрим на реализацию контрола, некий вариант ComboBox, точнее посмотрим только на реализацию того, что предопределено в интерфейсе:

 
public sealed class DBComboBox : System.Windows.Forms.UserControl, IDBControl
{
  public System.Windows.Forms.ComboBox cb;
  private IDBEntity FEntity;
  public IDBEntity Entity
  {
    get { return FEntity; }
    set { 
      FEntity = value; 
      if ( FEntity != null )
      {
        if (FEntity != null )
        {
          ...
          cb.DataSource = (DataTable)FEntity.List ();
          ...
        }
      }
    }
  }
  ...
}

Как видно из текста, при присвоении (в runtime) экземпляра сущности контролу, происходит инициализация DataSource, и контрол, в принципе, готов к использованию.
Наследником интерфейса IDBControl, можно сделать, практически любой компонент, например, System.Windows.Forms.Panel, System.Windows.Forms.Form. Вы, пока подумайте над перспективами, а я продолжу работать.

Кодинг

Предположим у нас уже есть, форма DBFormEntity, наследник IDBControl, есть также форма DBFormEntityList и DBFormEntityEdit. Первая, как можно догадаться из названия, отображает что-то списочное, например, для выбора (ListView, DataGrid, TreeVew), вторая предоставляет возможность редактирования экземпляров сущности.
Предположим даже, что у нас есть даже интерфейсы: IDBControl, IDBFormEntityList, IDFormEntityEdit.

Глянем на класс:

 
public class CEntity 
{
  public static object FormList(IDBEntity Entity)
  {
    object result = null;
    try
    {
      Assembly formAssembly = Assembly. LoadFrom (Entity.AssemblyNameList);
      Type formType = formAssembly.GetType(Entity.FormNameList
      FormEntityList form = (FormEntityList)Activator.CreateInstance(formType);
      form.Entity = Entity;
      if (form.ShowDialog() == DialogResult.OK)
      {
        result = form.KeyValue;
      }
    }
    catch
    {
    }
    return result;
  }
  public static object[] FormEdit(IDBEntity Entity)
  {
    object[] result = null;
    try
    {
      Assembly formAssembly = Assembly. LoadFrom (Entity.AssemblyNameEdit);
    Type formType = formAssembly.GetType(Entity.FormNameEdit
      FormEntityEdit form = (FormEntityEdit)Activator.CreateInstance(formType);
      form.Entity = Entity;
      if (form.ShowDialog() == DialogResult.OK)
      {
        result = form.Parameters;
      }
    }
    catch
    {
    }
    return result;
  }
}

Вызвать форму просмотра можно, например, так:

 
CEntity.FormList (Entity);

Резюме

Пару слов об организации solutions:

  • первый содержит описания всех интерфейсов и вспомогательных классов подобных CDBEntityParameters;
  • второй может содержать реализацию контролов и форм;
  • третий реализует интерфейс IDBEntity в классе CDBEntity;

Как организовать остальное, то есть формы, ориентированные на ту или иную сущность, реализацию классов сущностей (наследников CDBEntity или его экземпляры) и главную форму с реализацией метода Main(), наверное, уже не столь важно, впрочем, стоит внимательно и хорошо подумать и об этом.
Данная организация позволит разрабатывать как уже ставшие привычные двухуровневые системы, так и трехуровневые, используя COM+ или .NET Remoting.

Собственно это всё, читайте, думайте, спрашивайте, предлагайте.


Контакт Реклама на сайте Спонсорам Веб мастерам

Лицензионное соглашение - © 2000-2010 dotSITE
Хостинг .NET предоставлен PARKING.RU
Поддержку сайта осуществляет Murano Software Inc., Offshore software development