使用NHibernate 3.2实现Repository(ORuM)(十)Linq Provider

LINQ扩展性

可通过多种方式来扩展 LINQ,以便能够在 LINQ 模式中查询任何数据源。 数据源可以是数据结构、Web 服务、文件系统或数据库等。 LINQ 模式使客户端可以轻松地查询能够进行 LINQ 查询的数据源,因为查询的语法和模式没有更改。

可通过以下方式将 LINQ 扩展到这些数据源:

  • 在某个类型中实现 IEnumerable<T> 接口,以使 LINQ to Objects 能够查询该类型。
  • 创建可扩展某个类型的标准查询运算符方法(比如 Where 和 Select),以使自定义 LINQ 能够查询该类型。
  • 为实现 IQueryable<T> 接口的数据源创建一个提供程序。 实现此接口的提供程序以表达式树的形式接收 LINQ 查询,提供程序能够以自定义方式(例如以远程方式)执行该查询。 
  • 为数据源创建一个利用现有 LINQ 技术的提供程序。 这种提供程序不仅能够进行查询,而且能够为用户定义的类型插入、更新和删除操作及映射。

LINQ查询数据源

  • 内存中的数据。通过两种方式,您可以使 LINQ 能够查询内存中数据。 如果数据的类型实现了 IEnumerable<T>,您可以使用 LINQ to Objects 来查询数据。 如果无法通过实现 IEnumerable<T> 接口来启用类型枚举,您可以在该类型中定义 LINQ 标准查询运算符方法,或创建可扩展该类型的 LINQ 标准查询运算符方法。 标准查询运算符的自定义实现应使用延迟执行来返回结果。
  • 远程数据。使 LINQ 能够查询远程数据源的最佳选项是实现 IQueryable<T> 接口。 但是,这与为数据源扩展提供程序(比如 LINQ to SQL)有所不同。 Visual Studio 中没有用于将现有 LINQ 技术(比如 LINQ to SQL)扩展为其他数据源类型的提供程序模型。

Linq Provider

实现 IQueryable<T> 的 LINQ 提供程序之间的复杂性可能差别很大。

  • 复杂性较低的 IQueryable 提供程序可与 Web 服务的一个方法交互。 这种类型的提供程序非常具体,因为它需要所处理的查询中有具体信息。 它有封闭的类型系统,可能会公开单一结果类型。 大多数查询都是在本地执行的,例如,通过使用标准查询运算符的 Enumerable 实现来执行。 复杂性较低的提供程序可能只会检查表示查询的表达式树中的一个方法调用表达式,并允许在其他地方处理查询的其余逻辑。
  • 中等复杂性的 IQueryable 提供程序可能针对具有部分可表达查询语言的数据源。 如果该提供程序针对 Web 服务,它可以与 Web 服务的多个方法进行交互,并基于查询提出的问题选择要调用的方法。 与简单提供程序相比,中等复杂性的提供程序的类型系统较丰富,但它仍然是固定类型系统。 例如,提供程序可以公开具有可遍历的一对多关系的类型,但将不会为用户定义的类型提供映射技术。
  • 复杂的 IQueryable 提供程序(比如 LINQ to SQL 提供程序)可以将完整的 LINQ 查询转换为可表达查询语言(如 SQL)。与复杂性较低的提供程序相比,复杂的提供程序更为全面,因为它能在查询中处理各种各样的问题。 它还具有开放的类型系统,因而必须包含广泛的基础结构来映射用户定义的类型。 开发复杂的提供程序需要耗费大量的精力。

Linq Provider实现方法

 实现 IQueryable LINQ 提供程序所需的接口: IQueryable<T>、 IOrderedQueryable<T>和 IQueryProvider。

System.Linq.IQueryable<T>接口

using System;
using System.Collections;
using System.Collections.Generic;
namespace System.Linq
{
public interface IQueryable<out T> : IEnumerable<T>, IQueryable, IEnumerable
{
}
}

System.Linq.IQueryable接口

