实现IQueryable <t> </t>时对延迟执行的细粒度控制

时间:2011-08-30 00:08:40

标签: c# linq orm iqueryable deferred-execution

我正在实现IQueryable,到目前为止只为“Where”调用实现了一个表达式访问者,而其他所有内容当前都不受支持。表达式被翻译成本机T-SQL。我当然计划在一段时间内添加对其他方法调用的支持。

protected override Expression VisitMethodCall(MethodCallExpression m)
    {

        if (m.Method.DeclaringType == typeof(Queryable) && m.Method.Name == "Where")
        {

            sb.Append("SELECT * FROM (");

            this.Visit(m.Arguments[0]);

            sb.Append(") AS T WHERE ");

            LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);

            this.Visit(lambda.Body);

            return m;

        }

        throw new NotSupportedException(string.Format("Method '{0}' is not supported", m.Method.Name));

    }

由于我的'Where'支持使用延迟执行 - 我的问题是是否有可能和/或良好做法添加对其他方法的支持,例如'Select',其中引擎延迟执行没有使用,但它对使用IQueryable的任何人都是透明的。因此,在提供延迟解决方案之前,有一个可行的实施方案。

例如:

var _query = dbContext.Products
  .Where(x => x.ProductName == "") // deferred execution
  .Select(x => new { ... });       // cast ToList() under the hood and proceed

所以我想我的问题是双重的,

1)是否可能/实施起来有多容易?

2)这是一个好主意吗?

感谢。

1 个答案:

答案 0 :(得分:1)

当Linq-To-Sql中的某些内容无法转换为SQL时,它会抛出异常。然后,程序员必须考虑这一点,并在调用此类方法之前修改方法链以包含对.AsEnumerable的调用。 IMO,如果没有程序员知道(通过在引擎盖下调用.ToList),这比隐含地更明确。