Динамическое Linq Core OrderBy Nullable дочернее свойство - PullRequest
0 голосов
/ 16 января 2019

Когда я пытаюсь использовать библиотеку System.Linq.Dynamic.Core для заказа списка, я получаю NullReferenceException.

var myFinalOrderedList = myList.AsQueryable()
    .OrderBy("Company.Name asc, Process.Name asc, Reference.Name asc")
    .ToList();

Пустое исключение происходит на Reference.Name OrderBy, так как Reference имеет значение NULL.

Как мне заказать по обнуляемому Reference объекту?

StackTrace (конфиденциальная информация заменена на «****»):

    {
  "ClassName": "System.NullReferenceException",
  "Message": "Object reference not set to an instance of an object.",
  "Data": null,
  "InnerException": null,
  "HelpURL": null,
  "StackTraceString": "   at lambda_method(Closure , ControlActivity )\r\n   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)\r\n   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)\r\n   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)\r\n   at System.Linq.EnumerableSorter`1.ComputeMap(TElement[] elements, Int32 count)\r\n   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count, Int32 minIdx, Int32 maxIdx)\r\n   at System.Linq.OrderedEnumerable`1.GetEnumerator(Int32 minIdx, Int32 maxIdx)+MoveNext()\r\n   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)\r\n   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n   at ****.Dal.Repositories.ControlActivities.ControlActivityRepo.Search(ControlActivitySearchModel input) in C:\\Users\\****\\source\\Workspaces\\****\\Main\\****\\****.Dal\\Repositories\\ControlActivities\\ControlActivityRepo.cs:line 1189\r\n   at ****.Application.ControlActivities.ControlActivityService.Search(ControlActivitySearchModel input) in C:\\Users\\****\\source\\Workspaces\\****\\Main\\****\\****.Application\\ControlActivities\\ControlActivityService.cs:line 339\r\n   at ****.Api.Controllers.ControlActivityController.Search(String apikey, ControlActivitySearchModel input) in C:\\Users\\****\\source\\Workspaces\\****\\Main\\****\\****.Api\\Controllers\\ControlActivityController.cs:line 117",
  "RemoteStackTraceString": null,
  "RemoteStackIndex": 0,
  "ExceptionMethod": null,
  "HResult": -2147467261,
  "Source": "Anonymously Hosted DynamicMethods Assembly",
  "WatsonBuckets": null
}

Компания, Процесс и Ссылка являются внешними ключами основного списка (ControlActivity). У всех трех в основном просто есть PK Id и имя NVARCHAR. И Компания, и Процесс требуются для всех контрольных операций, и Ссылка не требуется.

1 Ответ

0 голосов
/ 16 января 2019

Я разобрался с ответом на свой вопрос с помощью ссылки, размещенной @Alen и https://github.com/StefH/System.Linq.Dynamic.Core/issues/98. Ниже я показываю немного больше моего реального кода, поэтому он выглядит иначе, чем вопрос , Ответ лежит с StaticMethod.ConvertToNullableNested. Например, я передаю {i.ColumnName} {i.SortOrder} = "Company.Name asc" и он возвращает Company == null ? null : Company.Name asc. Затем я добавляю каждый из сортов вместе и перехожу в OrderBy.

//TURN INTO QUERYABLE
var finalList = unionList.AsQueryable();

//DYNAMIC SORT
if (input.SortModel?.SortModelItems?.Count > 0)
{
    string sortQry = String.Empty;
    foreach (var i in input.SortModel.SortModelItems)
    {
        sortQry = sortQry + $"{StaticMethod.ConvertToNullableNested($"{i.ColumnName} {i.SortOrder}")}, ";
    }
    sortQry = sortQry.TrimEnd(", ");
    finalList = finalList.OrderBy(sortQry);
}

//RETURN AND REMEMBER TO .TAKE(Pagesize)
return Tuple.Create(finalList.Take(input.PageSize).ToList(), finalRowCount);

public static string ConvertToNullableNested(string expression, string result = "", int index = 0)
    {
        //Transforms => "a.b.c" to "(a != null ? (a.b != null ? a.b.c : null) : null)"
        if (string.IsNullOrEmpty(expression))
            return null;
        if (string.IsNullOrEmpty(result))
            result = expression;
        var properties = expression.Split(".");
        if (properties.Length == 0 || properties.Length - 1 == index)
            return result;
        var property = string.Join(".", properties.Take(index + 1));
        if (string.IsNullOrEmpty(property))
            return result;
        result = result.Replace(expression, $"{property} == null ? null : {expression}");
        return ConvertToNullableNested(expression, result, index + 1);
    }
...