加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – ConcurrentDictionary.GetOrAdd – 仅在不为null时添加

发布时间:2020-12-15 08:47:18 所属栏目:百科 来源:网络整理
导读:我正在使用ConcurrentDictionary通过并行访问来缓存数据,有时新项目可以存储在db中,并且它们不会加载到缓存中.这就是我使用GetOrAdd的原因 public User GetUser(int userId){ return _user.GetOrAdd(userId,GetUserFromDb); }private User GetUserFromDb(int
我正在使用ConcurrentDictionary通过并行访问来缓存数据,有时新项目可以存储在db中,并且它们不会加载到缓存中.这就是我使用GetOrAdd的原因
public User GetUser(int userId)
{
    return _user.GetOrAdd(userId,GetUserFromDb);        
}

private User GetUserFromDb(int userId)
{
    var user = _unitOfWork.UserRepository.GetById(userId);

    // if user is null,it is stored to dictionary

    return user;
}

但是,如果用户不为空,我如何检查用户是否从db获取并将用户存储到字典?

可能我可以在GetOrAdd之后立即从ConcurrentDictionary中删除null但它看起来不是线程安全的并且它不是非常优雅的解决方案.无用插入和从字典中删除.你知道怎么做吗?

解决方法

public User GetUser(int userId)
{
    var user = _user.GetOrAdd(userId,GetUserFromDb);
    if (user == null) _user.TryRemove(userId,out user);    
}

您还可以将其包装到扩展方法中:

public static TValue GetOrAddIfNotNull<TKey,TValue>(
    this ConcurrentDictionary<TKey,TValue> dictionary,TKey key,Func<TKey,TValue> valueFactory) where TValue : class
{
    var value = dictionary.GetOrAdd(key,valueFactory);
    if (value == null) dictionary.TryRemove(key,out value);
    return value;
}

然后你的代码看起来像:

public User GetUser(int userId)
{
    var user = _user.GetOrAddIfNotNull(userId,GetUserFromDb)   
}

UPDATE

根据@usr评论,可能有以下情况:

>线程1执行GetOrAdd,将null添加到字典并暂停.
>用户已添加到数据库中.
>线程2执行GetOrAdd并从字典中检索null而不是命中数据库.
>线程1和线程2执行TryRemove并从字典中删除记录.

有了这个时间,线程2将变为null而不是命中数据库并获取用户记录.如果这个边缘情况对您很重要并且您仍然想使用ConcurrentDictionary,那么您可以在扩展方法中使用lock:

public static class ConcurrentDictionaryExtensions
{
    private static readonly object myLock = new object();

    public static TValue GetOrAddIfNotNull<TKey,TValue>(
        this ConcurrentDictionary<TKey,TValue> valueFactory) where TValue : class
    {
        lock (myLock)
        {
            var value = dictionary.GetOrAdd(key,valueFactory);
            if (value == null) dictionary.TryRemove(key,out value);
            return value;
        }
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读