C# 如何转换IQueryable<;T>;到ObjectQuery<;T>;?

C# 如何转换IQueryable<;T>;到ObjectQuery<;T>;?,c#,.net,iqueryable,eager-loading,objectquery,C#,.net,Iqueryable,Eager Loading,Objectquery,我试图运用这篇文章中的建议: 它建议了一种解决方法,以确保在实体框架(4.2)中加载工作正常。该解决方法涉及将IQueryable强制转换为ObjectQuery 但是,当我尝试这样做时,如本文所示,查询返回空值 我的查询是(ctx是DbContext): IEnumerable优惠券= 来自ctx中的x。优惠券 其中x.LanguageCode.Equals(“EN”,StringComparison.InvariantCultureIgnoreCase)和&x.CategoryId==Mai

我试图运用这篇文章中的建议:

它建议了一种解决方法,以确保在实体框架(4.2)中加载工作正常。该解决方法涉及将IQueryable强制转换为ObjectQuery

但是,当我尝试这样做时,如本文所示,查询返回空值

我的查询是(ctx是DbContext):

IEnumerable优惠券=
来自ctx中的x。优惠券

其中x.LanguageCode.Equals(“EN”,StringComparison.InvariantCultureIgnoreCase)和&x.CategoryId==MainCategoryId和&x.Date>=fromDate和&x.Date=fromDate和&x.Date您所做的与此等效

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>;
IEnumerable优惠券=
来自ctx中的x。优惠券

其中x.LanguageCode.Equals(“EN”,StringComparison.InvariantCultureInogoreCase)和&x.CategoryId==MainCategoryId和&x.Date>=fromDate和&x.Date从注释到答案:

转换到
ObjectQuery
仅在查询确实是
ObjectQuery
时有效,它不会在任何其他
IQueryable
上工作。由于使用的是
DbContext
而不是
ObjectContext
,因此查询的类型不同。但是,您不需要强制转换为正确的类型,
DbExtensions.Include
扩展方法在
System.Data.Entity
命名空间中接受任何
IQueryable
类型,并调用相应的底层
Include
方法。您可以使用它,避免强制转换,从而避免在代码中显式指定查询的类型。

帮助我解决了这个问题,以满足稍微不同的要求,我需要访问TraceString和底层参数,以便我可以将一些
IQueryable
表达式插入
.SqlQuery()

在调试会话期间检查
IQueryable
时,您可以看到它在内部使用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>;
    }
//
///从IQueryable中提取内部对象查询,您可以这样做来访问内部参数,以便进行日志记录或注入
/// 
///来源于https://www.stevefenton.co.uk/2015/07/getting-the-sql-query-from-an-entity-framework-iqueryable/ 
///作为查询目标的实体类型
///要检查的查询
///表示相同IQueryable表达式的对象查询
公共静态System.Data.Entity.Core.Objects.ObjectQuery ToObjectQuery(此IQueryable查询)
{
//强制缓存查询,否则参数集合将为空!
字符串queryText=query.ToString();
queryText=queryText.ToLower();//停止编译器优化此代码,因为我们不使用queryText参数!
var internalQueryField=query.GetType().GetProperties(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)。其中(f=>f.Name.Equals(“InternalQuery”)。FirstOrDefault();
var internalQuery=internalQueryField.GetValue(查询);
var objectQueryField=internalQuery.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)。其中(f=>f.Name.Equals(“_objectQuery”)).FirstOrDefault();
将objectQueryField.GetValue(internalQuery)返回为System.Data.Entity.Core.Objects.ObjectQuery;
}
现在,您的代码可以如下所示:

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();
IEnumerable优惠券=
(来自ctx中的x。优惠券

其中x.LanguageCode.Equals(“EN”,StringComparison.InvariantCultureIgnoreCase)&&x.CategoryId==MainCategoryId&&x.Date>=fromDate&&x.Date>如果您使用
var
而不是
IEnumerable
,会怎么样?
IQueryable
IEnumerable
不是一回事。您的ctx是DbContext还是ObjectContext?ObjectQuerys仅与ObjectContext一起使用。您还可以检查优惠券。GetType()在调试器中,查看查询的实际类型。谢谢。我更新了帖子,说我使用的是DBContext。在这种情况下,唯一的答案是“你不能将
IQueryable
转换为
ObjectQuery
,除非
IQueryable
确实是
ObjectQuery
”我想知道为什么你真的需要它。在你的查询中,你一开始就不需要解决方法,但是如果你需要的话,
(从ctx.coups中的x选择x)。包括(…)
不要耍花招,假设你使用的是System.Data.Entity;
?@Hvd.Thank。我在使用声明中没有System.Data.Entity,并且依赖Intellisense来确定允许使用什么-所以我认为我不能使用。包括在那里!然后开始阅读一篇“确认”的旧博文这是一种误解。我想,Doh!不应该在疲倦和沮丧的时候编写代码。如果你想发布答案,我会接受它——或者我会在几天后自我回答,参考你的评论。谢谢。这确实可能是因为这种变通方法不再适用,就像2009年发布的帖子一样。
    /// <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();