使用Core的DI Singleton作为内存数据提供程序?

时间:2019-08-12 18:40:29

标签: c# design-patterns .net-core

我需要从远程服务(懒惰地)获得电台列表,并将其存储在DB和内存中。
然后,如果有人想要该列表,则尝试读取内存中的列表。
如果为null,则转到Db,如果DB中没有数据,则应转到远程服务,获取列表,并将列表存储在DB和内存中。

(基本上,我不想每次请求都去远程服务)

因此,我使用了.net核心的单例服务:

services.AddSingleton<IStations,Stations>()

该类将包含列表本身的位置:

public class Stations:IStations
{
 public List<StationModel> LstStationModel
        {
            get
            {
                lock (locker)
                {
                    if (_lstStationModel == null)

                    {
                        var ls = GetStationsFromDb().Result;
                        if (ls!=null && ls.Count > 0)
                            _lstStationModel = ls;
                        else
                            _lstStationModel = GetStationsFromProvider().Result;

                    }
                    return _lstStationModel;
                }
            }
            set
            {
                lock (locker)
                {
                    _lstStationModel = value;
                }
            }
        }
}

所以现在我在单例类中有一个属性。
当有人要求列表时,我检查它是否为null,然后转到db。 如果数据库中没有数据,我将开始从远程获取并填充列表。

我还添加了lock,以便2个请求不会调用两次提取。

问题

这里的东西看起来不正确。我不确定这是正确的方法。而且,我真的不喜欢这种解决方案。

有什么方法可以更优雅/更好地做到这一点?

1 个答案:

答案 0 :(得分:1)

您可以为此目的使用Lazy。如果在构造函数中传递true,则表明它是线程安全的。 示例:

 public class Stations : IStations
    {
        Lazy<List<StationModel>> _lazyStation = new Lazy<List<StationModel>>(() => Provider.GetStationsFromProvider().Result, isThreadSafe: true);

        public List<StationModel> LstStationModel
        {
            get { return _lazyStation.Value; }
            set { _lazyStation = new Lazy<List<StationModel>>(() => value, isThreadSafe: true);  }
        }

    }

请注意,这不是缓存或访问数据的最佳解决方案,因为您正在将Provider耦合到Stations对象。我建议创建一个服务/类,然后将您的“提供者”(作为抽象)注入其中,以反转依赖关系(Dependency Inversion Principle)。如果您将创建Service / Manager类,甚至可以注入ICacheService并使用MemoryCache

实现