using System;
using System.Collections;
using System.Linq.Expressions;
namespace System.Linq
{
public interface IQueryable : IEnumerable
{
Expression Expression
{
get;
}
Type ElementType
{
get;
}
IQueryProvider Provider
{
get;
}
}
}

System.Linq.IOrderedQueryable<T>接口

using System;
using System.Collections;
using System.Collections.Generic;
namespace System.Linq
{
public interface IOrderedQueryable<out T> : IQueryable<T>, IEnumerable<T>, IOrderedQueryable, IQueryable, IEnumerable
{
}
}

System.Linq.IOrderedQueryable接口

using System;
using System.Collections;
namespace System.Linq
{
public interface IOrderedQueryable : IQueryable, IEnumerable
{
}
}

System.Linq.IQueryProvider接口

using System;
using System.Linq.Expressions;
namespace System.Linq
{
public interface IQueryProvider
{
IQueryable CreateQuery(Expression expression);
IQueryable<TElement> CreateQuery<TElement>(Expression expression);
object Execute(Expression expression);
TResult Execute<TResult>(Expression expression);
}
}

 

Linq to Sql Provider

LINQ to SQL 是 .NET Framework 3.5 版的一个组件,提供了用于将关系数据作为对象管理的运行时基础结构。 

在 LINQ to SQL 中,关系数据库的数据模型映射到用开发人员所用的编程语言表示的对象模型。当应用程序运行时,LINQ to SQL 会将对象模型中的语言集成查询转换为 SQL,然后将它们发送到数据库进行执行。当数据库返回结果时,LINQ to SQL 会将它们转换回您可以用您自己的编程语言处理的对象。

LINQ to SQL只支持Sql Server数据库,它的Linq Provider实现是通过内部类System.Data.Linq.DataQuery。

System.Data.Linq.DataQuery<T>

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Linq.Provider;
using System.Data.Linq.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime;
using System.Runtime.CompilerServices;
namespace System.Data.Linq
{
internal sealed class DataQuery<T> : IOrderedQueryable<T>, IQueryable<T>, IQueryProvider, IEnumerable<T>, IOrderedQueryable, IQueryable, IEnumerable, IListSource
{
private DataContext context;
private Expression queryExpression;
private IBindingList cachedList;
Expression IQueryable.Expression
{
get
{
return this.queryExpression;
}
}
Type IQueryable.ElementType
{
get
{
return typeof(T);
}
}
IQueryProvider IQueryable.Provider
{
get
{
return this;
}
}
bool IListSource.ContainsListCollection
{
get
{
return false;
}
}
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public DataQuery(DataContext context, Expression expression)
{
this.context = context;
this.queryExpression = expression;
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
IQueryable IQueryProvider.CreateQuery(Expression expression)
{
if (expression == null)
{
throw Error.ArgumentNull("expression");
}
Type elementType = TypeSystem.GetElementType(expression.Type);
Type type = typeof(IQueryable<>).MakeGenericType(new Type[]
{
elementType
});
if (!type.IsAssignableFrom(expression.Type))
{
throw Error.ExpectedQueryableArgument("expression", type);
}
Type type2 = typeof(DataQuery<>).MakeGenericType(new Type[]
{
elementType
});
return (IQueryable)Activator.CreateInstance(type2, new object[]
{
this.context,
expression
});
}
IQueryable<S> IQueryProvider.CreateQuery<S>(Expression expression)
{
if (expression == null)
{
throw Error.ArgumentNull("expression");
}
if (!typeof(IQueryable<S>).IsAssignableFrom(expression.Type))
{
throw Error.ExpectedQueryableArgument("expression", typeof(IEnumerable<S>));
}
return new DataQuery<S>(this.context, expression);
}
object IQueryProvider.Execute(Expression expression)
{
return this.context.Provider.Execute(expression).ReturnValue;
}
S IQueryProvider.Execute<S>(Expression expression)
{
return (S)this.context.Provider.Execute(expression).ReturnValue;
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.context.Provider.Execute(this.queryExpression).ReturnValue).GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IEnumerable<T>)this.context.Provider.Execute(this.queryExpression).ReturnValue).GetEnumerator();
}
IList IListSource.GetList()
{
if (this.cachedList == null)
{
this.cachedList = this.GetNewBindingList();
}
return this.cachedList;
}
internal IBindingList GetNewBindingList()
{
return BindingList.Create<T>(this.context, this);
}
public override string ToString()
{
return this.context.Provider.GetQueryText(this.queryExpression);
}
}
}


