Difference between revisions of "NHibernate"

From no name for this wiki
Jump to: navigation, search
(Cascading)
(one to one)
 
(7 intermediate revisions by the same user not shown)
Line 221: Line 221:
 
</source>
 
</source>
  
== Queries ==
+
== one to one ==
=== OR, Criteria ===
 
 
<source lang="csharp">
 
<source lang="csharp">
var query = context.Session.CreateCriteria<Tag>();

+
using System;
query.Add(Restrictions.Or(
   
+
using FluentNHibernate.Cfg;
  Restrictions.Where<Tag>(t => t.NameDe.IsLike(searchString)),
   
+
using FluentNHibernate.Cfg.Db;
  Restrictions.Where<Tag>(t => t.NameEn.IsLike(searchString))));
             
+
using NHibernate;

return query.List<Tag>();             
              
+
using FluentNHibernate.Mapping;
 +
 
 +
namespace NhOneToOne
 +
{
 +
    public class Program
 +
    {
 +
        static void Main(string[] args)
 +
        {
 +
            try
 +
            {
 +
 
 +
                var sessionFactory = Fluently.Configure()
 +
                                            .Database(
 +
                                                    MsSqlConfiguration.MsSql2005
 +
                                                                      .ConnectionString(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=NHTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False")
 +
                                                                      .ShowSql()
 +
                                              )
 +
                                            .Mappings(m => m
 +
                                            .FluentMappings.AddFromAssemblyOf<Program>())
 +
                                            .BuildSessionFactory();
 +
 
 +
                ISession session = sessionFactory.OpenSession();
 +
 
 +
 
 +
                Child c = session.Get<Child>(1);
 +
                Parent p = c.Parent;
 +
                Child c2 = p.Child;
 +
 
 +
                session.Clear();
 +
 
 +
                p = session.Get<Parent>(2);
 +
                c2 = p.Child;             
 +
 +
            }
 +
            catch (Exception e)
 +
            {
 +
                Console.Write(e.Message);
 +
            }
 +
        }
 +
 
 +
    }
 +
 
 +
    public class Child
 +
    {
 +
        public virtual string Name { get; set; }
 +
        public virtual int Id { get; set; }
 +
 
 +
        public virtual Parent Parent { get; set; }
 +
    }
 +
 
 +
    public class Parent
 +
    {
 +
        public virtual string Name { get; set; }
 +
        public virtual int Id { get; set; }
 +
 
 +
        public virtual Child Child { get; set; }
 +
 
 +
    }
 +
 
 +
    public class ChildMap : ClassMap<Child>
 +
    {
 +
        public ChildMap()
 +
        {
 +
            Table("ChildTable");
 +
            Id(x => x.Id).GeneratedBy.Native();
 +
            Map(x => x.Name);
 +
 
 +
            References(x => x.Parent).Column("IdParent");
 +
 
 +
        }
 +
    }
 +
 
 +
    public class ParentMap : ClassMap<Parent>
 +
    {
 +
        public ParentMap()
 +
        {
 +
            Table("ParentTable");
 +
            Id(x => x.Id).GeneratedBy.Native();
 +
             Map(x => x.Name);
 +
 
 +
            HasOne(x => x.Child).PropertyRef("Parent");
 +
        }
 +
 
 +
    }
 +
}
 +
 
 
</source>
 
</source>
  
=== HQL, Latest related object ===
 
 
<source lang="sql">
 
<source lang="sql">
select item, tag
+
CREATE TABLE [dbo].[ChildTable] (
from MyItem item
+
    [Id]      INT          IDENTITY (1, 1) NOT NULL,
     join item.Tags tag
+
    [IdParent] INT          NOT NULL,
where tag.Id = (                                  
+
     [Name]    VARCHAR (50) NULL
     select  max(tag2.Id)
+
);
     from MyItem item2
+
 
        join item2.Tags tag2
+
CREATE TABLE [dbo].[ParentTable] (
    where item2.Id = item.Id
+
     [Id]  INT          IDENTITY (1, 1) NOT NULL,
     group by item2.Id    
+
     [Name] VARCHAR (MAX) NULL
)
+
);
 +
ALTER TABLE [dbo].[ChildTable]
 +
     ADD CONSTRAINT [FK_ChildTable_ToTable] FOREIGN KEY ([IdParent]) REFERENCES [dbo].[ParentTable] ([Id]);
 
</source>
 
</source>
  
=== OR, Query Over ===
+
== Queries ==
<source lang="csharp">
+
[[NHibernateQueries]]
using (DbContext context = new DbContext())
 
{
 
 
 
    Tag tag = null;
 
 
 
    return context.Session.QueryOver<Tag>()
 
        .Where(t => t.NameDe.IsLike(searchString) || t.NameEn.IsLike(searchString))
 
        .SelectList(
 
        list => list.Select(x => x.Id).WithAlias(() => tag.Id)
 
                    .Select(x => x.NameDe).WithAlias(() => tag.NameDe)
 
                    .Select(x => x.NameEn).WithAlias(() => tag.NameEn))
 
                .TransformUsing(Transformers.AliasToBean<Tag>()).List<Tag>();
 
}          
           
 
</source>
 
  
 
== Insert, Updates und Save() ==
 
== Insert, Updates und Save() ==
Line 299: Line 370:
 
MyTag tag = session.Get<MyTag>(17);
 
MyTag tag = session.Get<MyTag>(17);
 
tag.Name = "Elefant";
 
tag.Name = "Elefant";
session.Save(tag); //Da Transaktion vorhanden ist, wird hier kein Update SQL ausgegeben.
+
session.Save(tag); //Da die Entität bereits eine Id hat, wird hier kein Update SQL ausgegeben.
 
tx.Commit(); //Schreibt die Änderung in die DB.
 
tx.Commit(); //Schreibt die Änderung in die DB.
 
                
 
                
Line 314: Line 385:
 
                
 
                
 
session.Close();
 
session.Close();
</source>      
+
</source>
 
 
Here is what each cascade option means:
 
 
 
none - do not do any cascades, let the users handles them by themselves.
 
save-update - when the object is saved/updated, check the associations and save/update any object that require it (including save/update the associations in many-to-many scenario).
 
delete - when the object is deleted, delete all the objects in the association.
 
delete-orphan - when the object is deleted, delete all the objects in the association. In addition to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.
 
all - when an object is save/update/delete, check the associations and save/update/delete all the objects found.
 
all-delete-orphan - when an object is save/update/delete, check the associations and save/update/delete all the objects found. In additional to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.
 
  
 
== Cascading bei Many to Many ==
 
== Cascading bei Many to Many ==
Line 395: Line 457:
 
== resourcen ==
 
== resourcen ==
 
* http://nhforge.org/doc/nh/en/index.html
 
* http://nhforge.org/doc/nh/en/index.html
 +
* http://stackoverflow.com/questions/713637/inverse-attribute-in-nhibernate

Latest revision as of 22:17, 8 March 2017

Konfigurationsdatei Sample

sqlserver sample

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">Server=(local);Database=nhibernate;Trusted_Connection=true;</property>
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

Mysql example

<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
    <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  </configSections>
  <appSettings>
    <add key="loglevel" value="info"/>
    <add key="logimplementation" value="NLOG"/>
    <add key="exportdirectory" value="/tmp" />
  </appSettings>
  <connectionStrings>
    <add name="testmasterconnection"
         connectionString="server=localhost;user=root;pwd=dukannstmichmal;database=mydb;port=3306;"
         providerName="MySql.Data.MySqlClient" />
  </connectionStrings>

  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="dialect">NHibernate.Dialect.MySQL5Dialect</property>
      <property name="connection.connection_string_name">testmasterconnection</property>
      <property name="show_sql">true</property>
      <property name="hbm2ddl.keywords">none</property>
    </session-factory>
  </hibernate-configuration>

  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <targets>
      <target name="logfile" xsi:type="File" fileName="out.txt" />
      <target name="console" xsi:type="Console" />
    </targets>

    <rules>
      <logger name="*" minLevel="Info" writeTo="logfile" />
      <logger name="*" minLevel="Info" writeTo="console" />
      <logger name="TagsManagement" minLevel="Debug" writeTo="console" />
    </rules>

  </nlog>
</configuration>

many to many mapping

Mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ConsoleApplication2"
                   namespace="ConsoleApplication2">

  <class name="MyItem">
    
    <id name="ID" generator="native"/>
    
    <property name="Name" />

    <!-- Many-to-many mapping: OrderItems -->
    <bag name="Tags" 
         table="MyItem_MyTag" 
         cascade="none" 
         lazy="true">
      <key column ="MyItemID" />
      <many-to-many class="MyTag" column="MyTagID" />
    </bag>
    
  </class>

</hibernate-mapping>

Klasse:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    public class MyItem
    {
        public virtual string Name { get; set; }
        public virtual int ID { get; set; }

        IList<MyTag> _tags = new List<MyTag>();
        public virtual IList<MyTag> Tags {
            get
            {
                return this._tags;
            }
            set
            {
                _tags = value;
            }
        }
    }
}

