动态 Linq 核心 OrderBy 可空子 属性
Dynamic Linq Core OrderBy Nullable Child Property
当我尝试使用 System.Linq.Dynamic.Core
库来订购列表时,我得到了 NullReferenceException
。
var myFinalOrderedList = myList.AsQueryable()
.OrderBy("Company.Name asc, Process.Name asc, Reference.Name asc")
.ToList();
空异常发生在 Reference.Name
OrderBy
上,因为 Reference
可以为空。
如何按可为空的 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
}
Company、Process 和 Reference 是主列表 (ControlActivity) 的外键。这三个几乎都只有 PK Id 和 NVARCHAR 名称。所有控制活动都需要公司和流程,不需要参考。
在@Alen 发布的 link 和 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);
}
当我尝试使用 System.Linq.Dynamic.Core
库来订购列表时,我得到了 NullReferenceException
。
var myFinalOrderedList = myList.AsQueryable()
.OrderBy("Company.Name asc, Process.Name asc, Reference.Name asc")
.ToList();
空异常发生在 Reference.Name
OrderBy
上,因为 Reference
可以为空。
如何按可为空的 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
}
Company、Process 和 Reference 是主列表 (ControlActivity) 的外键。这三个几乎都只有 PK Id 和 NVARCHAR 名称。所有控制活动都需要公司和流程,不需要参考。
在@Alen 发布的 link 和 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);
}