LINQ 提供程序列表

出自:http://blogs.msdn.com/b/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx


LINQ to Amazon:http://weblogs.asp.net/fmarguerie/archive/2006/06/26/Introducing-Linq-to-Amazon.aspx
LINQ to Active Directory:http://www.codeplex.com/LINQtoAD
LINQ to Bindable Sources (SyncLINQ):http://paulstovell.net/blog/index.php/why-synclinq-should-matter-to-you/
LINQ over C# project:http://www.codeplex.com/LinqOverCSharp
LINQ to CRM:http://www.codeplex.com/LinqtoCRM
LINQ To Geo - Language Integrated Query for Geospatial Data:http://www.codeplex.com/LinqToGeo
LINQ to Excel:http://www.codeplex.com/xlslinq
LINQ to Expressions (MetaLinq):http://www.codeplex.com/metalinq
LINQ Extender (Toolkit for building LINQ Providers): http://www.codeplex.com/LinqExtender
LINQ to Flickr:http://www.codeplex.com/LINQFlickr
LINQ to Google:http://www.codeplex.com/glinq">
LINQ to Indexes (LINQ and i40):http://www.codeplex.com/i4o/Release/ProjectReleases.aspx?ReleaseId=3519
LINQ to IQueryable (Matt Warren on Providers):http://blogs.msdn.com/mattwar/archive/2007/08/09/linq-building-an-iqueryable-provider-part-vi.aspx
LINQ to JSON:http://james.newtonking.com/archive/2008/02/11/linq-to-json-beta.aspx
LINQ to NHibernate:http://www.ayende.com/Blog/archive/2007/03/17/Implementing-Linq-for-NHibernate-A-How-To-Guide--Part.aspx
LINQ to JavaScript:http://www.codeplex.com/JSLINQ
LINQ to LDAP:http://community.bartdesmet.net/blogs/bart/archive/2007/04/05/the-iqueryable-tales-linq-to-ldap-part-0.aspx
LINQ to LLBLGen Pro:http://weblogs.asp.net/fbouma/archive/2008/03/12/beta-of-linq-to-llblgen-pro-released.aspx
LINQ to Lucene:http://www.codeplex.com/linqtolucene
LINQ to Metaweb(freebase):http://www.codeplex.com/metawebToLinQ
LINQ to MySQL, Oracle and PostgreSql (DbLinq):http://code2code.net/DB_Linq/
LINQ to NCover:http://blog.joefeser.com/post/Linq-To-NCover-Part-2.aspx
LINQ to Opf3:http://www.liensberger.it/web/blog/?p=235
LINQ to Parallel (PLINQ):http://www.microsoft.com/downloads/details.aspx?FamilyID=e848dc1d-5be3-4941-8705-024bc7f180ba&amp;displaylang=en
LINQ to RDF Files:http://blogs.msdn.com/hartmutm/archive/2006/07/24/677200.aspx
LINQ to Sharepoint:http://www.codeplex.com/LINQtoSharePoint
LINQ to SimpleDB:http://www.codeplex.com/LinqToSimpleDB
LINQ to Streams:http://www.codeplex.com/Slinq/
LINQ to WebQueries:http://blogs.msdn.com/hartmutm/archive/2006/06/12/628382.aspx
LINQ to WMI:http://bloggingabout.net/blogs/emile/archive/2005/12/12/10514.aspx
LINQ to XtraGrid:http://cs.rthand.com/blogs/blog_with_righthand/archive/2008/02/23/LINQ-to-XtraGrid.aspx

 

源代码下载:http://mvcquick.codeplex.com/  

 

posted @ 2011-10-21 09:36  GuYoung  阅读(1450)  评论(1编辑  收藏  举报