@@ -467,6 +467,119 @@ IList<Cat> oldCats =
467
467
.ToList();]]> </programlisting >
468
468
</sect1 >
469
469
470
+ <sect1 id =" querylinq-modifying" >
471
+ <title >Modifying entities inside the database</title >
472
+
473
+ <para >
474
+ Beginning with NHibernate 5.0, Linq queries can be used for inserting, updating or deleting entities.
475
+ The query defines the data to delete, update or insert, and then <literal >Delete</literal >,
476
+ <literal >Update</literal >, <literal >UpdateBuilder</literal >, <literal >InsertInto</literal > and
477
+ <literal >InsertBuilder</literal > queryable extension methods allow to delete it,
478
+ or instruct in which way it should be updated or inserted. Those queries happen entirely inside the
479
+ database, without extracting corresponding entities out of the database.
480
+ </para >
481
+ <para >
482
+ These operations are a Linq implementation of <xref linkend =" batch-direct" />, with the same abilities
483
+ and limitations.
484
+ </para >
485
+
486
+ <sect2 id =" querylinq-modifying-insert" >
487
+ <title >Inserting new entities</title >
488
+ <para >
489
+ <literal >InsertInto</literal > and <literal >InsertBuilder</literal > method extensions expect a NHibernate
490
+ queryable defining the data source of the insert. This data can be entities or a projection. Then they
491
+ allow specifying the target entity type to insert, and how to convert source data to those target
492
+ entities. Three forms of target specification exist.
493
+ </para >
494
+ <para >
495
+ Using projection to target entity:
496
+ </para >
497
+ <programlisting ><![CDATA[ session.Query<Cat>()
498
+ .Where(c => c.BodyWeight > 20)
499
+ .InsertInto(c => new Dog { Name = c.Name + "dog", BodyWeight = c.BodyWeight });]]> </programlisting >
500
+ <para >
501
+ Projections can be done with an anonymous object too, but it requires supplying explicitly the target
502
+ type, which in turn requires re-specifying the source type:
503
+ </para >
504
+ <programlisting ><![CDATA[ session.Query<Cat>()
505
+ .Where(c => c.BodyWeight > 20)
506
+ .InsertInto<Cat, Dog>(c => new { Name = c.Name + "dog", BodyWeight = c.BodyWeight });]]> </programlisting >
507
+ <para >
508
+ Or using assignments:
509
+ </para >
510
+ <programlisting ><![CDATA[ session.Query<Cat>()
511
+ .Where(c => c.BodyWeight > 20)
512
+ .InsertBuilder()
513
+ .Into<Dog>()
514
+ .Value(d => d.Name, c => c.Name + "dog")
515
+ .Value(d => d.BodyWeight, c => c.BodyWeight)
516
+ .Insert();]]> </programlisting >
517
+ <para >
518
+ In all cases, unspecified properties are not included in the resulting SQL insert.
519
+ <link linkend =" mapping-declaration-version" ><literal >version</literal ></link > and
520
+ <link linkend =" mapping-declaration-timestamp" ><literal >timestamp</literal ></link > properties are
521
+ exceptions. If not specified, they are inserted with their <literal >seed</literal > value.
522
+ </para >
523
+ <para >
524
+ For more information on <literal >Insert</literal > limitations, please refer to
525
+ <xref linkend =" batch-direct" />.
526
+ </para >
527
+ </sect2 >
528
+
529
+ <sect2 id =" querylinq-modifying-update" >
530
+ <title >Updating entities</title >
531
+ <para >
532
+ <literal >Update</literal > and <literal >UpdateBuilder</literal > method extensions expect a NHibernate
533
+ queryable defining the entities to update. Then they allow specifying which properties should be
534
+ updated with which values. As for insertion, three forms of target specification exist.
535
+ </para >
536
+ <para >
537
+ Using projection to updated entity:
538
+ </para >
539
+ <programlisting ><![CDATA[ session.Query<Cat>()
540
+ .Where(c => c.BodyWeight > 20)
541
+ .Update(c => new Cat { BodyWeight = c.BodyWeight / 2 });]]> </programlisting >
542
+ <para >
543
+ Projections can be done with an anonymous object too:
544
+ </para >
545
+ <programlisting ><![CDATA[ session.Query<Cat>()
546
+ .Where(c => c.BodyWeight > 20)
547
+ .Update(c => new { BodyWeight = c.BodyWeight / 2 });]]> </programlisting >
548
+ <para >
549
+ Or using assignments:
550
+ </para >
551
+ <programlisting ><![CDATA[ session.Query<Cat>()
552
+ .Where(c => c.BodyWeight > 20)
553
+ .UpdateBuilder()
554
+ .Set(c => c.BodyWeight, c => c.BodyWeight / 2)
555
+ .Update();]]> </programlisting >
556
+ <para >
557
+ In all cases, unspecified properties are not included in the resulting SQL update. This could
558
+ be changed for <link linkend =" mapping-declaration-version" ><literal >version</literal ></link > and
559
+ <link linkend =" mapping-declaration-timestamp" ><literal >timestamp</literal ></link > properties:
560
+ using <literal >UpdateVersioned</literal > instead of <literal >Update</literal > allows incrementing
561
+ the version. Custom version types (<literal >NHibernate.Usertype.IUserVersionType</literal >) are
562
+ not supported.
563
+ </para >
564
+ <para >
565
+ When using projection to updated entity, please note that the constructed entity must have the
566
+ exact same type than the underlying queryable source type. Attempting to project to any other class
567
+ (anonymous projections excepted) will fail.
568
+ </para >
569
+ </sect2 >
570
+
571
+ <sect2 id =" querylinq-modifying-delete" >
572
+ <title >Deleting entities</title >
573
+ <para >
574
+ <literal >Delete</literal > method extension expects a queryable defining the entities to delete.
575
+ It immediately deletes them.
576
+ </para >
577
+ <programlisting ><![CDATA[ session.Query<Cat>()
578
+ .Where(c => c.BodyWeight > 20)
579
+ .Delete();]]> </programlisting >
580
+ </sect2 >
581
+ </sect1 >
582
+
470
583
<sect1 id =" querylinq-querycache" >
471
584
<title >Query cache</title >
472
585
0 commit comments