У меня есть этот код:
[TestFixture]
public class CachingTest
{
[Test]
public void Caches_second_request()
{
var sessionFactory = CreateSessionFactory();
int orderId;
{
var order = new Order {Created = DateTime.Now};
order.Rows.Add(new OrderRow {Price = 123, Order = order});
order.Rows.Add(new OrderRow { Price = 456, Order = order });
using (var session = sessionFactory.OpenSession())
{
session.Save(order);
orderId = order.Id;
}
}
Console.WriteLine("Saved");
using (var session = sessionFactory.OpenSession())
{
var order = session.Get<Order>(orderId);
Console.WriteLine(order.Rows.Count);
}
Console.WriteLine("Fetched first time");
using (var session = sessionFactory.OpenSession())
{
var order = session.Get<Order>(orderId);
Console.WriteLine(order.Rows.Count);
}
}
private static ISessionFactory CreateSessionFactory()
{
var autoMappingConfig = new AutoMappingConfiguration();
ISessionFactory sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.FromAppSetting("connectionString"))
.ShowSql())
.Cache(c => c
.UseQueryCache()
.UseSecondLevelCache()
.ProviderClass<KamakuraCacheProvider>())
.Mappings(m =>
m.AutoMappings.Add(
AutoMap.AssemblyOf<CachingTest>(autoMappingConfig)
.Conventions.Add(
ForeignKey.EndsWith("Id"),
DefaultLazy.Never(),
DefaultCascade.All())
.Conventions.Add<CacheableConvention>()
))
.ExposeConfiguration(configuration =>
new SchemaExport(configuration).Create(false, true))
.BuildSessionFactory();
return sessionFactory;
}
}
public class CacheableConvention : IClassConventionAcceptance, IClassConvention
{
public void Accept(IAcceptanceCriteria<IClassInspector> criteria)
{
criteria.Expect(x => x.EntityType.IsAny(typeof (Order), typeof (OrderRow)));
}
public void Apply(IClassInstance instance)
{
instance.Cache.ReadWrite();
instance.Cache.IncludeAll();
}
}
public class AutoMappingConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type == typeof (Order) || type == typeof (OrderRow);
}
public override Access GetAccessStrategyForReadOnlyProperty(Member member)
{
return Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore);
}
}
public class Order
{
private readonly ICollection<OrderRow> _rows = new Collection<OrderRow>();
public virtual int Id { get; set; }
public virtual DateTime Created { get; set; }
public virtual ICollection<OrderRow> Rows
{
get { return _rows; }
}
}
public class OrderRow
{
public virtual int Id { get; set; }
public virtual Order Order { get; set; }
public virtual decimal Price { get; set; }
}
Это сгенерирует этот вывод:
NHibernate: INSERT INTO [Order] (Created) VALUES (@p0); select SCOPE_IDENTITY();@p0 = 2011-04-29 13:40:39 [Type: DateTime (0)]
NHibernate: INSERT INTO [OrderRow] (Price, OrderId) VALUES (@p0, @p1); select SCOPE_IDENTITY();@p0 = 123 [Type: Decimal (0)], @p1 = 1 [Type: Int32 (0)]
NHibernate: INSERT INTO [OrderRow] (Price, OrderId) VALUES (@p0, @p1); select SCOPE_IDENTITY();@p0 = 456 [Type: Decimal (0)], @p1 = 1 [Type: Int32 (0)]
Saved
NHibernate: SELECT order0_.Id as Id0_0_, order0_.Created as Created0_0_ FROM [Order] order0_ WHERE order0_.Id=@p0;@p0 = 1 [Type: Int32 (0)]
NHibernate: SELECT rows0_.OrderId as OrderId1_, rows0_.Id as Id1_, rows0_.Id as Id1_0_, rows0_.Price as Price1_0_, rows0_.OrderId as OrderId1_0_ FROM [OrderRow] rows0_ WHERE rows0_.OrderId=@p0;@p0 = 1 [Type: Int32 (0)]
2
Fetched first time
NHibernate: SELECT rows0_.OrderId as OrderId1_, rows0_.Id as Id1_, rows0_.Id as Id1_0_, rows0_.Price as Price1_0_, rows0_.OrderId as OrderId1_0_ FROM [OrderRow] rows0_ WHERE rows0_.OrderId=@p0;@p0 = 1 [Type: Int32 (0)]
2
Во второй раз, когда я получаю ордер с использованием метода Get, он незапросить таблицу заказов, но она все равно выполняет запрос к таблице OrderRow.
Можно ли это как-то настроить так, чтобы она кэшировалась вместе с данными таблицы заказов?