亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何阻止 NHibernate 讀取子集合?

如何阻止 NHibernate 讀取子集合?

C#
qq_遁去的一_1 2022-12-24 10:46:04
我的數據庫中有文檔列表。每個文檔都有一個子元素集合?,F在,我的方案是: - 讀取文檔(僅從文檔表) - 關閉會話并讓用戶做一些工作。但是當我這樣做時,Document 會嘗試在某些地方加載子元素。我不想要它。我只想明確地閱讀子元素。對于第一部分,我只需要閱讀簡單的文檔值。那么有什么方法可以對 nHibernate 說——“嘿,永遠不要讀這個集合!”?
查看完整描述

3 回答

?
婷婷同學_

TA貢獻1844條經驗 獲得超8個贊

將您收藏的延遲加載設置為LazyExtra,也許您的設置為NoLazy(又名預加載)。

最好將其設置為Extra而不是Lazy僅。因為當您只想獲取子集合的.Count()or時,它會阻止 NHibernate 獲取子集合的行.Any()Extra就像懶惰的更懶惰的版本:)

使用NoLazy / eager-loading

var post = session.Get<Post>(1);

這將從數據庫的帖子表中讀取一行,并從數據庫的評論表中讀取一行,即使您沒有從您的應用程序訪問帖子的子集合評論。

使用Lazy,var post = session.Get<Post>(1)只會加載帖子表中的一行,NHibernate 不會從數據庫中讀取帖子的子集合評論。

至于懶惰與額外

使用懶惰

var commentsCount = post.Comments.Count()

這將從數據庫中加載帖子的評論:

select * from comments where post_id = 1;

.Count(), 僅發生在應用程序端。

使用Extra,var commentsCount = post.Comments.Count()NHibernate 將僅發出計數查詢,而不是讀取所有行。

select count(*) from comments where post_id = 1

下面是一個示例配置,用于設置子集合的加載機制,如果您使用 NHibernate 的自動映射,您可以在BeforeMapSet事件上設置該設置:

http://img1.sycdn.imooc.com//63a668080001417007260326.jpg

當您需要預先加載配置為Lazy或的子集合Extra時,請使用FetchMany


查看完整回答
反對 回復 2022-12-24
?
30秒到達戰場

TA貢獻1828條經驗 獲得超6個贊

我發現是什么導致文檔的周期從數據庫加載,即使您不訪問文檔的周期屬性。


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();

            }

        }

    }

}

產生這個:


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)]

您的映射類似于以下內容。您的Lazy子集合加載設置為Lazy(而不是NoLazy),但其Fetch策略設置為Join。以機智:


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 未被其父項(文檔)過早獲取:


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)]

使用的重現步驟:https ://github.com/MichaelBuen/NHibernateFetchJoinTest2


查看完整回答
反對 回復 2022-12-24
?
當年話下

TA貢獻1890條經驗 獲得超9個贊

作為臨時解決方案,我創建了一個簡單的 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;

當然這個集合被映射為惰性的。子集合 (Periods) 必須定義為返回變量,因為它會阻止 NHibernate Proxy 使用屬性 getter。


查看完整回答
反對 回復 2022-12-24
  • 3 回答
  • 0 關注
  • 118 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號