NHibernate LINQ Query Extension Enhancements (Nineth article)

Source: Internet
Author: User

NHibernate LINQ Query Extension Enhancements (Nineth article)

  In the previous introduction of LINQ to NHibernate, all of the Iqueryover<troot in the namespace NHibernate namespace are provided by the Tsubtype> interface. Iqueryover<troot, tsubtype> This excuse is actually translated into conditional query (criteria Queries).

In fact, LINQ to NHibernate is more powerful. let's first introduce the namespace Nhibernate.linq, which has a more powerful extension of LINQ to NHibernate.

one, fetch immediately load (avoid lazy loading)

Let's take a look at some of the possible problems with NHibernate delay loading:

  deferred loading results in SQL execution:

        Staticvoid Main (String[] args) {isessionfactory sessionfactory = new Configuration (). Configure (). Buildsessionfactory (); using (isession session =  Sessionfactory.opensession ()) {Ilist<personmodel> Listperson = session. Queryover<personmodel> (). List (); foreach (personmodel p  In Listperson) {Console.WriteLine (P.personid + p.personname + P.country.countryname); }} console.readkey (); }

The result of the execution is:

  

  This delay loading play a big game.  foreach () Once, read a record, this ... See the above statement from the country, in fact, the main is to read the person when the country is not read out, make every time foreach () must be in the database to read the corresponding country caused by the person, If we do not want to because the cross-table query to country will be loaded, the person corresponding to the country also loaded over.

  loading immediately , fortunately, there is a fetch method, let's take a look at the following code:

        static void Main (string[] args)        {            isessionfactory sessionfactory = new Configuration (). Configure (). Buildsessionfactory ();            using (isession session = Sessionfactory.opensession ())            {                IList   foreach (console.readkey ();}     

The SQL statement executed is:

  

That's the way it's supposed to be. NHibernate The lazy load feature is turned on by default so that other queries can successfully apply the benefits of lazy loading. And when we don't want to delay loading, we can programmatically control it by means of a fetch (). Not bad. In the above procedure, the role of fetch is to force the country associated with the person to load when the person is loaded.

Now, to load something else immediately, we changed the original database to the following:

  

1. Multiple Associations

The person has a school in addition to one of the countries in which he belongs. Then we want to output a person's countryname and schoolname. And what should be done about it?

        Staticvoid Main (String[] args) {isessionfactorySessionfactory = (NewConfiguration ()). Configure (). Buildsessionfactory ();using (ISessionSession =Sessionfactory.opensession ()) {IList<  Personmodel  > Listperson = Session. Query< Personmodel  > ()   . Fetch (p = p.country). Fetch (P =>      p.school).   ToList (); foreach (  Personmodel  p in Listperson) {Console.WriteLine (p.name + " :" : P. School.schoolname); }} console.readkey (); }

We have to fetch (). Fetch () load the data one at a time, or it will appear foreach () once, query a school case.

The above code output is as follows:

  

2. Nested associations

In the previous section of the figure, person belongs to country, and country belongs to an area. If we fetch () the country, then if we want to output areaname, we should check the database again. So, we want to read the perosn, incidentally read the associated country, and then incidentally read out the associated area how to do it?

        Staticvoid Main (String[] args) {isessionfactorySessionfactory = (NewConfiguration ()). Configure (). Buildsessionfactory ();using (ISessionSession =Sessionfactory.opensession ()) {IList<  Personmodel  > Listperson = Session. Query< Personmodel  > ().   Fetch (p = p.country). Thenfetch (c =>      C.area) . ToList (); foreach (  Personmodel  p in Listperson) {Console.WriteLine (p.name + " :" : P. Country.Area.AreaName); }} console.readkey (); }

The output results are as follows:

  

The code above reads the required data at once, without affectation.

the difference between fetch and Fetchmany

The difference between fetch and Fetchmany is the same as the difference between select and SelectMany. Look at the method signature, mainly there is a difference between the parameters.

        Static inhfetchrequest<toriginating, trelated> fetch<toriginating, trelated> (TRelated> > relatedobjectselector);        static inhfetchrequest<toriginating, trelated> fetchmany<toriginating, trelated> (   ienumerable<trelated>>> relatedobjectselector);  

Notice that the method signature only checks a little, but for the area to get country and then get person, it is not fetchmany. Because fetch () parameters are not allowed for the collection.

For example, we identify all the regions, then list all the countries of the region, and then list all the PersonName:

     //-------------------------------------------------------------------------------------------------here C is IEnumerable <ContryModel> ilist<areamodel> Listarea = nsession.query<areamodel> (). Fetchmany (A = a.listcountry). Thenfetchmany (c =C.listperson).     ToList (); //ilist<areamodel> Listarea = nsession.query<areamodel> (). Fetch (A = a.listcountry). Thenfetch (c = c.listperson). ToList (); So write the compiler with the error foreach (Areamodel area in  Listarea) {Console.WriteLine (area. AreaName); foreach (countrymodel C in area  . Listcountry) {Console.WriteLine (c.countryname); foreach (Personmodel p in C.listperson) {Console.WriteLine (p.name);     }}} 

The output is as follows:

  

The difference is that Fetchmany,thenfetchmany accepts data input of the ienumerable<t> type, and Fetch,fetchmany does not support it.

Second, LINQ uses the cache

Linq-cache Description:

      • Cacheable enable level Two caching for a query display;

      • CacheMode cache mode, like the following optional:

        1. Ignore: Invalid level Two cache when updating data, other time not interacting with level two cache
        2. Put: Writes data to a level two cache, but does not read data from a level two cache
        3. Get: Read data from level two cache, write data to level two cache only when data is updated
        4. Normal: The default way. Read/write data from level two cache
        5. Refresh: Write data to Level two cache, want to not read data from level two cache, force level two cache refresh by reading data from the database when the configuration file Settings cache.use_minimal_puts
      • cacheregion specifies a specific named cache region for the query cache, and if two queries are the same, but the specified cacheregion is different, the data is also queried from the database.

1. Before using the cache, first turn on the nhibernate level two cache.

      <!--Configuring the two-level cache implementation Program-<PropertyName= "Cache.provider_class">nhibernate.cache.hashtablecacheprovider</Property><!--Turn on level two caching-<PropertyName= "Cache.use_second_level_cache">true</Property><!---- > <property name = "Cache.use_query_cache" >true</property> --> <class-cache class = "Model.personmodel,model"  Usage= "Read-write" />         

2. On the mapping file where you want to use the cached entity class, precede the ID node with this line:

    <!---    <usage= "Read-write"/>    

Then, use the example above to test it.

        Staticvoid Main (String[] args) {isessionfactory_sessionfactory =NewConfiguration (). Configure (). Buildsessionfactory ();UsingISessionNsession =_sessionfactory.opensession ()) {IList<Personmodel> Listperson = nsession.query<personmodel> (). Cacheable (). CacheMode (Cachemode.normal). Cacheregion ("Allcategories"). ToList ();foreach (PersonmodelPInchListperson) {Console.WriteLine (p.name);}} Console.WriteLine ("========================================================= "); using (  ISession  nsession = _sessionfactory.opensession ()) {  IList  <   Personmodel  > ListPerson2 = nsession.    query<personmodel> (). Cacheable (). CacheMode (Cachemode.normal). Cacheregion ("allcategories"     )  . ToList (); foreach (Personmodel P in  ListPerson2) {Console.WriteLine (p.name);} } console.readkey (); }

The output results are as follows:

  

There is nothing to say, read the instructions for the 3 methods.

NHibernate LINQ Query Extension Enhancements (Nineth article)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.