पर LINQ अभिव्यक्ति पास करें मेरे पास एक साधारण कस्टम क्वेरीप्रोवाइडर है जो अभिव्यक्ति लेता है, इसे SQL में अनुवाद करता है और एक SQL डेटाबेस से पूछताछ करता है।अन्य क्वेरीरीप्रोडर
मैं क्वेरीरीप्रोवाइडर में एक छोटा कैश बनाना चाहता हूं जो आमतौर पर एक्सेस की गई वस्तुओं को संग्रहीत करता है ताकि डाटाबेस हिट के बिना पुनर्प्राप्ति हो सके।
QueryProvider विधि
public object Execute(System.Linq.Expressions.Expression expression)
{
/// Builds an SQL statement from the expression,
/// executes it and returns matching objects
}
कैश इस QueryProvider कक्षा में एक क्षेत्र के रूप में बैठता है और एक सरल सामान्य सूची है।
यदि मैं List.AsQueryable विधि का उपयोग करता हूं और उपरोक्त अभिव्यक्ति को सूची में पास करता हूं। ऑक्साइबल के प्रदाता की निष्पादन विधि यह वांछित के रूप में काम नहीं करती है। ऐसा लगता है कि एक अभिव्यक्ति संकलित हो जाती है जब प्रारंभिक क्वेरीप्रोवाइडर एक अभिन्न हिस्सा बन जाता है।
क्या बाद में क्वेरीप्रोवाइडर को अभिव्यक्ति पारित करना संभव है और वांछित अभिव्यक्ति को निष्पादित करना संभव है? इस प्रकार
बुला कोड अस्पष्ट लग रहा है:
public class QueryProvider<Entity>()
{
private List<TEntity> cache = new List<Entity>();
public object Execute(System.Linq.Expressions.Expression expression)
{
/// check whether expression expects single or multiple result
bool isSingle = true;
if (isSingle)
{
var result = this.cache.AsQueryable<Entity>().Provider.Execute(expression);
if (result != null)
return result;
}
/// cache failed, hit database
var qt = new QueryTranslator();
string sql = qt.Translate(expression);
/// .... hit database
}
}
यह एक त्रुटि वापस नहीं करता है, बजाय इसे पाश जहां यह एक ही प्रदाता बार बार कहा जाता है में फंस जाता है।
यहां कुछ और कोड मैं क्या करने की कोशिश कर रहा हूँ दिखा रहा है:
संग्रह:
class Collection<Entity>
{
internal List<Entity> cacheOne { get; private set; }
internal Dictionary<Guid, Entity> cacheTwo { get; private set; }
internal Collection()
{
this.cacheOne = new List<Entity>();
this.cacheTwo = new Dictionary<Guid, Entity>();
}
public IQueryable<Entity> Query()
{
return new Query<Entity>(this.cacheOne, this.cacheTwo);
}
}
क्वेरी:
class Query<Entity> : IQueryable<Entity>
{
internal Query(List<Entity> cacheOne, Dictionary<Guid, Entity> cacheTwo)
{
this.Provider = new QueryProvider<Entity>(cacheOne, cacheTwo);
this.Expression = Expression.Constant(this);
}
internal Query(IQueryProvider provider, Expression expression)
{
this.Provider = provider;
if (expression != null)
this.Expression = expression;
}
public IEnumerator<Entity> GetEnumerator()
{
return this.Provider.Execute<IEnumerator<Entity>>(this.Expression);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public Type ElementType
{
get { return typeof(Entity); }
}
public System.Linq.Expressions.Expression Expression { get; private set; }
public IQueryProvider Provider { get; private set; }
}
QueryProvider:
class QueryProvider<Entity> : IQueryProvider
{
private List<Entity> cacheOne;
private Dictionary<Guid, Entity> cacheTwo;
internal QueryProvider(List<Entity> cacheOne, Dictionary<Guid, Entity> cacheTwo)
{
this.cacheOne = cacheOne;
this.cacheTwo = cacheTwo;
}
public IQueryable<TElement> CreateQuery<TElement>(System.Linq.Expressions.Expression expression)
{
return new Query<TElement>(this, expression);
}
public IQueryable CreateQuery(System.Linq.Expressions.Expression expression)
{
throw new NotImplementedException();
}
public TResult Execute<TResult>(System.Linq.Expressions.Expression expression)
{
return (TResult)this.Execute(expression);
}
public object Execute(System.Linq.Expressions.Expression expression)
{
Iterator<Entity> iterator = new Iterator<Entity>(expression, cacheOne, cacheTwo);
return (iterator as IEnumerable<Entity>).GetEnumerator();
}
}
इटरेटर:
class Iterator<Entity> : IEnumerable<Entity>
{
private Expression expression;
private List<Entity> cacheOne;
private Dictionary<Guid, Entity> cacheTwo;
internal Iterator(Expression expression, List<Entity> cacheOne, Dictionary<Guid, Entity> cacheTwo)
{
this.expression = expression;
this.cacheOne = cacheOne;
this.cacheTwo = cacheTwo;
}
public IEnumerator<Entity> GetEnumerator()
{
foreach (var result in (IEnumerable<Entity>)this.cacheOne.AsQueryable<Entity>().Provider.Execute(expression))
{
yield return result;
}
foreach (var more in (IEnumerable<Entity>)this.cacheTwo.Values.AsQueryable<Entity>().Provider.Execute(expression))
{
yield return more;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
कार्यक्रम:
class Program
{
static void Main(string[] args)
{
/// Create collection + caches
var collection = new Collection<Giraffe>();
collection.cacheOne.AddRange(new Giraffe[] {
new Giraffe() { Id = Guid.NewGuid(), DateOfBirth = new DateTime(2011, 03, 21), Height = 192, Name = "Percy" },
new Giraffe() { Id = Guid.NewGuid(), DateOfBirth = new DateTime(2005, 12, 25), Height = 188, Name = "Santa" },
new Giraffe() { Id = Guid.NewGuid(), DateOfBirth = new DateTime(1999, 04, 01), Height=144, Name="Clown" }
});
var cachetwo = new List<Giraffe>(new Giraffe[] {
new Giraffe() { Id = Guid.NewGuid(), DateOfBirth = new DateTime(1980, 03,03), Height = 599, Name="Big Ears" },
new Giraffe() { Id = Guid.NewGuid(), DateOfBirth = new DateTime(1985, 04, 02), Height= 209, Name="Pug" }
});
foreach (var giraffe in cachetwo)
collection.cacheTwo.Add(giraffe.Id, giraffe);
/// Iterate through giraffes born before a certain date
foreach (var result in collection.Query().Where(T => T.DateOfBirth < new DateTime(2006, 01, 01)))
{
Console.WriteLine(result.Name);
}
}
}
जिराफ:
class Giraffe
{
public Guid Id { get; set; }
public string Name { get; set; }
public long Height { get; set; }
public DateTime DateOfBirth { get; set; }
}
विशेष मामलों उदा सिंगल एंड डिफॉल्ट, इत्यादि छोड़ दिए गए हैं। जिस हिस्से में मैं काम करना चाहता हूं वह इटरेटर में होता है, जहां यह सबसे पहले शब्दकोश के निष्पादन से पहले सूची के क्वेरीप्रोवाइडर को निष्पादित करता है।
दो क्वेरी योग्य वस्तुओं में से एक डेटाबेस हो सकता है, या कुछ और।
क्या आप कॉलिंग कोड जोड़ सकते हैं? –
कॉलिंग कोड जोड़ा गया – Anthony
क्या आप लिंक अभिव्यक्ति का उदाहरण दे सकते हैं जिसका उपयोग आप अपने QueryProvider को कॉल करने के लिए कर रहे हैं? (मैं स्थानीय रूप से आपके कोड को पुनर्निर्माण करने की कोशिश कर रहा हूं)। साथ ही, क्या आप निष्पादन के सामान्य संस्करण को भी लागू करते हैं? 'सार्वजनिक ट्रेशल्ट निष्पादन (System.Linq.Expressions.Expression अभिव्यक्ति) {...}' –
CodingWithSpike