5

我正在尝试应用这篇文章中的建议:Tip 22 - How to make Include really Include

它建议了一种解决方法,以确保在 Entity Framework (4.2) 中进行预加载工作。该解决方法涉及将 IQueryable 转换为 ObjectQuery。

但是,当我尝试这样做时,如帖子中所示,查询返回 null。

我的查询是(ctx 是一个 DbContext):

IEnumerable<Coupon> coupons =
    from x in ctx.Coupons
    where x.LanguageCode.Equals("EN", StringComparison.InvariantCultureIgnoreCase) && x.CategoryId == MainCategoryId && x.Date >= fromDate && x.Date <= toDate
    select x;

这按预期工作。

但是,当我使用时,

IEnumerable<Coupon> coupons =
    (from x in ctx.Coupons
     where x.LanguageCode.Equals("EN", StringComparison.InvariantCultureIgnoreCase) && x.CategoryId == MainCategoryId && x.Date >= fromDate && x.Date <= toDate
     select x) as ObjectQuery<Coupon>;

它将 null 分配给“优惠券”。

知道我做错了什么吗?

4

3 回答 3

5

从评论到答案:

ObjectQuery<T>只有当查询确实是 an 时,转换为 an才有效ObjectQuery<T>,它不会在任何其他 上工作IQueryable<T>。由于您使用的是 aDbContext而不是 a ObjectContext,因此查询属于不同的类型。但是,您不需要强制转换为正确的类型,命名空间DbExtensions.Include中的扩展方法System.Data.Entity接受任何IQueryable<T>类型,并调用适当的底层Include方法。您可以使用它,避免强制转换,从而避免在代码中明确指定查询的类型。

于 2011-12-17T18:07:50.727 回答
4

你正在做的相当于这个

IEnumerable<Coupon> coupons =
    from x in ctx.Coupons
    where x.LanguageCode.Equals("EN", StringComparison.InvariantCultureIgnoreCase) && x.CategoryId == MainCategoryId && x.Date >= fromDate && x.Date <= toDate
    select x;

ObjectQuery<Coupon> converted = coupons as ObjectQuery<Coupon>;

,coupons不为空且为converted空。

这意味着演员阵容失败。
这并不能解决您的问题,但至少可以识别它。

也许您正在使用不同版本的实体框架?

于 2011-12-16T18:37:20.927 回答
0

从实体框架获取 SQL 查询 IQueryable帮助我解决了这个问题以满足稍微不同的要求,我需要访问 TraceString底层参数,以便我可以将一些IQueryable<>表达式注入到.SqlQuery<>()

当您IQueryable在调试会话期间检查 an 时,您可以看到它在内部使用 ObjectQuery,但它不从 ObjectQuery继承,因此您不能直接转换它。然而,我们可以使用反射来访问内部查询对象。

这是 Steve Fenton 的代码封装到扩展方法中:

    /// <summary>
    /// Extract the Internal Object Query from an IQueryable, you might do this to access the internal parameters for logging or injection purposes
    /// </summary>
    /// <remarks>Sourced from https://www.stevefenton.co.uk/2015/07/getting-the-sql-query-from-an-entity-framework-iqueryable/ </remarks>
    /// <typeparam name="T">Entity Type that is the target of the query</typeparam>
    /// <param name="query">The query to inspect</param>
    /// <returns>Object Query that represents the same IQueryable Expression</returns>
    public static System.Data.Entity.Core.Objects.ObjectQuery<T> ToObjectQuery<T>(this IQueryable<T> query)
    {
        // force the query to be cached, otherwise parameters collection will be empty!
        string queryText = query.ToString();
        queryText = queryText.ToLower(); // stop compiler from optimising this code away because we don't do anything with queryText parameter!

        var internalQueryField = query.GetType().GetProperties(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("InternalQuery")).FirstOrDefault();
        var internalQuery = internalQueryField.GetValue(query);
        var objectQueryField = internalQuery.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("_objectQuery")).FirstOrDefault();
        return objectQueryField.GetValue(internalQuery) as System.Data.Entity.Core.Objects.ObjectQuery<T>;
    }

现在您的代码可能如下所示:

IEnumerable<Coupon> coupons =
    (from x in ctx.Coupons
     where x.LanguageCode.Equals("EN", StringComparison.InvariantCultureIgnoreCase) && x.CategoryId == MainCategoryId && x.Date >= fromDate && x.Date <= toDate
     select x).ToObjectQuery();
于 2019-03-21T15:13:26.243 回答