我正在尝试在这篇文章中应用这些建议:Tip 22 - How to make Include really Include
它建议在实体框架(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>;
它为“优惠券”指定了空值。
知道我做错了吗?
答案 0 :(得分:5)
从评论到答案:
转换为ObjectQuery<T>
仅在查询确实为ObjectQuery<T>
时才有效,但不适用于任何其他IQueryable<T>
。由于您使用的是DbContext
而不是ObjectContext
,因此查询的类型不同。但是,您不需要强制转换为正确的类型,DbExtensions.Include
命名空间中的System.Data.Entity
扩展方法接受任何IQueryable<T>
类型,并调用相应的基础Include
方法。您可以使用它,避免强制转换,从而避免在代码中明确指定查询的类型。
答案 1 :(得分: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
为空。
这意味着演员阵容失败 这并不能解决您的问题,但至少可以识别它。
也许您使用的是不同版本的Entity Framework?
答案 2 :(得分:0)
Getting the SQL Query From an Entity Framework IQueryable帮助我解决了这个问题,以满足稍有不同的要求,我需要访问TraceString AND 基础参数,以便可以向其中注入一些IQueryable<>
表达式.SqlQuery<>()
在调试会话期间检查
IQueryable
时,您会看到它在内部使用ObjectQuery,但是它没有从ObjectQuery中 Inherit 继承,因此您无法直接对其进行强制转换。但是,我们可以使用Reflection访问内部查询对象。
以下是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();