Перевод запроса LINQ в CRM QueryExpression при использовании «выбрать новый»

У меня есть следующий класс контейнера:

public class AssetAndItsDepositsContainer
    {
        public jp_asset Asset { get; set; }
        public jp_deposit Deposit { get; set; }
    }

Есть ли способ выполнить следующий запрос LINQ:

from a in serviceContext.jp_assetSet
join d in serviceContext.jp_depositsSet on a.Id equals d.jp_assetid.Id
where a.statecode == jp_assetState.Active &&
      a.jp_isonhold = true
select new AssetAndItsDepositsContainer()
{
     Asset = a,
     Deposit = d
})
.ToList();

И "перевести" его с помощью QueryExpression? Это то, что я придумал до сих пор, но я не знаю, как имитировать выражение select new:

QueryExpression query = new QueryExpression(jp_asset.EntityLogicalName);
query.ColumnSet = new ColumnSet(true);

query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)jp_assetState.Active);
query.Criteria.AddCondition("jp_isonhold", ConditionOperator.Equal, true);
LinkEntity link = query.AddLink(jp_deposit.EntityLogicalName, "Id", "jp_assetid", JoinOperator.Inner);

// Now what?
var res = service.RetrieveMultiple(query).Entities; // gets only jp_assets

person OfirD    schedule 03.07.2017    source источник


Ответы (2)


Вы не можете получить доступ ко всему LinkEntity, вы можете получить доступ только к его атрибутам как к свойствам AliasedValue самого основного Entity.

Я бы просто получил идентификатор второй записи, которую вы ищете, как часть EntityReference, а затем выполнил Retrieve.

person Dave Clark    schedule 03.07.2017
comment
Ваш ответ неверен. Учитывая тот факт, что мы можем получить доступ к атрибутам LinkEntity, мы вполне можем создавать объекты Entity из набора результатов. Просто используя метод Select выражения LINQ. - person Henk van Boeijen; 25.08.2017

На самом деле вы можете создавать допустимые Entity объекты из связанных сущностей. Единственное требование состоит в том, что первичный ключ связанного объекта должен быть доступен в наборе результатов.

Таким образом, ваш фрагмент кода может быть расширен следующим образом:

var query = new QueryExpression(jp_asset.EntityLogicalName);
query.ColumnSet.AllColumns = true;
query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)jp_assetState.Active);
query.Criteria.AddCondition("jp_isonhold", ConditionOperator.Equal, true);

LinkEntity link = query.AddLink(jp_deposit.EntityLogicalName, "Id", "jp_assetid", JoinOperator.Inner);
link.EntityAlias = "d";
link.Columns.AddColumns("jp_depositid", "jp_name");

IEnumerable<Entity> deposits = Service.RetrieveMultiple(query).Entities
    .Select(e => new Entity("jp_deposit")
    {
        Id = (Guid)e.GetAttributeValue<AliasedValue>("d.jp_depositid").Value,
        ["jp_name"] = e.GetAttributeValue<AliasedValue>("d.jp_name")?.Value
    });

Примечание

Приведенный выше пример будет надежно работать только для внутренних соединений. В результирующем наборе всегда будет доступен первичный ключ (ID) для связанной сущности. Поэтому можно безопасно получить его значение, используя синтаксис .Value. Все остальные значения атрибутов можно получить с помощью ?.Value.

Для левых соединений вам нужно будет сначала отфильтровать набор результатов, прежде чем выполнять Select.

person Henk van Boeijen    schedule 25.08.2017