Konfiguration mit fluet configuration

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NHibernate.Cfg;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;

namespace ConsoleApplication2
{
    class Program
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            try
            {

                var sessionFactory = Fluently.Configure()
                                             .Database(
                                                    MsSqlConfiguration.MsSql2005
                                                                      .ConnectionString(
"Server=(local);Database=nhibernate;Trusted_Connection=true;")
                                                                      .ShowSql()
                                              )
                                             .Mappings(m => m
                                             .FluentMappings.AddFromAssemblyOf<Program>())
                                             .BuildSessionFactory();

                ISession session = sessionFactory.OpenSession();



                ...
                  
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
        }
    }
}

using FluentNHibernate.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2.Mappings
{
    class MyItemMap : ClassMap<MyItem>
    {
        public MyItemMap()
        {
            Id(x => x.ID).GeneratedBy.Native();

            Map(x => x.Name);

            HasManyToMany(x => x.Tags)
                .Table("MyItem_MyTag")
                .ParentKeyColumn("MyItemID")
                .ChildKeyColumn("MyTagID")
                .Cascade.None().LazyLoad();

        }
    }
}

Wenn Fremdschlüssel kein Constraint aufweist:

 //Cache einschalten:
 Cache.ReadOnly().Region("Keep15Min");

 //Fremdschlüssel ohne Fremdschlüsselconstraint
 References(x => x.Verantwortlicher, "strVerantwortlicher").Nullable()
                .ForeignKey("FK_Vertrag_Verantwortlicher_Employee")
                .Index("IX_strVerantwortlicherId")
                .NotFound.Ignore()
                .Access.CamelCaseField(Prefix.Underscore);

