如何缓存“IQueryable”.First”结果?

发布于 2024-09-15 16:14:35 字数 1777 浏览 2 评论 0原文

我有两个类似的查询:

ICmOption optionRes = CmOptionRepository<ICmOption>
            .GetAll()
            .Where(option => option.Name == strCommandName && option.Data == strCommandOption)
            .FirstOrDefault()
            ;

IErrorType errorType = ErrorTypeRepository<IErrorType>
                    .GetAll()
                    .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                    .First()
                    ;

在这两种情况下都会从数据库中获取常量数据。由于这个原因,我想缓存这些查询的结果...

一个请求的最简单的解决方案是:

    public IErrorType GetErrorType(IComponent component, string strErrorCode)
    {
        IErrorType errorType;

        string strKey = string.Concat(component.Id, "_", strErrorCode);
        lock (Dict)
        {
            if (Dict.ContainsKey(strKey))
            {
                errorType = Dict[strKey];
            }
            else
            {
                errorType = Repository
                    .GetAll()
                    .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                    .First()
                    ;
                Dict.Add(strKey, errorType);
            }
        }
        return errorType;
    }

    private static Dictionary<string, IErrorType> Dict { get { return _dict; } }

    private static readonly Dictionary<string, IErrorType> _dict
        = new Dictionary<string, IErrorType>();

我确实需要第二个实体的类似解决方案,并且还会有更多...所以我想创建一个类(CachableRepository )将接受参数,检查它们的对象是否已缓存,如果没有 - 从数据库获取数据并放入缓存。这应该适用于不同数量的参数。

问题是:我没有看到一种简单的方法如何为不同参数创建缓存密钥,以及如何为这些参数构建 lambda 函数...

如果您有什么想法或建议,请分享。

多谢!

I have 2 similar queries:

ICmOption optionRes = CmOptionRepository<ICmOption>
            .GetAll()
            .Where(option => option.Name == strCommandName && option.Data == strCommandOption)
            .FirstOrDefault()
            ;

IErrorType errorType = ErrorTypeRepository<IErrorType>
                    .GetAll()
                    .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                    .First()
                    ;

In both cases constant data from DB are fetched. Due to this reason I want to cache results of these queries...

the simplest solution for one request is:

    public IErrorType GetErrorType(IComponent component, string strErrorCode)
    {
        IErrorType errorType;

        string strKey = string.Concat(component.Id, "_", strErrorCode);
        lock (Dict)
        {
            if (Dict.ContainsKey(strKey))
            {
                errorType = Dict[strKey];
            }
            else
            {
                errorType = Repository
                    .GetAll()
                    .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                    .First()
                    ;
                Dict.Add(strKey, errorType);
            }
        }
        return errorType;
    }

    private static Dictionary<string, IErrorType> Dict { get { return _dict; } }

    private static readonly Dictionary<string, IErrorType> _dict
        = new Dictionary<string, IErrorType>();

I do need the similar for the 2nd entity, and few more are coming... So I want to create a class (CachableRepository) that will accept parameters, check if object for them is cached already, if not - get data from DB and put to cache. And this should work for different number of parameters..

The problem is: I don't see a simple way how to create a key for cache for a different parameters, and how to build a lambda-function for these parameters...

If you have any thought or suggestion, please share them.

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

堇色安年 2024-09-22 16:14:35

我自己的“快速”解决方案:

internal class CacheManager<TIEntity>
    where TIEntity : IEntity
{
    internal TIEntity GetObject(string strKey, Func<TIEntity> funcGetEntity)
    {
        TIEntity entity;
        lock (Dict)
        {
            if (Dict.ContainsKey(strKey))
            {
                entity = Dict[strKey];
            }
            else
            {
                entity = funcGetEntity();
                Dict.Add(strKey, entity);
            }
        }
        return entity;
    }

    private Dictionary<string, TIEntity> Dict { [DebuggerStepThrough] get { return _dict; } }

    private readonly Dictionary<string, TIEntity> _dict = new Dictionary<string, TIEntity>();
}


    public IErrorType GetErrorType(IComponent component, string strErrorCode)
    {
        string strKey = string.Concat(component.Id, "_", strErrorCode);
        IErrorType errorType = _sCacheManager.GetObject(
            strKey,
            () => Repository
                .GetAll()
                .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                .First()
            );
        return errorType;
    }

    private static CacheManager<IErrorType> _sCacheManager = new CacheManager<IErrorType>();

如果您看到任何更好的选择,请告诉我。

多谢!

My own 'quick' solution:

internal class CacheManager<TIEntity>
    where TIEntity : IEntity
{
    internal TIEntity GetObject(string strKey, Func<TIEntity> funcGetEntity)
    {
        TIEntity entity;
        lock (Dict)
        {
            if (Dict.ContainsKey(strKey))
            {
                entity = Dict[strKey];
            }
            else
            {
                entity = funcGetEntity();
                Dict.Add(strKey, entity);
            }
        }
        return entity;
    }

    private Dictionary<string, TIEntity> Dict { [DebuggerStepThrough] get { return _dict; } }

    private readonly Dictionary<string, TIEntity> _dict = new Dictionary<string, TIEntity>();
}


    public IErrorType GetErrorType(IComponent component, string strErrorCode)
    {
        string strKey = string.Concat(component.Id, "_", strErrorCode);
        IErrorType errorType = _sCacheManager.GetObject(
            strKey,
            () => Repository
                .GetAll()
                .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                .First()
            );
        return errorType;
    }

    private static CacheManager<IErrorType> _sCacheManager = new CacheManager<IErrorType>();

Please let me know if you see any better option.

Thanks a lot!

定格我的天空 2024-09-22 16:14:35

我几乎在任何地方都使用此方法来处理 ASP.NET 缓存中的缓存对象,可以将其修改为缓存在字典中。

public static T GetOrInsert<T>(string cacheKey, Func<T> creator)
{
    object cacheItem = HttpRuntime.Cache.Get(cacheKey);
    if (cacheItem is T)
    {
        return (T)cacheItem;
    }
    else
    {
        T newItem = creator();
        HttpRuntime.Cache.Insert(cacheKey, newItem);

        return newItem;
    }
}

然后你可以像这样使用它

public IErrorType GetErrorType(IComponent component, string strErrorCode)
{
    string strKey = string.Concat(component.Id, "_", strErrorCode);
    return CacheUtil.GetOrInsert<IErrorType>( strKey, 
            () => Repository
                .GetAll()
                .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                .First()
    );
}

I use this method pretty much everywhere to handle caching objects in the ASP.NET cache, it could be modified to cache in a Dictionary instead.

public static T GetOrInsert<T>(string cacheKey, Func<T> creator)
{
    object cacheItem = HttpRuntime.Cache.Get(cacheKey);
    if (cacheItem is T)
    {
        return (T)cacheItem;
    }
    else
    {
        T newItem = creator();
        HttpRuntime.Cache.Insert(cacheKey, newItem);

        return newItem;
    }
}

You can then use it like

public IErrorType GetErrorType(IComponent component, string strErrorCode)
{
    string strKey = string.Concat(component.Id, "_", strErrorCode);
    return CacheUtil.GetOrInsert<IErrorType>( strKey, 
            () => Repository
                .GetAll()
                .Where(et => et.ComponentId == (int)component.Id && et.ComponentErrorCode == strErrorCode)
                .First()
    );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文