在我的RIA域名服务中,我暴露了一个
的IQueryable<顾客>
在客户端上我可以像
一样查询DomainContext.Customers.Where(c => c.Id == theID)
我的问题是如何将此表达式添加到发送到数据库的查询中,因为我的域服务方法不会使用IQueryable。
在EF解析它并将sql发送到数据库之前,RIA或EF是否有任何“钩子”暴露以检查/操纵表达式? 任何关于RIA如何在引擎盖下工作的网址也会受到赞赏。
答案 0 :(得分:2)
我实际上遇到了你的帖子,因为我正在寻找完全相同的信息。我正在编写一个简单的MySql查询提供程序,用于RIA服务。由于没有答案,我认为即使问题有点陈旧,我也会添加我的发现。当您编写服务器端查询方法时,它可能是“IQueryable GetCustomers()”,但在客户端,您将拥有GetCustomersQuery()。实际获取数据的方式不是通过调用GetCustomers方法,而是通过调用Load方法并将查询传递给它。
关键是RIA将使用您的GetCustomers方法获取IQueryable,从客户端组合查询中获取表达式树并将它们组合在一起,然后才枚举IQueryable并返回结果。这就是查询提供程序可以看到您在客户端创建的表达式树的原因。有一种方法可以查看实体框架生成的SQL查询字符串,但我不确定如何(尝试查找ToTraceString方法)。
关于能够查看表达式树,您可以创建IQueryable和IQueryProvider接口的存根实现,并使用它来查看表达式树(用于调试)。这是一个用于实现这些接口的代码示例(从IQueryProvider中删除重要器官,大量借鉴The Wayward Weblog - Building an IQueryable Provider):
public class Query<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable
{
IQueryProvider provider;
Expression expression;
public Query(IQueryProvider provider)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
this.provider = provider;
this.expression = Expression.Constant(this);
}
public Query(IQueryProvider provider, Expression expression)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
if (expression == null)
{
throw new ArgumentNullException("expression");
}
if (!typeof(IQueryable<T>).IsAssignableFrom(expression.Type))
{
throw new ArgumentOutOfRangeException("expression");
}
this.provider = provider;
this.expression = expression;
}
Expression IQueryable.Expression
{
get { return this.expression; }
}
Type IQueryable.ElementType
{
get { return typeof(T); }
}
IQueryProvider IQueryable.Provider
{
get { return this.provider; }
}
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
}
}
public class QueryProvider : IQueryProvider
{
#region IQueryProvider Implementation
public IQueryable<T> CreateQuery<T>(Expression expression)
{
return new Query<T>(this, expression);
}
public IQueryable CreateQuery(Expression expression)
{
Type elementType = TypeSystem.GetElementType(expression.Type);
try
{
return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
public S Execute<S>(Expression expression)
{
return (S)this.Execute(expression);
}
public object Execute(Expression expression)
{
// You can write code here to look at the expression tree :P
return null;
}
#endregion
}