3 回答

TA貢獻(xiàn)1844條經(jīng)驗(yàn) 獲得超8個(gè)贊
將您收藏的延遲加載設(shè)置為Lazy
或Extra
,也許您的設(shè)置為NoLazy
(又名預(yù)加載)。
最好將其設(shè)置為Extra
而不是Lazy
僅。因?yàn)楫?dāng)您只想獲取子集合的.Count()
or時(shí),它會阻止 NHibernate 獲取子集合的行.Any()
。Extra
就像懶惰的更懶惰的版本:)
使用NoLazy / eager-loading:
var post = session.Get<Post>(1);
這將從數(shù)據(jù)庫的帖子表中讀取一行,并從數(shù)據(jù)庫的評論表中讀取一行,即使您沒有從您的應(yīng)用程序訪問帖子的子集合評論。
使用Lazy
,var post = session.Get<Post>(1)
只會加載帖子表中的一行,NHibernate 不會從數(shù)據(jù)庫中讀取帖子的子集合評論。
至于懶惰與額外
使用懶惰:
var commentsCount = post.Comments.Count()
這將從數(shù)據(jù)庫中加載帖子的評論:
select * from comments where post_id = 1;
而.Count()
, 僅發(fā)生在應(yīng)用程序端。
使用Extra,var commentsCount = post.Comments.Count()
NHibernate 將僅發(fā)出計(jì)數(shù)查詢,而不是讀取所有行。
select count(*) from comments where post_id = 1
下面是一個(gè)示例配置,用于設(shè)置子集合的加載機(jī)制,如果您使用 NHibernate 的自動(dòng)映射,您可以在BeforeMapSet事件上設(shè)置該設(shè)置:
當(dāng)您需要預(yù)先加載配置為Lazy
或的子集合Extra
時(shí),請使用FetchMany

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個(gè)贊
我發(fā)現(xiàn)是什么導(dǎo)致文檔的周期從數(shù)據(jù)庫加載,即使您不訪問文檔的周期屬性。
namespace NHibernateFetchJoinTest2
{
using System;
using NHibernateFetchJoinTest2.DomainMapping;
using NHibernateFetchJoinTest2.Domains;
class MainClass
{
public static void Main(string[] args)
{
using (var session = Mapper.SessionFactory.OpenSession())
{
Console.WriteLine("SQL produced: ");
var d = session.Get<Document>(1);
Console.ReadLine();
//Console.WriteLine("Document's periods: ");
//foreach (var period in d.Periods)
//{
// Console.WriteLine($"* {period.PeriodDescription}");
//}
Console.ReadLine();
}
}
}
}
產(chǎn)生這個(gè):
SQL produced:
NHibernate:
SELECT
document0_.Id as id1_0_1_,
document0_.DocumentDescription as documentdescription2_0_1_,
periods1_.DocumentId as documentid3_1_3_,
periods1_.Id as id1_1_3_,
periods1_.Id as id1_1_0_,
periods1_.PeriodDescription as perioddescription2_1_0_
FROM
Document document0_
left outer join
Period periods1_
on document0_.Id=periods1_.DocumentId
WHERE
document0_.Id=@p0;
@p0 = 1 [Type: Int32 (0:0:0)]
您的映射類似于以下內(nèi)容。您的Lazy子集合加載設(shè)置為Lazy(而不是NoLazy),但其Fetch策略設(shè)置為Join。以機(jī)智:
namespace NHibernateFetchJoinTest2.DomainMapping.Mappings
{
using NHibernate.Mapping.ByCode.Conformist;
using NHibernateFetchJoinTest2.Domains;
public class DocumentMapping : ClassMapping<Document>
{
public DocumentMapping()
{
Id(x => x.Id);
Property(x => x.DocumentDescription);
Bag(x => x.Periods, collectionMapping =>
{
collectionMapping.Inverse(true);
collectionMapping.Key(k => k.Column("DocumentId"));
collectionMapping.Lazy(NHibernate.Mapping.ByCode.CollectionLazy.Lazy);
// Remove this. This causes Document's Periods to load,
// even if child collection Periods is not accessed yet.
// This is evident in SQL log, it shows LEFT JOIN Period.
collectionMapping.Fetch(NHibernate.Mapping.ByCode.CollectionFetchMode.Join);
}, mapping => mapping.OneToMany());
}
}
public class PeriodMapping: ClassMapping<Period>
{
public PeriodMapping()
{
Id(x => x.Id);
Property(x => x.PeriodDescription);
}
}
}
如果刪除此...
collectionMapping.Fetch(NHibernate.Mapping.ByCode.CollectionFetchMode.Join);
...子集合 Periods 未被其父項(xiàng)(文檔)過早獲?。?/p>
SQL produced:
NHibernate:
SELECT
document0_.Id as id1_0_0_,
document0_.DocumentDescription as documentdescription2_0_0_
FROM
Document document0_
WHERE
document0_.Id=@p0;
@p0 = 1 [Type: Int32 (0:0:0)]
使用的重現(xiàn)步驟:https ://github.com/MichaelBuen/NHibernateFetchJoinTest2

TA貢獻(xiàn)1890條經(jīng)驗(yàn) 獲得超9個(gè)贊
作為臨時(shí)解決方案,我創(chuàng)建了一個(gè)簡單的 hack:
public class Document
{
IList<Periods> periods;
public virtual IList<Period> Periods
{
get { return periods; }
set { periods = value; }
}
public virtual void ResetPeriods()
{
periods = new List<Period>();
}
}
這就是我獲取文件的方式:
db.BeginTransaction();
IList<Document> list = db.Get<Document>();
db.CommitTransaction();
List<Document> result = new List<Document>();
foreach (var item in list)
{
item.ResetPeriods(); //todo: HACK! Preventing from lazy load of periods
result.Add(item);
}
return result;
當(dāng)然這個(gè)集合被映射為惰性的。子集合 (Periods) 必須定義為返回變量,因?yàn)樗鼤柚?NHibernate Proxy 使用屬性 getter。
- 3 回答
- 0 關(guān)注
- 125 瀏覽
添加回答
舉報(bào)