Spread the love

Применение tagged values в БД

   Применение стандартных методов проектирования баз данных не всегда удовлетворяет запросы программиста. Одно из ограничений – невозможность изменить набор атрибутов объекта после создания БД, что, при постоянно изменяемых требованиях заказчика, приводит к необходимости менять структуру БД (не потеряв при этом введенные данные), менять и заново отлаживать код программы, поля ввода/редактирования и т.д.
   Вашему вниманию предлагается один из способов решения этой проблемы — применение tagged values (TV , тэг-значений, или именованных значений).  
Сами значения хранятся в БД в строковом формате, но могут интерпретироваться в приложении по-разному, в зависимости от заданного типа значения. Аналог – всем известные ini-files! Основное преимущество применения TV – это возможность расширения списка значений в процессе исполнения приложения, без изменения структуры БД!
(image placeholder)

Список тэг-значений хранятся в таблице TaggedValue.

  • DefaultValue – это значение будет использоваться, если не задано действующее значение.
  • DefaultValueAlias – соответственно, значение для локализации.
  • ValueType – тип значения. Кроме стандартных типов, можно использовать свои, все зависит от фантазии разработчика. В зависимости от типа значения выбирается встроенный редактор значений. Например, для типа «OCL» используется редактор OCL-выражений. Для перечислимого типа производится выбор значений, которые хранятся в таблице TV_ValueSet. Возможен выбор из списка объектов БД – тогда надо задать ValuesListName.
  • Hint – подсказка при выборе/редактировании значения.
  • HintAlias – локализованная подсказка.
  • IsReadOnly – ну, это понятно.
  • ValuesListName – название класса объектов, из списка значений которых будет производиться выбор. Например «City», и тогда будет предложен выбор из списка ClassByExpressionName(‘City’).

   Список значений для набора объектов – в таблице TV_ValueSet. Например, для логического типа можно задать значения «True/False», а возможно и «Можно/Нельзя».
  Сами значения TV хранятся в таблице TV_Value. StringValue – действительное значение, значение, StringValueAlias – то, которое используется для локализации программы (или для показа юзеру ().

(image placeholder)

Для того, чтобы подключить к объекту тэг-значения, нужно создать ассоциацию типа n-n – OverridenTagedValues. Вся прелесть в том, что таким образом хранятся только переопределенные значения! Если нет значения – будет использоваться значение по-умолчанию! Классом такой ассоциации будет TV_Value, то есть, экземпляр класса – тэг-значение будет создан только при действительном вводе информации! Если грамотно подобрать умолчания, можно существенно сэкономить на размере БД!

Программная реализация.

Эта функция возвращает действующее тэг-значение по его имени. Если значение не было переопределено – возвращается значение по умолчанию.

function TMetaActorProperty.ActualValueByName(Tag: String): String;
var
  _TaggedValue:TTaggedValue;
  _TV_Value:TTV_Value;
begin
  _TaggedValue:=Self.TaggedValues.EvaluateExpressionAsDirectElement(‘self->select(name=’+QuotedStr(Tag)+’)->first’) as TTaggedValue;
  if Self.OverridenTaggedValues.Includes(_TaggedValue) then begin
    _TV_Value:=Self.TV_Value.BoldObjects[Self.OverridenTaggedValues.IndexOf(_TaggedValue)];
    Result:=_TV_Value.StringValue;
  end
  else
    Result:=Self.TaggedValues.EvaluateExpressionAsString(‘self->select(name=’+QuotedStr(Tag)+’)->first.defaultValue’, 1);
end;

Эта процедура устанавливает тэг-значение.

procedure TMetaActorProperty.SetTVByName(Tag: String; Value: String);
var
  _TaggedValue:TTaggedValue;
  _TV_Value:TTV_Value;
  Overriden: Boolean;
begin
  _TaggedValue:=LocateInList(Self.TaggedValues, ‘name’, Tag) as TTaggedValue;
  if not Assigned(_TaggedValue) then begin
     MsgError(Self.Name+’: Not found TV=’+Tag);
     Exit;
  end;  
  Overriden:=Self.OverridenTaggedValues.Includes(_TaggedValue);
  if Overriden then begin //Ранее было переопределено
    _TV_Value:=           //Найдем переопределенное значение
      Self.TV_Value.BoldObjects[Self.OverridenTaggedValues.IndexOf(_TaggedValue)];
    if (Value=_TaggedValue.DefaultValue) then //Если ввели значение по умолчанию — удалим переопределенное
       Self.OverridenTaggedValues.Remove(_TaggedValue)
    else  //Ранее было переопределено и изменили значение
      _TV_Value.StringValue:=Value;
  end
  else   //Ранее было по умолчанию
  begin
    Assert(Assigned(_TaggedValue), ‘SetTVByName’);
    Self.OverridenTaggedValues.Add(_TaggedValue);
    _TV_Value:=           //Найдем переопределенное значение
      Self.TV_Value.BoldObjects[Self.OverridenTaggedValues.IndexOf(_TaggedValue)];
    _TV_Value.StringValue:=Value;
  end;
end;

Функция дает список подключенных тэг-значений.

function TMetaActorProperty.TaggedValues: TTaggedValueList;  //Find TaggedValueList
var
  expr: string;
begin
  Result:=nil;
  if not Assigned(Self) then Exit;
  expr:=’TV_Section.allInstances->select(name=’+QuotedStr(Self.MetaClassName)+’)->first.taggedValues’;
  Result:=TBoldSystem.DefaultSystem.EvaluateExpressionAsDirectElement(expr)as TTaggedValueList;
end;

Такие тэг-значения удобны для сохранения в БД настроек программы, быстрого создания прототипов проекта для согласования с заказчиком и добавления/изменения атрибутов на «лету» (в дальнейшем, после обкатки приложения, легко все оформить в виде «настоящих» атрибутов).

Для  создания/редактирования тэг-значений применяется редактор на основе компонента TCommonInspector из пакета Greatis — http://www.greatis.com.

Работа с мультимедийным таймером на Win API

Читать на сайте автора.

Построение графиков с использованием компонента gl.ocx

Читать на сайте автора.

Работа с таймером на Win API

Читать на сайте автора.

Работа со шрифтами на Win API

Читать на сайте автора.

Создание группы RadioButton средствами Win API

Читать на сайте автора.

Создание RadioButton средствами Win API

Читать на сайте автора.

Создание CheckBox’ов средствами Win API

Читать на сайте автора.

Создание поля для ввода текста на Win API

Читать на сайте автора.

Создание кнопок средствами Win API

Читать на сайте автора.