2

このコードは、この例のために簡略化されています。

クエリは実際にはサービスから返されるため、この方法でメソッドを記述したいと思います。

[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 を提供しているサービスのメソッドを使用できないため、私にとっては完全には機能しません。

もう 1 つの注意点は、Logging メソッドが IQueryable に変換された場合、すべてが正しく機能することです。しかし、クエリで Count を返す必要があるため、PageResult を返さなければなりません。

4

1 に答える 1

3

これは私が使用している回避策です。ODataQueryOptions からのフィルターのみを適用し、手動で Top と Skip を適用します。

まず、いくつかの拡張メソッドを作成しました。

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);
}
于 2013-08-02T02:01:16.443 に答える