简体   繁体   English

如何在nhibernate二级缓存中加载所有内容?

[英]How can I load everything up in nhibernate 2nd level cache?

I have an asp.net-mvc site that is using nhibernate and SQL server, there are a few pages that are quite slow because they require view that need queries which join about 25 different tables. 我有一个使用nhibernate和SQL服务器的asp.net-mvc站点,有一些页面非常慢,因为它们需要查看需要加入大约25个不同表的查询。 If i don't a large join it takes a while and if I do a multi query it still seems to take a while 如果我没有大型连接需要一段时间,如果我进行多次查询,它似乎还需要一段时间

Its a pretty ready heavy (light write) DB so I wanted to see if there is a good way to basically load up the entire object graph of my database (my server has plenty of memory) into 2nd level cache so I am confident that it rarely hits the db. 它是一个非常准备好的重(轻写)数据库,所以我想看看是否有一个很好的方法基本上加载我的数据库的整个对象图(我的服务器有足够的内存)到二级缓存,所以我有信心它很少打到数据库。 I am using 我在用

  NHibernate.Caches.SysCache.SysCacheProvider

as the second level cache (not a distributed cache). 作为二级缓存(不是分布式缓存)。 Is there any flaw in this idea and is there a recommended way of doing this? 这个想法有什么缺陷吗?有推荐的方法吗?

You are caching your query results, but not your entity (those are separate caches) Caching a query's results just stores the IDs; 您正在缓存查询结果,但不缓存您的实体(这些是单独的缓存)缓存查询的结果只存储ID; if you are not caching your entities too, a query is issued to load each returned entity (this is usually bad) The default table name for the MyDTO class is MyDTO, so that's where it's looking This looks like a Query by ID, for which you shouldn't be using a loose named query, but a proper loader . 如果你也没有缓存你的实体,会发出一个查询来加载每个返回的实体(这通常是坏的)MyDTO类的默认表名是MyDTO,所以它看起来就像这看起来像一个按ID查询,你不应该使用松散的命名查询,而是使用适当的加载器。 (see 17.4. Custom SQL for loading) Once you set up the loader and entity caching, you'll just be able to retrieve your objects using just session.Get(id), which will use the second level cache, as long as you do all of your work inside transactions, which is a recommended practice. (参见17.4。加载自定义SQL)设置加载器和实体缓存后,只需使用session.Get(id)就可以检索对象,它将使用二级缓存,只要你在交易中完成所有工作,这是一种推荐的做法。

Second-level cache always associates with the Session Factory object. 二级缓存始终与Session Factory对象关联。 While running the transactions, in between it loads the objects at the Session Factory level, so that those objects will be available to the entire application, not bound to single user. 在运行事务时,它在两者之间加载会话工厂级别的对象,以便这些对象可供整个应用程序使用,而不是绑定到单个用户。 Since the objects are already loaded in the cache, whenever an object is returned by the query, at that time no need to go for a database transaction. 由于对象已经加载到缓存中,因此每当查询返回一个对象时,就不需要进行数据库事务。

second-level cache has to be not only enabled but configured for every single individual entity class that you want cached. 必须不仅启用二级缓存,而且还要为要缓存的每个单个实体类进行配置。 So enable cache all 15 objects that are mapped to 15 tables. 因此,启用缓存映射到15个表的所有15个对象。

In XML, this is done inside the element: 在XML中,这是在元素内部完成的:

<cache usage="read-write"/>

In Fluent NHibernate (non-automap), it's done in the ClassMap constructor or wherever you put the rest of your mapping code: 在Fluent NHibernate(非自动化)中,它在ClassMap构造函数中完成,或者在您放置其余映射代码的任何位置完成:

Cache.ReadWrite().Region("Configuration");

From here it depends on the size and load of DB, and how new data must be present. 从这里开始,它取决于DB的大小和负载,以及新数据的存在方式。

If Db is relatively small and there are few writes you can update cache on every write/update. 如果Db相对较小且写入很少,则可以在每次写入/更新时更新缓存。

ISession.Clear();
ReloadCache();

If Db is massive: And you have a luxury of updating database once per day lets say a 12am and then keep 'new' data in cache for a day then you're ok too. 如果Db是庞大的:你有一个奢侈的更新数据库每天一次让我们说早上12点,然后将“新”数据保存在缓存中一天然后你也可以。 You will get a lag spike for a few users while reloading. 在重新加载时,您将为少数用户获得延迟峰值。

Here's an example: http://www.codeproject.com/Articles/529016/NHibernate-Second-Level-Caching-Implementation 这是一个例子: http//www.codeproject.com/Articles/529016/NHibernate-Second-Level-Caching-Implementation

If your DB is massive and users must get updated data you will manually have to update data in cache. 如果您的数据库庞大且用户必须获取更新数据,您将手动更新缓存中的数据。

Database db =   new Database (); 
Transaction tx = db.BeginTransaction (); 
try 
{ 
// Read from the cache 
MyEntity1 entity1 = cache.Get <MyEntity1> ("pk of entity1"); 
// Cache is not read from the database 
 if (entity1 ==   null) entity1 = db.Get <MyEntity1> ("pk of entity1"); 

// Entity1 processing 

updated = db.Update, (entity1); / / entity1 update saved to the database 
 if (updated) cache.Put (entity1); / / database update successfully, the update cache 

// Transaction processing 

tx.commit (); 
} 
catch 
{ 
tx.Rollback (); 
throw; 
}

more on that here: http://www.databaseskill.com/3093355/ 更多关于这一点: http//www.databaseskill.com/3093355/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM