Как выполнить рефакторинг запроса MongoDB .NET LINQ, который использует статический метод в инструкции select

#c# #.net #mongodb #linq

#c# #.net #mongodb #linq

Вопрос:

Недавно я обновил драйверы .NET MongoDB с устаревших на более новые. Многие запросы больше не работают, этот ставит меня в тупик.

        var dataSource = permissions.Select(x => new PermissionSetPermissionGridViewModel
        {
            Id = x.Id,
            PermissionGroupInfo = new KeyValuePair<Guid?, string>(x.PermissionGroupId, TitleHelper.GetPermissionGroupTitle(x.PermissionGroupId)),
            IsEnabled = x.IsEnabled,
            ObjectType = ObjectTypeIds.GetEnumValue(x.ObjectTypeId.Value)
        }).ToList()
  

Похоже, он не поддерживает статическую функцию TitleHelper.GetPermissionGroup() выдает следующую ошибку.

     [NotSupportedException]: GetPermissionGroupTitle of type Saturn.WebUI.Core.Helpers.TitleHelper is not supported in the expression tree GetPermissionGroupTitle({document}{PermissionGroupId}).
   at MongoDB.Driver.Linq.Translators.AggregateLanguageTranslator.TranslateMethodCall(MethodCallExpression node)
   at MongoDB.Driver.Linq.Translators.AggregateLanguageTranslator.TranslateMapping(ProjectionMapping mapping)
   at MongoDB.Driver.Linq.Translators.AggregateLanguageTranslator.TranslateMapping(ProjectionMapping mapping)
   at MongoDB.Driver.Linq.Translators.AggregateLanguageTranslator.TranslateValue(Expression node)
   at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslateProjectValue(Expression selector)
   at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslateSelect(SelectExpression node)
   at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslatePipeline(PipelineExpression node)
   at MongoDB.Driver.Linq.Translators.QueryableTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions)
   at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Execute(Expression expression)
   at MongoDB.Driver.Linq.MongoQueryableImpl`2.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Saturn.WebUI.Areas.Security.Controllers.PermissionSetRecordController.GetStaticPermissions(DataSourceRequest request, Guid permissionSetId) in C:worksaturn-developsaturnsrcSaturn.WebUIAreasSecurityControllersPermissionSetRecordController.cs:line 87
  

Как я могу реорганизовать этот запрос, чтобы он поддерживался более новыми драйверами?

Комментарии:

1. Используйте анализатор, такой как wireshark или fiddler, и проверьте статус ответа, чтобы увидеть, получаете ли вы 200 OK. Работает ли исходный код по-прежнему? Если это так, сравните исходные заголовки в первом запросе с нерабочими. ВОЗМОЖНО, у вас проблема с TLS. TLS 1.0 / 1.1 был прекращен в июне этого года. Недавно Microsoft выпустила новое обновление для системы безопасности на серверах, которые отключили TLS 1.0 / 1.1, и вы должны использовать TLS 1.2 или новее. Установленный вами новый драйвер, возможно, обновил ваши клиенты до TLS 1.2. Существует слишком много комбинаций, чтобы прямо сейчас сказать, что именно вызывает проблему. Результаты сниффера помогут.

2. Я почти уверен, что этот комментарий предназначался для другого вопроса

3. У вас проблема со временем выполнения, поскольку вы сказали, что запросы не выполняются. Не ошибки компилятора. Итак, проблемы связаны с более новым драйвером во время выполнения. Итак, почему вы не думаете, что мой ответ предназначен для другого вопроса?

Ответ №1:

Ваш GetPermissionGroupTitle(...) метод не может быть переведен в осмысленное выражение Mongo (у него нет эквивалента).

Что вы можете сделать, так это получить все необходимые данные в памяти, а затем впоследствии вызвать этот статический метод. В принципе, вы должны вызвать .ToList() , а затем другой .Select(...) , в котором вызвать ваш статический метод. Другой способ сделать это — использовать AutoMapper — мы вызываем такой вспомогательный метод расширения при сопоставлении между различными моделями. Примерно такой должна быть конфигурация:

 CreateMap<Permission, PermissionSetPermissionGridViewModel>()
    .ForMember(
        dest => dest.PermissionGroupInfo,
        cfg => cfg.MapFrom(src => new KeyValuePair<Guid?, string>( TitleHelper.GetPermissionGroupTitle(src.PermissionGroupId, src.PermissionGroupId))))