Постановка задачи задания ограничений на псевдодетейлы
Пусть сущности “Клиент” и “Кредит” связаны представленным на изображении образом.
Нужно ограничить клиентов, задав при этом ограничение на ссылающихся на них кредиты. Специфика данной задачи состоит в том, что согласно модели клиент не знает, какие кредиты на него ссылаются.
Задание ограничений на псевдодетейлы
Пусть:
var ds = (SQLDataService)DataServiceProvider.DataService;
Задание ограничение на псевдодетейлы чуть менее интуитивно, чем использование других возможностей LinqProvider.
Для задания ограничения на псевдодетейл в LinqProvider добавлена дополнительная сущность PseudoDetail
. Для PseudoDetail
доступно несколько вариантов конструктора.
Варианты конструктора PseudoDetail
(Большое число конструкторов обусловлено тем, что в Linq-выражении сложности с использованием конструкторов со значением по умолчанию).
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLinkName"> Имя связи от псевдодетейла к мастеру. </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
string masterLinkName)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLink"> Метод, определяющий имя связи от псевдодетейла к мастеру (определение идёт через "Information.ExtractPropertyPath(masterLink)"). </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
Expression<Func<TP, object>> masterLink)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении настоящий детейл (для псевдодетейлов данный метод будет некорректен).
/// </summary>
/// <param name="view"> Представление детейла. </param>
public PseudoDetail(
ICSSoft.STORMNET.View view)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLink"> Метод, определяющий имя связи от псевдодетейла к мастеру (определение идёт через "Information.ExtractPropertyPath(masterLink)"). </param>
/// <param name="masterToDetailPseudoProperty"> Имя связи от мастера к псевдодетейлу (псевдосвойство). </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
Expression<Func<TP, object>> masterLink,
string masterToDetailPseudoProperty)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLink"> Метод, определяющий имя связи от псевдодетейла к мастеру (определение идёт через "Information.ExtractPropertyPath(masterLink)"). </param>
/// <param name="masterToDetailPseudoProperty"> Имя связи от мастера к псевдодетейлу (псевдосвойство). </param>
/// <param name="masterConnectProperties"> Свойства мастера, по которым можно произвести соединение. Аналог OwnerConnectProp для <see cref="DetailVariableDef"/> в lcs. </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
Expression<Func<TP, object>> masterLink,
string masterToDetailPseudoProperty,
string[] masterConnectProperties)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLinkName"> Имя связи от псевдодетейла к мастеру. </param>
/// <param name="masterToDetailPseudoProperty"> Имя связи от мастера к псевдодетейлу (псевдосвойство). </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
string masterLinkName,
string masterToDetailPseudoProperty)
/// <summary>
/// Конструктор сущности, представляющей в Linq-выражении псевдодетейл.
/// </summary>
/// <param name="view"> Представление псевдодетейла. </param>
/// <param name="masterLinkName"> Имя связи от псевдодетейла к мастеру. </param>
/// <param name="masterToDetailPseudoProperty"> Имя связи от мастера к псевдодетейлу (псевдосвойство). </param>
/// <param name="masterConnectProperties"> Свойства мастера, по которым можно произвести соединение. Аналог OwnerConnectProp для <see cref="DetailVariableDef"/> в lcs. </param>
public PseudoDetail(
ICSSoft.STORMNET.View view,
string masterLinkName,
string masterToDetailPseudoProperty,
string[] masterConnectProperties)
Методы PseudoDetail
На псевдодетейлы возможно накладывать ограничения существования и всеобщности.
/// <summary>
/// Вспомогательный метод, преобразуемый на этапе компиляции Linq-выражения в funcExist.
/// </summary>
/// <returns> При компиляции вернёт true, при интерпретации в Linq формируется DetailVariableDef. </returns>
public bool Any()
/// <summary>
/// Вспомогательный метод, преобразуемый на этапе компиляции Linq-выражения в funcExist.
/// </summary>
/// <param name="predicate"> LimitFunction для псевдодетейла. </param>
/// <returns> При компиляции вернёт true, при интерпретации в Linq формируется DetailVariableDef. </returns>
public bool Any(Expression<Func<TP, bool>> predicate)
/// <summary>
/// Вспомогательный метод, преобразуемый на этапе компиляции Linq-выражения в funcExistExact.
/// </summary>
/// <param name="predicate"> LimitFunction для псевдодетейла. </param>
/// <returns> При компиляции вернёт true, при интерпретации в Linq формируется DetailVariableDef. </returns>
public bool All(Expression<Func<TP, bool>> predicate)
Ограничение существования на псевдодетейлы
Объект типа PseudoDetail
определяется вне linq-выражения:
var pseudoDetail = new PseudoDetail<Порода, Кошка>(
Information.GetView("КошкаE", typeof(Кошка)),
Information.ExtractPropertyPath<Кошка>(x => x.Порода));
// Все породы, для которых определены кошки
ds.Query<Порода>(Порода.Views.ПородаE).Where(
y => pseudoDetail.Any()).ToList();
Объект типа PseudoDetail
определяется внутри linq-выражения:
// Все породы, для которых определены кошки, у которых кличка не "Барсик"
ds.Query<Порода>(Порода.Views.ПородаE)
.Where(
y =>
new PseudoDetail<Порода, Кошка>(
Information.GetView("КошкаE", typeof(Кошка)),
Information.ExtractPropertyPath<Кошка>(x => x.Порода))
.Any(x.Кличка != "Барсик"))
.ToList();
Ограничение всеобщности на псевдодетейлы
// Все породы, где кошки не носят кличку "Барсик"
ds.Query<Порода>(Порода.Views.ПородаE)
.Where(
y =>
new PseudoDetail<Порода, Кошка>(
Information.GetView("КошкаE", typeof(Кошка)),
Information.ExtractPropertyPath<Кошка>(x => x.Порода))
.All(x.Кличка != "Барсик"))
.ToList();
PseudoDetail и DetailVariableDef
Ниже показан пример кода, демонстрирующий связь PseudoDetail
и DetailVariableDef.
ComparePseudoDetailWithDetailVariableDef
- это метод, проводящий конвертацию из linq в lcs и сравнивающий результаты.
const string masterToDetailPropertyName = "SomePropertyName";
var masterConnectProperties = new string[] { "Property1", "Property2" };
ComparePseudoDetailWithDetailVariableDef(
new PseudoDetail<Порода, Кошка>(
Information.GetView("КошкаE", typeof(Кошка)),
Information.ExtractPropertyPath<Кошка>(x => x.Порода),
masterToDetailPropertyName,
masterConnectProperties),
new DetailVariableDef(
this.ldef.GetObjectType("Details"),
masterToDetailPropertyName,
Information.GetView("КошкаE", typeof(Кошка)),
"Порода",
masterConnectProperties));