Как делать подзапросы в EntitySchemaQuery и фильтровать по ним
В стандартном блоке чтения данных есть способ фильтровать данных по наличию записей на детали, я хочу сделать тоже самое, но в entityschema query
как такое можно реализовать?
Сейчас мой метод выглядит так, но он не работает, как его следует изменить?
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
public string GetContactsBySubFilterDetail() {
EntitySchemaQuery esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
esq.AddColumn("Name");
EntitySchemaQuery subEsq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "ContactAddress");
subEsq.AddColumn(subEsq.CreateAggregationFunction(AggregationTypeStrict.Count, "Id"));
subEsq.Filters.Add(subEsq.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", "[Contact:Id:Id]"));
EntitySchemaQueryColumn subQueryColumn = esq.AddColumn(subEsq);
esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.GreaterOrEqual, subQueryColumn.Name, 1));
return esq.GetEntityCollection(UserConnection).ToJson();
}
Нравится
Добрый день,
На сколько я понял из кода, что Вы предоставили, то нужно выбрать имена всех контактов, у которых есть больше одного адреса. В теории это можно сделать через ESQ, но, увы, у меня не было примера такого подзапроса. Но: если переводить этот код в SQL запрос, то получим два варианта:
--Вариант 1
SELECT
[Contact].[Id], [Contact].[Name]
FROM
[Contact]
WHERE
(
SELECT
COUNT([Id])
FROM
[ContactAddress]
WHERE
[ContactAddress].[ContactId] = [Contact].[Id]
) > 1
--Вариант 2
SELECT
[c].[Name], [ca].[ContactId]
FROM
[Contact] [c]
INNER JOIN
[ContactAddress] [ca]
ON
[ca].[ContactId] = [c].[Id]
GROUP BY
[ca].[ContactId], [c].[Name]
HAVING
COUNT([ca].[ContactId]) > 1Что один, что второй запрос вернет нужную информацию. Второй запрос можно написать с применением Terrasoft.Core.DB.Select класса (с первым вариантом все сложнее). Протестировал в бизнес процессе - подход рабочий.
1) В методы бизнес процесса подключаем следующие пространства имен:
Terrasoft.Core.DB
Newtonsoft.Json
System
System.Collections.Generic
System.Data
Terrasoft.Common
Terrasoft.Core
2) В методы бизнес процесса добавляем приватный метод CreateJson:
private string CreateJson(IDataReader dataReader)
{
var list = new List<dynamic>();
var cnt = dataReader.FieldCount;
var fields = new List<string>();
for (int i = 0; i < cnt; i++)
{
fields.Add(dataReader.GetName(i));
}
while (dataReader.Read())
{
dynamic exo = new System.Dynamic.ExpandoObject();
foreach (var field in fields)
{
((IDictionary<String, Object>)exo).Add(field, dataReader.GetColumnValue(field));
}
list.Add(exo);
}
return JsonConvert.SerializeObject(list);
}3) В схеме бизнес процесса:
в скрипт-таске указываем код:
var result = "{}";
var select = new Select(UserConnection)
.Column("Contact","Name").As("Name")
.Column("ContactAddress","ContactId").As("ContactId")
.From("Contact")
.Join(JoinType.Inner, "ContactAddress")
.On("Contact", "Id").IsEqual("ContactAddress", "ContactId")
.GroupBy("ContactAddress", "ContactId")
.GroupBy("Contact", "Name")
.Having(Func.Count("ContactAddress", "ContactId")).IsGreater(Column.Parameter("1"))
as Select;
using (DBExecutor dBExecutor = UserConnection.EnsureDBConnection())
{
using (IDataReader dataReader = select.ExecuteReader(dBExecutor))
{
result = CreateJson(dataReader);
}
}
Set<string>("ResultJSON", result);
return true;4) Добавляем текстовый параметр с кодом ResultJSON в бизнес процесс.
5) Отображаем в автогенерируемой странице результат (значение параметра ResultJSON).
Результат:
Если нужны только имена, то из кода нужно убрать
.Column("ContactAddress","ContactId").As("ContactId")
Судя по Вашему коду, Вы будете использовать GetContactsBySubFilterDetail как эндпоинт кастомного сервиса, но сути не меняет, нужно использовать этот же подход с Terrasoft.Core.DB.Select классом. Просто добавьте нужные простраства имен, приватный метод CreateJson и перепишите свой метод GetContactsBySubFilterDetail и можете получить нужный результат.