c# - 从缓存列表查询 IQuery 返回 null 异常

标签 c# linq entity-framework caching

我一直在尝试 Peter Montgomery 的“缓存 LINQ 查询的结果”源代码 here

它为 IQueryable<T> 创建一个扩展方法返回 IEnumerable<T>如果可能的话,从缓存的数据中。主要扩展方法如下所示。

    /// <summary>
    /// Returns the result of the query; if possible from the cache, otherwise
    /// the query is materialized and the result cached before being returned.
    /// </summary>
    /// <param name="query">The IQueryable for which to return the query.</param>
    /// <param name="priority">The relative cache priority of the object.</param>
    /// <param name="slidingExpiration">The timespan indicating the duration of the sliding expiration</param>
    /// <returns>The result of the query; if possible from the cache</returns>
    /// <typeparam name="T">The type of entity for which to provide the method.</typeparam>
    public static IEnumerable<T> FromCache<T>(this IQueryable<T> query, CacheItemPriority priority, TimeSpan slidingExpiration)
    {
        string key = query.GetCacheKey();

        // try to get the query result from the cache
        var result = HttpRuntime.Cache.Get(key) as List<T>;

        if (result == null)
        {
            // TODO: ... ensure that the query results do not
            // hold on to resources for your particular data source
            //
            //////// for entity framework queries, set to NoTracking
            //////var entityQuery = query as ObjectQuery<T>;
            //////if (entityQuery != null)
            //////{
            //////    entityQuery.MergeOption = MergeOption.NoTracking;
            //////}

            // materialize the query
            result = query.ToList();

            HttpRuntime.Cache.Insert(
                key,
                result,
                null, // no cache dependency
                Cache.NoAbsoluteExpiration,
                slidingExpiration,
                priority,
                null); // no removal notification
        }

        return result;
    }

我使用这样的方法:

    /// <summary>
    /// Retrieves all instances of the specified type, if possible from the cache.
    /// Objects are maintained in a <see cref="T:System.Data.EntityState.Detached">Detached</see> state and 
    /// are not tracked in the <see cref="T:System.Data.Objects.ObjectStateManager">ObjectStateManager</see>. 
    /// </summary>
    /// <returns>A list of all instances of the specified type.</returns>
    /// <typeparam name="T">The type of entity for which to provide the method.</typeparam>
    public IQueryable<T> All<T>() where T : class, new()
    {
        //return new ObjectQuery<T>(GetSetName<T>(), this.context, MergeOption.NoTracking);
        return new ObjectQuery<T>(GetSetName<T>(), this.context, MergeOption.NoTracking).FromCache<T>().AsQueryable<T>();
    }

然后我会像这样过滤我的请求(查询 AdventureWorks 数据库示例):

List<Product> products = new List<Product>(readonlySession.All<Product>()
.Where(x => x.Color.Equals("Black", StringComparison.InvariantCultureIgnoreCase)));

我的问题是,当我尝试像这样查询数据时,我得到 NullReferenceException因为某些产品返回 null 属性 Color 。如果我在没有缓存的情况下查询实体,就没有问题。

谁能解释一下为什么会发生这种情况以及如何解决这个问题?

非常感谢。

更新:我发现使用 == 解决了我的问题,尽管我不知道为什么。不过,我希望能够使用 Equals()。

最佳答案

当您执行 x.Color.Equals("Black", StringComparison.InvariantCultureIgnoreCase) 且 Color 为 null 时,您将得到 null 异常,更好的方法是使用静态字符串方法,即使参数为 null,该方法也能工作,如下所示:

String.Equals(x.Color, "Black", StringComparison.InvariantCultureIgnoreCase)

关于c# - 从缓存列表查询 IQuery 返回 null 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4844433/

相关文章:

c# - 用另一个更新数据表

c# - 自定义 ValidationAttribute ErrorMessage 未按预期工作

c# - 使用 Func<T, TResult> 委托(delegate)

c# - 将 json 响应转换为列表

c# - 如何使用 dotnetbrowser 获取 ajax 请求响应正文?

C# 单元测试

c# - 将 SQL 转换为 EF Linq

entity-framework - EF 代码优先模型是否旨在完整描述数据库的结构?

c# - 如何在 Entity Framework 代码优先数据库中手动设置实体主键?

c# - 将 EF Core 查询从 2.2 转换为 3.0 - async await