Попытка создать дерево узлов с LINQ to SQL приводит к NotSupportedException - PullRequest
1 голос
/ 04 апреля 2019

У меня есть следующий код, который отлично работает внутри LINQPad, как вы можете видеть на скриншоте. Обратите внимание на часть Results в нижней части экрана, где показано дерево узлов:

LINQPad

Но , когда я запускаю его в своем приложении, оно показывает следующее исключение:

System.NotSupportedException Невозможно создать нулевое постоянное значение тип «System.Collections.Generic.IEnumerable`1 [[EverGas.Back.Domain.Temp.NodeDto, EverGas.Back.Domain.Temp, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = NULL]]». Только типы сущностей, типы перечисления или примитивные типы поддерживаются в этом контексте. ан System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate (ExpressionConverter родитель, ConstantExpression linq)

Полагаю, это Children = null во внутренней инициализации. Что я должен сделать, чтобы создать узел без детей?

Это полный код:

void Main()
{
    var query = from customer in EVG_T_M_SUJETO
                where customer.ID_SUJETO == 830
                from account in customer.EVG_T_G_CUENTA
                group account by customer
                into level1
                select new NodeDto
                {
                    Id = level1.Key.ID_SUJETO,
                    Text = level1.Key.DE_SUJETO,
                    Children = from cuenta in level1
                               from product in cuenta.EVG_T_G_CONTRATO
                               group product by cuenta
                        into level2
                               select new NodeDto
                               {
                                   Id = level2.Key.ID_CUENTA,
                                   Text = level2.Key.CD_CUENTA,
                                   Children = from cont in level2
                                              from link in cont.EVG_T_R_PRODUCTO_CONTRATO
                                              let prod = link.EVG_T_M_PRODUCTO
                                              group prod by cont
                                       into level3
                                              select new NodeDto
                                              {
                                                  Id = level3.Key.ID_CONTRATO,
                                                  Text = level3.Key.CD_CONTRATO,
                                                  Children = level3.Select(x => new NodeDto()
                                                  {
                                                      Id = x.ID_PRODUCTO,
                                                      Text = x.DE_PRODUCTO,
                                                      Children = null,
                                                  }),
                                              }
                               }

                };

    query.ToList().Dump();
}

class NodeDto
{
    public int Id { get; set; }
    public string Text { get; set; }
    public IEnumerable<NodeDto> Children { get; set; }
}

1 Ответ

3 голосов
/ 05 апреля 2019

Это ограничение проекции LINQ to Entities для EF6.

Вы не можете использовать Children = null из-за вышеупомянутого исключения во время выполнения. Enumerable.Empty<T>(), new List<T>, new T[] также не допускаются. И если вы пропустите эту строку, вы получите еще одно исключение (требование):

System.NotSupportedException: `Тип 'Пространство имен + NodeDto' появляется в двух структурно несовместимых инициализациях в рамках одного запроса LINQ to Entities. Тип может быть инициализирован в двух местах одного и того же запроса, но только если в обоих местах установлены одинаковые свойства и эти свойства установлены в одном и том же порядке.

К счастью, есть простой трюк - создайте производный тип и используйте его в проекции, где вам нужно пропустить Children. Например:

class LeafNodeDto : NodeDto { }

и затем на уровне 3:

 Children = level3.Select(x => new LeafNodeDto // <--
 {
     Id = x.ID_PRODUCTO,
     Text = x.DE_PRODUCTO,
 }),
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...