using YLErp.Abstract.DataProviders; namespace YLErp.Modules.DataProviderModule { /// /// 日终参考价数据提供(这个类只有特殊情况下用到) /// public class EodReferencePriceProvider : IPriceProvider { bool _initialized; Dictionary _priceDic; /// /// 构造函数 /// /// 结算价取值日 public EodReferencePriceProvider(DateTime valueDate) { ValueDate = valueDate.Date; } /// /// 结算价取值日 /// public DateTime ValueDate { get; } /// /// 初始化数据字典 /// (提前初始化可在大批量标的取结算价时提高一定性能) /// public EodReferencePriceProvider Initialize(string[] underlyingCodes = null) { //多线程时只初始化一次 if (!_initialized) { lock (this) { if (!_initialized) { InnerInitialize(underlyingCodes); } _initialized = true; } } return this; } private void InnerInitialize(string[] underlyingCodes) { using (var db = DbContextFactory.GetYLDbContext()) { var predicate1 = PredicateBuilder.Create(t => t.ValueDate == ValueDate); var predicate2 = PredicateBuilder.Create(t => t.ValueDate == ValueDate); if (underlyingCodes != null && underlyingCodes.Any(n => !string.IsNullOrEmpty(n))) { predicate1 = predicate1.And(n => underlyingCodes.Contains(n.UnderlyingCode)); predicate2 = predicate2.And(n => underlyingCodes.Contains(n.UnderlyingCode)); } var eodFutureQuery = db.eod_commodity_future_price.Where(predicate1).Select(n => new { n.UnderlyingCode, n.ReferencePrice }); var eodStockQuery = db.eod_stock_price.Where(predicate2).Select(n => new { n.UnderlyingCode, n.ReferencePrice }); //数据加载到字典中 var set = new HashSet(StringComparer.OrdinalIgnoreCase); _priceDic = eodFutureQuery.Concat(eodStockQuery).ToArray() .Where(n => n.UnderlyingCode != null && set.Add(n.UnderlyingCode)) .ToDictionary(n => n.UnderlyingCode, m => m.ReferencePrice, StringComparer.OrdinalIgnoreCase); } } public double GetPrice(string instrumentCode) { return InnerTryGetPrice(instrumentCode, out var price) ? price : 0d; } public bool TryGetPrice(string instrumentCode, out double price) { return InnerTryGetPrice(instrumentCode, out price); } private bool InnerTryGetPrice(string instrumentCode, out double price) { price = 0; if (string.IsNullOrWhiteSpace(instrumentCode)) { return false; } lock (this) { if (_priceDic == null) { _priceDic = new Dictionary(StringComparer.OrdinalIgnoreCase); } else if (_priceDic.TryGetValue(instrumentCode, out var nPrice)) { price = nPrice ?? 0; return nPrice.HasValue; } else if (_initialized) { return false; } } var exists = EodPriceQueryService.TryGetReferencePrice(ValueDate, instrumentCode, out price); lock (this) { _priceDic[instrumentCode] = exists ? (double?)price : null; } return exists; } } }