We're updating the issue view to help you get more done. 

LINQ fetched collections aren't cached

Description

Config:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var automappingConfiguration = new AutomappingConfiguration(); return Fluently.Configure() .Database(MsSqlConfiguration.MsSql2012.ConnectionString( ConfigurationManager.ConnectionStrings["Main"].ConnectionString)) .Cache(c => c.UseQueryCache().UseSecondLevelCache().ProviderClass<SysCacheProvider>()) .Mappings(m => m.AutoMappings.Add( AutoMap.AssemblyOf<User>(automappingConfiguration) .IgnoreBase<EntityBase>() .Conventions .Setup(c => { c.Add(ForeignKey.Format((member, type) => { // standard foreign key, straight forward if (member != null) return member.Name + "Id"; // member is null, because it's trying to find the "reverse" column name for a collection // it doesn't find the "reverse" property when it exists, so we find it ourselves var properties = type.GetProperties(); var collectionProperties = properties.Where(p => p.PropertyType.IsGenericType && new[] { typeof(ISet<>), typeof(IList<>) }.Contains(p.PropertyType.GetGenericTypeDefinition())); // unfortunately, we don't know which collection property it is and have to guess and go with the first one var firstCollectionProperty = collectionProperties.First(); var collectionItem = firstCollectionProperty.PropertyType.GetGenericArguments()[0]; var reversePropertyInfo = collectionItem.GetProperties().First(p => p.PropertyType == type); return reversePropertyInfo.Name + "Id"; })); c.Add<EnumConvention>(); c.Add(Cache.Is(ci => ci.ReadWrite())); }) ) ) .BuildSessionFactory();

Query:

1 2 3 4 session.Query<User>() .FetchMany(u => u.DataSources).ThenFetchMany(uds => uds.ParameterLimits).ThenFetchMany(udsp => udsp.Options).ThenFetch(udspo => udspo.Option) .FetchMany(u => u.DataSources).ThenFetchMany(uds => uds.ParameterLastValues).ThenFetchMany(udsplv => udsplv.Options).ThenFetch(o => o.Option) .Where(u => u.Email == email).ToList().First()

Cold cache - correct operation (almost: I have to run around and dedupe some collections, and First() doesn't work - it limits all collections to 1 item only, too - have to do .Where(...).ToList().First(); perhaps I should create another bug for these).

Warm cache - user is retrieved from cache, but then all other collections are retrieved as if lazy loaded:

1 2 exec sp_executesql N'SELECT datasource0_.UserId as UserId2_2_1_, datasource0_.Id as Id1_2_1_, datasource0_.Id as Id1_2_0_, datasource0_.UserId as UserId2_2_0_, datasource0_.DataSourceId as DataSo3_2_0_, datasource0_.LastGraphModuleId as LastGr4_2_0_, datasource0_.LastGridModuleId as LastGr5_2_0_ FROM [UserDataSource] datasource0_ WHERE datasource0_.UserId=@p0',N'@p0 int',@p0=1 exec sp_executesql N'SELECT parameterl0_.UserDataSourceId as UserDa2_5_1_, parameterl0_.Id as Id1_5_1_, parameterl0_.Id as Id1_5_0_, parameterl0_.UserDataSourceId as UserDa2_5_0_, parameterl0_.DataSourceParameterId as DataSo3_5_0_ FROM [UserDataSourceParameterLimit] parameterl0_ WHERE parameterl0_.UserDataSourceId=@p0',N'@p0 int',@p0=1

Environment

Windows 10, .NET 4.6.2, MVC5 web site

Status

Assignee

Unassigned

Reporter

Tahir K Ahmadov