one to one

using System;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using FluentNHibernate.Mapping;

namespace NhOneToOne
{
    public class Program
    {
        static void Main(string[] args)
        {
            try
            {

                var sessionFactory = Fluently.Configure()
                                             .Database(
                                                    MsSqlConfiguration.MsSql2005
                                                                      .ConnectionString(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=NHTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False")
                                                                      .ShowSql()
                                              )
                                             .Mappings(m => m
                                             .FluentMappings.AddFromAssemblyOf<Program>())
                                             .BuildSessionFactory();

                ISession session = sessionFactory.OpenSession();


                Child c = session.Get<Child>(1);
                Parent p = c.Parent;
                Child c2 = p.Child;

                session.Clear();

                p = session.Get<Parent>(2);
                c2 = p.Child;               
 
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
        }

    }

    public class Child
    {
        public virtual string Name { get; set; }
        public virtual int Id { get; set; }

        public virtual Parent Parent { get; set; }
    }

    public class Parent
    {
        public virtual string Name { get; set; }
        public virtual int Id { get; set; }

        public virtual Child Child { get; set; }

    }

    public class ChildMap : ClassMap<Child>
    {
        public ChildMap()
        {
            Table("ChildTable");
            Id(x => x.Id).GeneratedBy.Native();
            Map(x => x.Name);

            References(x => x.Parent).Column("IdParent");

        }
    }

    public class ParentMap : ClassMap<Parent>
    {
        public ParentMap()
        {
            Table("ParentTable");
            Id(x => x.Id).GeneratedBy.Native();
            Map(x => x.Name);

            HasOne(x => x.Child).PropertyRef("Parent");
        }

    }
}
CREATE TABLE [dbo].[ChildTable] (
    [Id]       INT          IDENTITY (1, 1) NOT NULL,
    [IdParent] INT          NOT NULL,
    [Name]     VARCHAR (50) NULL
);

CREATE TABLE [dbo].[ParentTable] (
    [Id]   INT           IDENTITY (1, 1) NOT NULL,
    [Name] VARCHAR (MAX) NULL
);
ALTER TABLE [dbo].[ChildTable]
    ADD CONSTRAINT [FK_ChildTable_ToTable] FOREIGN KEY ([IdParent]) REFERENCES [dbo].[ParentTable] ([Id]);

Queries

NHibernateQueries

Insert, Updates und Save()

Hier gibt es keine Änderung an der Datenbank:

ISession session = sessionFactory.OpenSession();
MyTag tag = session.Get<MyTag>(17);
tag.Name = "Furunkel"; //Wird nicht in DB übernommen.
session.Close();

Ohne Transaktion kein Update.


Änderung an der Datenbank ohne Save:

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
MyTag tag = session.Get<MyTag>(17);
tag.Name = "Furunkel";
tx.Commit(); //Schreibt die Änderung in die DB.

Save:

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
MyTag tag = new MyTag();
tag.Name = "test";
session.Save(tag); //Insert Statement wird hier zur DB ausgegeben. Id von db wird hier gelöst.
tx.Commit();

Save mit Update:

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
MyTag tag = session.Get<MyTag>(17);
tag.Name = "Elefant";
session.Save(tag); //Da die Entität bereits eine Id hat,  wird hier kein Update SQL ausgegeben.
tx.Commit(); //Schreibt die Änderung in die DB.
              
session.Close();

Das macht gar nichts:

ISession session = sessionFactory.OpenSession();
MyTag tag = session.Get<MyTag>(17);
tag.Name = "Elefant";
session.Save(tag); //Das macht gar nichts, da keine Tx vorhanden ist.
              
session.Close();

Cascading bei Many to Many

Insert

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();

MyItem item = new MyItem { Name = "CascadeAllItem" };
MyTag tag = new MyTag { Name = "CascadeAllTag" };
item.Tags.Add(tag);

session.Save(item);

tx.Commit(); 
              
session.Close();
  • None(): NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave.
  • SaveUpdate(): Beide Entitäten werden in die Datenbank eingefügt.
  • Delete(): NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave.
  • Merge(): NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave.
  • All(): Beide Entitäten werden in die Datenbank eingefügt.
  • AllDeleteOrphan(): Beide Entitäten werden in die Datenbank eingefügt.

Delete

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();

MyItem item = session.Get<MyItem>(27); //Item enthält ein Tag.

session.Delete(item);

tx.Commit(); 
              
session.Close();
  • None(): Nur MyItem wird gelöscht.
  • All(): MyItem und MyTag wird gelöscht.
  • Merge(): Nur MyItem wird gelöscht.
  • Delete(): MyItem und MyTag wird gelöscht.
  • DeleteAll(): MyItem und MyTag wird gelöscht.
  • DeleteOrphan(): MyItem und MyTag wird gelöscht.
  • AllDeleteOrphan(): MyItem und MyTag wird gelöscht.

Remove from collection

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();

MyItem item = session.Get<MyItem>(37); //Item enthält ein Tag.

item.Tags.Clear();

tx.Commit(); 
              
session.Close();
  • None(): Tag wird nicht gelöscht. Verknüpfung zwischen Tag und Item wird entfernt.
  • All(): Tag wird nicht gelöscht. Verknüpfung zwischen Tag und Item wird entfernt.
  • Merge(): Tag wird nicht gelöscht. Verknüpfung zwischen Tag und Item wird entfernt.
  • Delete(): Tag wird nicht gelöscht. Verknüpfung zwischen Tag und Item wird entfernt.
  • DeleteAll(): Tag wird nicht gelöscht. Verknüpfung zwischen Tag und Item wird entfernt.
  • DeleteOrphan(): Tag wird gelöscht.
  • AllDeleteOrphan(): Tag wird gelöscht.

resourcen