Access "a023 using nhib1_3.2 to implement repository (Orum) (10) LINQ provider"
Nhib.pdf. LINQ
After. NET Framework 3.5 provided the support for LINQ, the call for LINQ was once high, and various LINQ providers were even more powerful. He can integrate data query statements into programming languages and operate various data sources in a unified manner to reduce the complexity of data access. However, LINQ also provides excellent scalability, allowing developers to easily write their own LINQ providers.
In versions earlier than Nhibernate 3.0.0, The LINQ function does not exist. ayende plugin (maintenance has been stopped). It is a LINQ provider based on the criteria API, the main function is to convert a simple LINQ expression to the criteria API. Due to the limited functionality of the Criteria API, there are many inherent limitations (the join and subquery functions are not supported ). If you use nhibernate2.1.0ga or nhibernate2.1.2ga, you can download and use nhiberante. LINQ. dll,
Since nhibbench 3.0.0, the supported query methods for nhibbench query are added.
Hql ast analyzer-based LINQ provider for nhib.pdf 3.x. It was developed by Steve strong contributor and uses the third-party re-LINQ open-source framework at the underlying layer.
Nhib1_linq provider
Implementation process:
Nhib.pdf. LINQ. linqextensionmethods class
public static class LinqExtensionMethods
{
public static IQueryable<T> Query<T>(this ISession session)
{
return new NhQueryable<T>(session.GetSessionImplementation());
}
......
}
Nhibib. LINQ. nhqueryable <t> class
///<summary>
/// Provides the main entry point to a LINQ query.
///</summary>
public class NhQueryable<T> : QueryableBase<T>
{
// This constructor is called by our users, create a new IQueryExecutor.
public NhQueryable(ISessionImplementor session)
: base(new DefaultQueryProvider(session))
{
}
// This constructor is called indirectly by LINQ's query methods, just pass to base.
public NhQueryable(IQueryProvider provider, Expression expression)
: base(provider, expression)
{
}
}
Remotion. LINQ. queryablebase <t> class
public abstract class QueryableBase<T> : IOrderedQueryable<T>, IQueryable<T>,
IEnumerable<T>, IOrderedQueryable, IQueryable, IEnumerable
{
protected QueryableBase(IQueryProvider provider);
protected QueryableBase(IQueryParser queryParser, IQueryExecutor executor);
protected QueryableBase(IQueryProvider provider, Expression expression);
public Type ElementType { get; }
public Expression Expression { get; }
public IQueryProvider Provider { get; }
public IEnumerator<T> GetEnumerator();
}
Nhib.pdf. LINQ. inhqueryprovider Interface
public interface INhQueryProvider : IQueryProvider
{
object ExecuteFuture(Expression expression);
void SetResultTransformerAndAdditionalCriteria(IQuery query,
NhLinqExpression nhExpression, IDictionary<string, Tuple<object, IType>> parameters);
}
Nhib.pdf. LINQ. defaultqueryprovider class
public class DefaultQueryProvider : INhQueryProvider
{
public DefaultQueryProvider(ISessionImplementor session)
{
Session = session;
}
protected virtual ISessionImplementor Session { get; private set; }
#region IQueryProvider Members
public virtual object Execute(Expression expression)
{
IQuery query;
NhLinqExpression nhQuery;
NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);
return ExecuteQuery(nhLinqExpression, query, nhQuery);
}
public TResult Execute<TResult>(Expression expression)
{
return (TResult)Execute(expression);
}
public virtual IQueryable CreateQuery(Expression expression)
{
MethodInfo m = ReflectionHelper.GetMethodDefinition(
(DefaultQueryProvider p) => p.CreateQuery<object>(null))
.MakeGenericMethod(expression.Type.GetGenericArguments()[0]);
return (IQueryable)m.Invoke(this, new[] { expression });
}
public virtual IQueryable<T> CreateQuery<T>(Expression expression)
{
return new NhQueryable<T>(this, expression);
}
#endregion
public virtual object ExecuteFuture(Expression expression)
{
IQuery query;
NhLinqExpression nhQuery;
NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);
return ExecuteFutureQuery(nhLinqExpression, query, nhQuery);
}
protected NhLinqExpression PrepareQuery(Expression expression, out IQuery query,
out NhLinqExpression nhQuery)
{
var nhLinqExpression = new NhLinqExpression(expression);
query = Session.CreateQuery(nhLinqExpression);
nhQuery = query.As<ExpressionQueryImpl>().QueryExpression.As<NhLinqExpression>();
SetParameters(query, nhLinqExpression.ParameterValuesByName);
SetResultTransformerAndAdditionalCriteria(query, nhQuery, nhLinqExpression.ParameterValuesByName);
return nhLinqExpression;
}
protected virtual object ExecuteFutureQuery(NhLinqExpression nhLinqExpression,
IQuery query, NhLinqExpression nhQuery)
{
MethodInfo method;
if (nhLinqExpression.ReturnType == NhLinqExpressionReturnType.Sequence)
{
method = typeof(IQuery).GetMethod("Future").MakeGenericMethod(nhQuery.Type);
}
else
{
method = typeof(IQuery).GetMethod("FutureValue").MakeGenericMethod(nhQuery.Type);
}
object result = method.Invoke(query, new object[0]);
if (nhQuery.ExpressionToHqlTranslationResults.PostExecuteTransformer != null)
{
((IDelayedValue)result).ExecuteOnEval =
nhQuery.ExpressionToHqlTranslationResults.PostExecuteTransformer;
}
return result;
}
protected virtual object ExecuteQuery(NhLinqExpression nhLinqExpression,
IQuery query, NhLinqExpression nhQuery)
{
IList results = query.List();
if (nhQuery.ExpressionToHqlTranslationResults.PostExecuteTransformer != null)
{
try
{
return nhQuery.ExpressionToHqlTranslationResults.PostExecuteTransformer
.DynamicInvoke(results.AsQueryable());
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
if (nhLinqExpression.ReturnType == NhLinqExpressionReturnType.Sequence)
{
return results.AsQueryable();
}
return results[0];
}
private static void SetParameters(IQuery query, IDictionary<string, Tuple<object, IType>> parameters)
{
foreach (string parameterName in query.NamedParameters)
{
Tuple<object, IType> param = parameters[parameterName];
if (param.First == null)
{
if (typeof(ICollection).IsAssignableFrom(param.Second.ReturnedClass))
{
query.SetParameterList(parameterName, null, param.Second);
}
else
{
query.SetParameter(parameterName, null, param.Second);
}
}
else
{
if (param.First is ICollection)
{
query.SetParameterList(parameterName, (ICollection)param.First);
}
else if (param.Second != null)
{
query.SetParameter(parameterName, param.First, param.Second);
}
else
{
query.SetParameter(parameterName, param.First);
}
}
}
}
public void SetResultTransformerAndAdditionalCriteria(IQuery query,
NhLinqExpression nhExpression, IDictionary<string, Tuple<object, IType>> parameters)
{
query.SetResultTransformer(nhExpression.ExpressionToHqlTranslationResults.ResultTransformer);
foreach (var criteria in nhExpression.ExpressionToHqlTranslationResults.AdditionalCriteria)
{
criteria(query, parameters);
}
}
}
The remotion. LINQ. queryablebase <t> class is provided by re-LINQ.
Re-LINQ
From: http://relinq.codeplex.com/
With re-LINQ, it's now easier than ever to create full-featured LINQ providers.
Yes, you 've heard that before. But re-LINQ is the real thing:
- Instead of the iqueryable Expression Tree, re-LINQ gives you an abstract syntax tree that resembles the original LINQ query expression (the one usingFrom,WhereEtc. Keywords ).
- This works even when the original query was not a query expression, but a sequence of method invocations of where (), select () etc.
- You can easily extend or modify quieries using this representation in your application, directly or via a specification framework.
- In the process, re-LINQ gets rid of everything that iqueryable puts between you and your desired target query language:
- The structure is simplified (e.g., selectple is transformed back to multipleFrom-Sources ).
- Transparent identifiers are removed.
- Sub-queries are identified and can be handled as such.
- Expressions are evaluated up-front wherever possible.
- Special method callinserted by Visual Basic are "normalized" so that they are handled implicitly, should T if you choose to handle them differently.
- Re-LINQ handles even the most complex LINQ query expression, including joins, groups and nested queries.
- Re-LINQ gives you the tools to easily create your own provider, including:
- A set of visitors that you just implement for your transformation.
- A registry for translating methods to specific expressions in the target Query Language (like string methods, or icollection. Contains ).
- A mechanic to specify eager fetching for related objects or collections that will automatically create the required queries.
- Re-LINQ is completely agnostic of the target query language. you can use it to create any dialect of SQL as well as other query syntax ages such as xql or Entity SQL. currently, the nhib1_project uses re-LINQ to create hql ASTs.
Use nhib.pdf. LINQ
1,
using NHibernate.Linq;
2. Use the query <t> () Extension Method of the isession interface to create a nhib.pdf. LINQ query.
VaR query = session. query <user> (). Where (x => X. Username = "Zhang San"). tolist ();
The query <t> () Extension Method returns system. LINQ. iqueryable <t> In the nhib.pdf. LINQ. linqextensionmethods class.
Source code download: http://mvcquick.codeplex.com/