asp.net-mvc - Web API + ODataQueryOptions + $top 或 $skip 导致 SqlException

标签 asp.net-mvc asp.net-web-api

此示例的代码已被简化。

查询实际上是从服务返回的,这就是为什么我更喜欢这样编写方法。

[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionLog> options)
{
    var query = from o in _exceptionLoggingService.entities.ExceptionDatas
                select new ExceptionLog {
                    ExceptionDataId = o.ExceptionDataId,
                    SiteId = o.SiteId,
                    ExceptionDateTime = o.ExceptionDateTime,
                    StatusCode = o.StatusCode,
                    Url = o.Url,
                    ExceptionType = o.ExceptionType,
                    ExceptionMessage = o.ExceptionMessage,
                    Exception = o.Exception,
                    RequestData = o.RequestData
                };

    var results = options.ApplyTo(query) as IEnumerable<ExceptionLog>;
    var count = results.LongCount();

    return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), count);
}

上述代码在“results.LongCount()”上出现错误,并出现以下异常:

SqlException: The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.

看来我在尝试分页时遇到了异常,例如“$top=2”。如果我的查询字符串是这样的“$filter=ExceptionDataId gt 100”,则一切正常。

由于 ExceptionData(实体)与 ExceptionLog(业务模型)匹配,我可以做这样的事情作为解决方法:

[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionData> options)
{
    var query = from o in _exceptionLoggingService.entities.ExceptionDatas
                orderby o.ExceptionDateTime descending
                select o;

    var results = from o in options.ApplyTo(query) as IEnumerable<ExceptionData>
                    select new ExceptionLog {
                        ExceptionDataId = o.ExceptionDataId,
                        SiteId = o.SiteId,
                        ExceptionDateTime = o.ExceptionDateTime,
                        StatusCode = o.StatusCode,
                        Url = o.Url,
                        ExceptionType = o.ExceptionType,
                        ExceptionMessage = o.ExceptionMessage,
                        Exception = o.Exception,
                        RequestData = o.RequestData
                    };

    return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), results.LongCount());
}

但这对我来说并不完全有效,因为它有点黑客,而且我无法使用已经为我提供了 IQueryable 的服务方法。

另一件事需要注意,如果 Logging 方法转换为 IQueryable,则一切正常。但我需要通过查询返回 Count,因此我必须返回 PageResult。

最佳答案

这是我正在使用的解决方法。我仅应用 ODataQueryOptions 中的过滤器,并手动应用“顶部”和“跳过”。

首先我创建了一些扩展方法:

using System;
using System.Collections.Generic;
using System.Linq;

namespace System.Web.Http.OData.Query
{
    public static class ODataQuerySettingsExtensions
    {
        public static IEnumerable<T> ApplyFilter<T>(this IQueryable<T> query, ODataQueryOptions<T> options)
        {
            if (options.Filter == null)
            {
                return query;
            }

            return options.Filter.ApplyTo(query, new ODataQuerySettings()) as IEnumerable<T>;
        }

        public static IEnumerable<T> ApplyTopAndTake<T>(this IEnumerable<T> query, ODataQueryOptions<T> options)
        {
            IEnumerable<T> value = query;

            if (options.Top != null)
            {
                value = value.Take(options.Top.Value);
            }

            if (options.Skip != null)
            {
                value = value.Skip(options.Skip.Value);
            }

            return value;
        }
    }
}

现在我的方法如下所示:

[HttpGet]
public PageResult<ExceptionLog> Logging(ODataQueryOptions<ExceptionLog> options)
{
    // GetLogs returns an IQueryable<ExceptionLog> as seen in Question above.
    var query = _exceptionLoggingService.GetLogs()
                                        .ApplyFilter(options);
    var count = query.Count();
    var results = query.ApplyTopAndTake(options);

    return new PageResult<ExceptionLog>(results, Request.GetNextPageLink(), count);
}

关于asp.net-mvc - Web API + ODataQueryOptions + $top 或 $skip 导致 SqlException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18006938/

相关文章:

asp.net-mvc - 发送 HTTP header 后服务器无法设置状态 IIS7.5

asp.net-mvc - 关于在 ASP.NET MVC 中放置 AntiXSS 调用的位置的建议

c# - 如何执行 HTTP POST 并将用户重定向到外部站点?

.net - 从本地主机连接到 asp.net web api 时出现 SSL 错误

iis - 使用 (LocalDb) 连接字符串在本地主机上托管 Web API 无法连接

c# - .NET Core 2.0 身份和 jwt?

c# - ASP.NET 中的 Twitter API 集成

c# - WebApi复杂类型uri/获取多个参数

asp.net-web-api - 如何在带有存储库的 Web Api 中使用 Redis 缓存

c# - 来自数据库的数据未返回,但正常列表是