You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core中使用Like筛选带千分位的Decimal类型数据问题

问题:EF Core中Decimal类型列按千分位格式筛选的问题

数据库中有带精度的Decimal类型列,需要使用Entity Framework Core的Contains或Like函数执行包含千分位的筛选查询。在SQL Server中常用的实现语法如下:

SELECT * FROM Table WHERE CONVERT(VARCHAR(32), CONVERT(MONEY, Rate), 3) LIKE '%12,%'

尝试将数值类型转换为字符串时出现错误,代码如下:

.Where(x => x.Rate.ToString("N2").Contains($"{searchValue}"))

更新:错误信息

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null. (Parameter 'source')

at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Linq.Enumerable.Skip[TSource](IEnumerable`1 source, Int32 count)
at Game.BackEnd.Controllers.AdaDeyController.GetData(DataTableRequestModel post) in C:\MyGame\Game.BackEnd\Controllers\AdaDeyController.cs:line 261
at lambda_method216(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

更新:完整LINQ代码

var query = _context.AdaDey
    .Include(x => x.SourceSatu)
    .Include(y => y.TargetSatu)
    .Select(s => new AdaDey()
    {
        Id = s.Id,
        Date = s.StartDate,
        Rate = s.Rate,
        SourceSatu = new SourceSatu()
        {
            Id = s.Id,
            Code = s.SourceSatu!.Code,
            Name = s.SourceSatu.Name
        },
        TargetSatu = new TargetSatu()
        {
            Id = s.Id,
            Code = s.TargetSatu!.Code,
            Name = s.TargetSatu.Name
        }
    })
    .Where(x => (x.Rate).ToString("N2").Contains($"{searchValue}"));

更新:报错代码行(AdaDeyControllers.cs第261行)

return Json(new
                {
                    draw = post.draw,
                    recordsFiltered = dataResponse?.DataResponse?.Count ?? 0,
                    recordsTotal = totalRecords,
                    data = dataResponse?.DataResponse.Skip(skip).Take(post.length)
                }, opt);

解决方案

1. 解决千分位筛选问题

EF Core无法将ToString("N2")直接转换为SQL语句,导致查询无法在服务器端执行,甚至引发异常。要实现和SQL中CONVERT(VARCHAR(32), CONVERT(MONEY, Rate), 3)等价的逻辑,有两种可行方式:

方式一:使用参数化原生SQL查询

直接复用你熟悉的SQL语法,通过EF Core的FromSqlInterpolated实现参数化查询,避免SQL注入风险:

var query = _context.AdaDey
    .FromSqlInterpolated($"SELECT * FROM AdaDey WHERE CONVERT(VARCHAR(32), CONVERT(MONEY, Rate), 3) LIKE '%{searchValue}%'")
    .Include(x => x.SourceSatu)
    .Include(y => y.TargetSatu)
    .Select(s => new AdaDey()
    {
        Id = s.Id,
        Date = s.StartDate,
        Rate = s.Rate,
        SourceSatu = new SourceSatu()
        {
            Id = s.SourceSatu.Id,
            Code = s.SourceSatu.Code,
            Name = s.SourceSatu.Name
        },
        TargetSatu = new TargetSatu()
        {
            Id = s.TargetSatu.Id,
            Code = s.TargetSatu.Code,
            Name = s.TargetSatu.Name
        }
    });

方式二:映射SQL Server的FORMAT函数

通过自定义EF Core函数映射SQL Server的FORMAT函数,实现千分位格式化后筛选:
首先在DbContext中定义静态函数:

[DbFunction("FORMAT", "")]
public static string FormatDecimal(decimal value, string format)
{
    throw new NotImplementedException("此函数仅用于EF Core SQL转换,不会在客户端执行");
}

然后在查询中使用:

.Where(x => EF.Functions.Like(YourDbContext.FormatDecimal(x.Rate, "N2"), $"%{searchValue}%"))

2. 解决ArgumentNullException报错

报错是因为dataResponse?.DataResponse为null时调用Skip方法导致的,需要在调用前做空值判断,返回空集合替代:

return Json(new
{
    draw = post.draw,
    recordsFiltered = dataResponse?.DataResponse?.Count ?? 0,
    recordsTotal = totalRecords,
    data = dataResponse?.DataResponse?.Skip(skip).Take(post.length) ?? Enumerable.Empty<AdaDey>()
}, opt);

内容的提问来源于stack exchange,提问作者Amigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:54:53