如何(干净地)实现EF实体类型的缓存?

本文关键字:类型 实体 缓存 EF 实现 如何 | 更新日期: 2023-09-27 18:08:24

我一次又一次地遇到这种情况:编写代码来创建实体实例(即将行填充到数据库中),其中有需要填写的子关联(即FK引用)。

的例子:

namespace EomApp1.Formss.AB2.Model
{
    public class UnitConversionSource : EomApp1.Formss.AB2.Model.IUnitConversionSource
    {
        IEnumerable<UnitConversion> IUnitConversionSource.UnitConversions(DirectAgentsEntities model)
        {
            yield return new UnitConversion
            {
                Coefficient = 1,
                FromUnit = model.Units.First(c => c.Name == "USD"),
                ToUnit = model.Units.First(c => c.Name == "USD"),
                DateSpan = new DateSpan
                {
                    FromDate = DateTime.Now,
                    ToDate = DateTime.Now.Add(TimeSpan.FromHours(1))
                }
            };
        }
    }
}

Desired:在给定的过期时间内(比如10秒)第一次执行model.Units.First(c => c.Name == "USD"),实体从数据库中取出,但随后(在过期时间内)从内存缓存中取出。

目标:防止插入一百万行的循环执行相同的查询一百万次。

我特别感兴趣的是一个非侵入性的解决方案,它不会影响我在示例中编写代码的方式。这是(希望)从关注点分离体系结构的角度出发的最佳实践的精神。

(ps:我不确定我对"非侵入性"一词的使用是否符合标准语义——请告诉我是否有更好的表达方式)

如何(干净地)实现EF实体类型的缓存?

我不知道你的代码是什么意思,但它有明显的和正确的解决方案:

    IEnumerable<UnitConversion> IUnitConversionSource.UnitConversions(DirectAgentsEntities model)
    {
        string unit = model.Units.First(c => c.Name == "USD");
        yield return new UnitConversion
        {
            Coefficient = 1,
            FromUnit = unit,
            ToUnit = unit,
            DateSpan = new DateSpan
            {
                FromDate = DateTime.Now,
                ToDate = DateTime.Now.Add(TimeSpan.FromHours(1))
            }
        };
    }

如果你知道你必须经常使用一些值,正确的方法是将它们获取到一些字典中,并自己处理它的生存期,或者在一些缓存API中。

在更复杂的情况下,你可以使用EF缓存提供程序,但在这种解决方案中,你的查询仍然必须被解析,必须计算散列等,所以对于你的场景,将所有单元预加载到字典中看起来是更好的方法。