In this chapter, we will be covering how to override NHibernate configuration. There are just a few things you need to keep in mind.
First of all, configuration in NHibernate is additive.
So you don't just have to use a single xml file or you don't just have to use the code-based configuration or fluent NHibernate.
You can mix and match all of these methods depending on how you want to configure your application.
The important point to remember is that, lastly configuration wins.
In the following example, you can see that we create our configuration object, configure it using the code-based configuration and finally call the cfg.configure() method, which loads the hibernate.cfg.xml file.
String Data Source = asia13797\\sqlexpress; String Initial Catalog = NHibernateDemoDB; String Integrated Security = True; String Connect Timeout = 15; String Encrypt = False; String TrustServerCertificate = False; String ApplicationIntent = ReadWrite; String MultiSubnetFailover = False; cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + Initial Catalog + Integrated Security + Connect Timeout + Encrypt + TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); x.LogSqlInConsole = true; }); cfg.Configure();
So anything inside of a hibernate.cfg.xml overrides the settings set by code-based configuration.
By reversing these two processes we can have the defaults inside of hibernate.cfg.xml and then do our overrides inside of a code-based configuration.
There is nothing that excludes if you are using code-based configuration and also there is nothing that prevents you from using the hibernate.cfg.xml file.
Let’s have a look into a simple example in which we will override the configuration by using a mixture of xml-based and code-based configuration.
Let’s also move the connection string to the app.config file using the following code.
<?xml version = "1.0" encoding = "utf-8" ?> <configuration> <startup> <supportedRuntime version = "v4.0" sku = ".NETFramework,Version = v4.5" /> </startup> <connectionStrings> <add name = "default" connectionString = "Data Source = asia13797\\sqlexpress; Initial Catalog = NHibernateDemoDB; Integrated Security = True; Connect Timeout = 15; Encrypt = False; TrustServerCertificate = False; ApplicationIntent = ReadWrite; MultiSubnetFailover = False"/> </connectionStrings> </configuration>
The connection string is sitting in some app.config file with a default name. Now, we need to mention the default name in hibernate.cfg.xml file instead of the connection string.
<?xml version = "1.0" encoding = "utf-8" ?> <hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2"> <session-factory> <property name = "connection.connection_string">default</property> <property name = "connection.driver_class"> NHibernate.Driver.SqlClientDriver </property> <property name = "dialect"> NHibernate.Dialect.MsSql2008Dialect </property> <mapping assembly = "NHibernateDemoApp"/> </session-factory> </hibernate-configuration>
Let’s comment on the connection string part, driver, and dialect part from the code-based configuration, because the program will read it from the hibernate.cfg.xml file and the LogSqlInConsole part will remain in the code-based configuration.
using HibernatingRhinos.Profiler.Appender.NHibernate; using NHibernate.Cfg; using NHibernate.Dialect; using NHibernate.Driver; using System; using System.Linq; using System.Reflection; namespace NHibernateDemoApp { class Program { static void Main(string[] args) { NHibernateProfiler.Initialize(); var cfg = new Configuration(); String Data Source = asia13797\\sqlexpress; String Initial Catalog = NHibernateDemoDB; String Integrated Security = True; String Connect Timeout = 15; String Encrypt = False; String TrustServerCertificate = False; String ApplicationIntent = ReadWrite; String MultiSubnetFailover = False; cfg.DataBaseIntegration(x = > { //x.ConnectionString = "Data Source + Initial Catalog + Integrated Security + Connect Timeout + Encrypt + TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; //x.Driver<SqlClientDriver>(); //x.Dialect<MsSql2008Dialect>(); x.LogSqlInConsole = true; }); cfg.Configure(); cfg.AddAssembly(Assembly.GetExecutingAssembly()); var sefact = cfg.BuildSessionFactory(); using (var session = sefact.OpenSession()) { using (var tx = session.BeginTransaction()) { var students = session.CreateCriteria<Student>().List<Student>(); Console.WriteLine("\nFetch the complete list again\n"); foreach (var student in students) { Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID, student.FirstName, student.LastName, student.AcademicStanding); } tx.Commit(); } Console.ReadLine(); } } } }
Now when you run the application, you will see that the program has read the log from code-based configuration and other configuration from the hibernate.cfg.xml file.
NHibernate: SELECT this_.ID as ID0_0_, this_.LastName as LastName0_0_, this_.FirstMidName as FirstMid3_0_0_, this_.AcademicStanding as Academic4_0_0_ FROM Student this_ Fetch the complete list again 1 Allan Bommer Excellent 2 Jerry Lewis Good
So now we have got some of our configuration inside of our hibernate.cfg.xml file, some of it is inside of the code-based configuration and depending on the order of calling code-based versus configure(), we can change which of them overrides the other.