Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在具有自己用户类型的延迟加载属性上激活二级缓存?_C#_.net_Nhibernate_Caching_Fluent Nhibernate - Fatal编程技术网

C# 如何在具有自己用户类型的延迟加载属性上激活二级缓存?

C# 如何在具有自己用户类型的延迟加载属性上激活二级缓存?,c#,.net,nhibernate,caching,fluent-nhibernate,C#,.net,Nhibernate,Caching,Fluent Nhibernate,前言: 在我的应用程序中,我将原始WAV数据作为byte[]存储在数据库中。在我的域模型中,有一个类表示原始WAV数据。我创建了NHibernate的IUserType的一个实现,用于在我的类和byte[]之间转换 有几个类使用PcmAudioStream类,所有这些类都映射到数据库表。为了避免在从这样的表中检索行时总是加载所有WAV数据,我创建了Fluent NHibernate的IUserTypeConvention的一个实现,该实现指定这些属性应该总是延迟加载。 所有这些都很有魅力 问题:

前言
在我的应用程序中,我将原始WAV数据作为
byte[]
存储在数据库中。在我的域模型中,有一个类表示原始WAV数据。我创建了NHibernate的
IUserType
的一个实现,用于在我的类和
byte[]之间转换

有几个类使用
PcmAudioStream
类,所有这些类都映射到数据库表。为了避免在从这样的表中检索行时总是加载所有WAV数据,我创建了Fluent NHibernate的
IUserTypeConvention
的一个实现,该实现指定这些属性应该总是延迟加载。
所有这些都很有魅力

问题:
因为这些
PcmAudioStream
s的内容很少改变,所以我想将检索到的实例放在二级缓存中。现在,我知道如何为一个完整的类激活二级缓存,但如何仅为一个延迟加载的属性实现这一点


我的域模型的相关部分如下所示:

public class User : Entity
{
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual PcmAudioStream FullNameRecording { get; set; }
    // ...
}
映射很简单(注意:这不是我的映射,我使用的是约定,但它是等效的):

公共类用户映射:类映射
{
公共用户映射()
{
Id(x=>x.Id);
Map(x=>x.FirstName);
Map(x=>x.LastName);
映射(x=>x.FullNameRecording).CustomType();
}
}

我不确定是否只缓存一个属性,但我猜这不是NH缓存基础设施的构建方式。IMHO您可以将整个类实例或查询结果放入二级缓存

但我会尝试勾勒出一个解决方案

在NH3和对惰性属性的支持之前,如果您不想从DB加载整个实体(在您的情况下,这是非常合理的!),那么您必须将这些“昂贵”的数据保存在一个引用的惰性加载表中。至少我是这样解决的

这似乎是一种倒退,但使用这种方法,我非常确定您将能够缓存这些数据


另一方面,NH3+中的缓存和查询似乎存在问题:

您可以使用私有静态缓存来完成此操作。设置它需要更多的工作,但不需要对域模型进行额外的类或公共更改。一个很大的缺点是不会从缓存中删除条目,但是可以使用自定义集合或“全局”缓存来限制条目的数量

public class Entity
{
    public virtual int Id { get; protected set; }
}

public class PcmAudioStream
{}

public class User : Entity
{
    private static readonly IDictionary<int, PcmAudioStream> _fullNameRecordingCache;

    private PcmAudioStream _fullNameRecording;

    static User()
    {
        _fullNameRecordingCache = new Dictionary<int, PcmAudioStream>();
    }

    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual PcmAudioStream FullNameRecording
    {
        get
        {
            if (_fullNameRecordingCache.ContainsKey(Id))
            {
                return _fullNameRecordingCache[Id];
            }
            // May need to watch for proxies here
            _fullNameRecordingCache.Add(Id, _fullNameRecording);
            return _fullNameRecording;
        }
        set
        {
            if (_fullNameRecordingCache.ContainsKey(Id))
            {
                _fullNameRecordingCache[Id] = value;
            }
            _fullNameRecording = value;
        }
    }
    // ...
}
公共类实体
{
公共虚拟整数Id{get;protected set;}
}
公共类数据流
{}
公共类用户:实体
{
私有静态只读IDictionary_fullNameRecordingCache;
私有PcmAudioStream\u全名记录;
静态用户()
{
_fullNameRecordingCache=新字典();
}
公共虚拟字符串FirstName{get;set;}
公共虚拟字符串LastName{get;set;}
公共虚拟PcmAudioStream FullNameRecording
{
得到
{
if(_fullnamecordingcache.ContainsKey(Id))
{
返回_fullnamecordingcache[Id];
}
//可能需要注意这里的代理
_添加(Id,\u fullnamecording);
返回全名记录;
}
设置
{
if(_fullnamecordingcache.ContainsKey(Id))
{
_fullNameRecordingCache[Id]=值;
}
_fullNameRecording=值;
}
}
// ...
}
映射:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        Map(x => x.FullNameRecording).CustomType<PcmAudioStreamAsByteArray>()
            .Access.CamelCaseField(Prefix.Underscore);
    }
}
公共类用户映射:类映射
{
公共用户映射()
{
Id(x=>x.Id);
Map(x=>x.FirstName);
Map(x=>x.LastName);
映射(x=>x.FullNameRecording).CustomType()
.Access.CamelCaseField(前缀.下划线);
}
}

根据评论编辑:

我认为在用户类型中不可能实现这一点,因为IDataReader已经在NullSafeGet中打开。我认为您可以在实现IPreLoadEventListener的侦听器中执行此操作,但这不允许您使缓存无效。我认为这两种选择都不可行


在仔细考虑之后,我仍然认为我的原始解决方案(或变体)是最好的选择。我理解(并分享)您对干净域模型的渴望,但有时需要妥协,我的解决方案不会改变模型的公共成员或需要任何其他引用。另一个理由是,对象是第一个知道录制已更改,需要在缓存中替换或添加到缓存的对象。

您使用的是哪个版本的NH?我使用的是NH 3.1和FNH 1.2,我也有类似的问题。只是想知道现在是否有一种方法可以让nhibernate缓存延迟加载的属性,而不是建议的解决方案。我知道这是以前用于延迟加载属性的解决方法。当我在谷歌上搜索时,我读了很多关于它的帖子。基于这些帖子,我的理解是,我不仅在数据库中有一个单独的表——我可以使用它——而且在我的域模型中还有一个单独的类——我不能使用它。这种理解正确吗?关于JIRA问题:我正在使用LINQ,所以我对它没有任何问题。至少到目前为止我没有得到任何异常。为什么单独的类/表是个问题?单独的表不是问题。但在我的域模型中有一个单独的类是,因为它污染了它。它可能看起来不漂亮,但它可能会解决您的缓存问题:-)它会,但它不是一个选项。我不想牺牲我的领域模型的架构,因为ORM不能做某些事情。。。没有别的办法吗?谢谢你的主意。一般来说,我写自己的缓存没有问题。但它不属于域模型。如果有的话,我会把它放在用户类型中。。。
public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        Map(x => x.FullNameRecording).CustomType<PcmAudioStreamAsByteArray>()
            .Access.CamelCaseField(Prefix.Underscore);
    }
}