ठीक है - मैंने इसे समझ लिया।
निम्नलिखित परिणामस्वरूप केवल एक ही रावेन क्वेरी जारी की जा रही है, जो परिणाम, और परिणाम-गणना दोनों देता है।
इस क्षेत्र में उनके प्रयोगों के लिए David Ruttka पर धन्यवाद। मैंने अपने कोड को RavenDb के साथ काम करने के लिए अनुकूलित किया है। यह कोड परिणाम लौटाएगा, और परिणाम-डेटाबेस डेटाबेस क्वेरी के माध्यम से गिनती होगी, जैसा कि RavenDB का इरादा था।
मैंने नीचे अपना कोड जोड़ दिया है - इसका उपयोग करने के लिए, आपको अपनी वेबएपी विधि से IRavenQueryable<T>
वापस करना होगा (IQueryable<T>
नहीं)। फिर, आपके Uri के लिए $ inlinecount = allpages जोड़ना हैंडलर का आह्वान करेगा। यह कोड अन्य ओडीटा क्वेरी एक्सटेंशन ($ ले, $ वगैरह आदि) तोड़ नहीं देगा
नोट: यह कोड 'इनलाइन' तकनीक का उपयोग करता है, जिसमें संदेश संदेश में आंकड़े वापस आते हैं - आप कोड बदल सकते हैं यदि आपको पसंद आया तो शीर्षलेख में आंकड़ों को इंजेक्ट करने के लिए - मैंने अभी मानक तरीके से जाना चुना है जो ओडाटा काम करता है।
आप रावण उत्पन्न करने वाले किसी भी और सभी आंकड़ों को शामिल करने के लिए इस कोड को अनुकूलित कर सकते हैं।
एएसपी.NET के साथ हैंडलर पंजीकृत करने के लिए निम्न कोड का उपयोग करें (अपने Global.asax में।सीएस)
RegistrationCode:
GlobalConfiguration.Configuration.MessageHandlers.Add(new WebApi.Extensions.InlineRavenCountHandler());
हैंडलर कोड:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Reflection;
using System.Net.Http.Headers;
using System.Net;
namespace WebApi.Extensions
{
public class InlineRavenCountHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!ShouldInlineCount(request))
return base.SendAsync(request, cancellationToken);
// Otherwise, we have a continuation to work our magic...
return base.SendAsync(request, cancellationToken).ContinueWith(
t =>
{
var response = t.Result;
// Is this a response we can work with?
if (!ResponseIsValid(response)) return response;
var pagedResultsValue = this.GetValueFromObjectContent(response.Content);
Type queriedType;
// Can we find the underlying type of the results?
if (pagedResultsValue is IQueryable)
{
queriedType = ((IQueryable)pagedResultsValue).ElementType;
// we need to work with an instance of IRavenQueryable to support statistics
var genericQueryableType = typeof(Raven.Client.Linq.IRavenQueryable<>).MakeGenericType(queriedType);
if (genericQueryableType.IsInstanceOfType(pagedResultsValue))
{
Raven.Client.Linq.RavenQueryStatistics stats = null;
// register our statistics object with the Raven query provider.
// After the query executes, this object will contain the appropriate stats data
dynamic dynamicResults = pagedResultsValue;
dynamicResults.Statistics(out stats);
// Create the return object.
var resultsValueMethod =
this.GetType().GetMethod(
"CreateResultValue", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(
new[] { queriedType });
// Create the result value with dynamic type
var resultValue = resultsValueMethod.Invoke(
this, new[] { stats, pagedResultsValue });
// Push the new content and return the response
response.Content = CreateObjectContent(
resultValue, response.Content.Headers.ContentType);
return response;
}
else
return response;
}
else
return response;
});
}
private bool ResponseIsValid(HttpResponseMessage response)
{
// Only do work if the response is OK
if (response == null || response.StatusCode != HttpStatusCode.OK) return false;
// Only do work if we are an ObjectContent
return response.Content is ObjectContent;
}
private bool ShouldInlineCount(HttpRequestMessage request)
{
var queryParams = request.RequestUri.ParseQueryString();
var inlinecount = queryParams["$inlinecount"];
return string.Compare(inlinecount, "allpages", true) == 0;
}
// Dynamically invoked for the T returned by the resulting ApiController
private ResultValue<T> CreateResultValue<T>(Raven.Client.Linq.RavenQueryStatistics stats, IQueryable<T> pagedResults)
{
var genericType = typeof(ResultValue<>);
var constructedType = genericType.MakeGenericType(new[] { typeof(T) });
var ctor = constructedType
.GetConstructors().First();
var instance = ctor.Invoke(null);
var resultsProperty = constructedType.GetProperty("Results");
resultsProperty.SetValue(instance, pagedResults.ToArray(), null);
var countProperty = constructedType.GetProperty("Count");
countProperty.SetValue(instance, stats.TotalResults, null);
return instance as ResultValue<T>;
}
// We need this because ObjectContent's Value property is internal
private object GetValueFromObjectContent(HttpContent content)
{
if (!(content is ObjectContent)) return null;
var valueProperty = typeof(ObjectContent).GetProperty("Value", BindingFlags.Instance | BindingFlags.NonPublic);
if (valueProperty == null) return null;
return valueProperty.GetValue(content, null);
}
// We need this because ObjectContent's constructors are internal
private ObjectContent CreateObjectContent(object value, MediaTypeHeaderValue mthv)
{
if (value == null) return null;
var ctor = typeof(ObjectContent).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(
ci =>
{
var parameters = ci.GetParameters();
if (parameters.Length != 3) return false;
if (parameters[0].ParameterType != typeof(Type)) return false;
if (parameters[1].ParameterType != typeof(object)) return false;
if (parameters[2].ParameterType != typeof(MediaTypeHeaderValue)) return false;
return true;
});
if (ctor == null) return null;
return ctor.Invoke(new[] { value.GetType(), value, mthv }) as ObjectContent;
}
}
public class ResultValue<T>
{
public int Count { get; set; }
public T[] Results { get; set; }
}
}
आप के बजाय विधि मानकों के माध्यम से फिल्टर समर्थन विचार किया है? इस तरह से आप विधि रिटर्न से पहले परिणाम गिनती प्राप्त कर सकते हैं। – cecilphillip
ज़रूर - लेकिन फिर मुझे उन सभी तरीकों की भविष्यवाणी करनी होगी जो सेवा उपभोक्ता परिणाम को बाधित करना चाहते हैं। इससे बचें ओडाटा का पूरा बिंदु था - क्षमा करें, नहीं, यह कोई विकल्प नहीं है। – Adam
एकमात्र अन्य विकल्प जो मैं कल्पना कर सकता हूं कि आपके पास http हेडर वैल्यू – cecilphillip