/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Data.Common; using System.Reflection; using log4net; using NHibernate; using NHibernate.Cfg; using NHibernate.Tool.hbm2ddl; using OpenMetaverse; using Environment=NHibernate.Cfg.Environment; namespace OpenSim.Data.NHibernate { public class NHibernateManager { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private string dialect; private Configuration configuration; private ISessionFactory sessionFactory; #region Initialization /// /// Initiate NHibernate Manager /// /// NHibernate dialect, driver and connection string separated by ';' /// Name of the store public NHibernateManager(string connect, string store) { ParseConnectionString(connect); //To create sql file uncomment code below and write the name of the file //SchemaExport exp = new SchemaExport(cfg); //exp.SetOutputFile("nameofthefile.sql"); //exp.Create(false, true); Assembly assembly = GetType().Assembly; sessionFactory = configuration.BuildSessionFactory(); RunMigration(dialect, assembly, store); } /// /// Initiate NHibernate Manager with spesific assembly /// /// NHibernate dialect, driver and connection string separated by ';' /// Name of the store /// Outside assembly to be included public NHibernateManager(string connect, string store, Assembly assembly) { ParseConnectionString(connect); configuration.AddAssembly(assembly); sessionFactory = configuration.BuildSessionFactory(); RunMigration(dialect, assembly, store); } /// /// Parses the connection string and creates the NHibernate configuration /// /// NHibernate dialect, driver and connection string separated by ';' private void ParseConnectionString(string connect) { // Split out the dialect, driver, and connect string char[] split = { ';' }; string[] parts = connect.Split(split, 3); if (parts.Length != 3) { // TODO: make this a real exception type throw new Exception("Malformed Inventory connection string '" + connect + "'"); } dialect = parts[0]; // NHibernate setup configuration = new Configuration(); configuration.SetProperty(Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider"); configuration.SetProperty(Environment.Dialect, "NHibernate.Dialect." + dialect); configuration.SetProperty(Environment.ConnectionDriver, "NHibernate.Driver." + parts[1]); configuration.SetProperty(Environment.ConnectionString, parts[2]); configuration.AddAssembly("OpenSim.Data.NHibernate"); } /// /// Runs migration for the the store in assembly /// /// Dialect in use /// Assembly where migration files exist /// Name of the store in use private void RunMigration(string dialect, Assembly assembly, string store) { // Migration subtype is the folder name under which migrations are stored. For mysql this folder is // MySQLDialect instead of MySQL5Dialect which is the dialect currently in use. To avoid renaming // this folder each time the mysql version changes creating simple mapping: String migrationSubType = dialect; if (dialect.StartsWith("MySQL")) { migrationSubType = "MySQLDialect"; } Migration migration = new Migration((DbConnection)sessionFactory.ConnectionProvider.GetConnection(), assembly, migrationSubType, store); migration.Update(); } #endregion /// /// Gets object of given type from database with given id. /// Uses stateless session for efficiency. /// /// Type of the object. /// Id of the object. /// The object or null if object was not found. public object Get(Type type, Object id) { using (IStatelessSession session = sessionFactory.OpenStatelessSession()) { object obj = null; try { obj = session.Get(type.FullName, id); } catch (Exception e) { m_log.ErrorFormat("[NHIBERNATE] {0} of id {1} loading threw exception: " + e.ToString(), type.Name, id); } return obj; } } /// /// Gets object of given type from database with given id. /// Use this method for objects containing collections. For flat objects stateless mode is more efficient. /// /// Type of the object. /// Id of the object. /// The object or null if object was not found. public object GetWithStatefullSession(Type type, Object id) { using (ISession session = sessionFactory.OpenSession()) { object obj = null; try { obj = session.Get(type.FullName, id); } catch (Exception e) { m_log.ErrorFormat("[NHIBERNATE] {0} of id {1} loading threw exception: " + e.ToString(), type.Name, id); } return obj; } } /// /// Inserts given object to database. /// Uses stateless session for efficiency. /// /// Object to be insterted. /// Identifier of the object. Useful for situations when NHibernate generates the identifier. public object Insert(object obj) { try { using (IStatelessSession session = sessionFactory.OpenStatelessSession()) { using (ITransaction transaction=session.BeginTransaction()) { Object identifier=session.Insert(obj); transaction.Commit(); return identifier; } } } catch (Exception e) { m_log.Error("[NHIBERNATE] issue inserting object ", e); return null; } } /// /// Inserts given object to database. /// Use this method for objects containing collections. For flat objects stateless mode is more efficient. /// /// Object to be insterted. /// Identifier of the object. Useful for situations when NHibernate generates the identifier. public object InsertWithStatefullSession(object obj) { try { using (ISession session = sessionFactory.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { Object identifier = session.Save(obj); transaction.Commit(); return identifier; } } } catch (Exception e) { m_log.Error("[NHIBERNATE] issue inserting object ", e); return null; } } /// /// Updates given object to database. /// Uses stateless session for efficiency. /// /// Object to be updated. /// True if operation was succesful. public bool Update(object obj) { try { using (IStatelessSession session = sessionFactory.OpenStatelessSession()) { using (ITransaction transaction = session.BeginTransaction()) { session.Update(obj); transaction.Commit(); return true; } } } catch (Exception e) { m_log.Error("[NHIBERNATE] issue updating object ", e); return false; } } /// /// Updates given object to database. /// Use this method for objects containing collections. For flat objects stateless mode is more efficient. /// /// Object to be updated. /// True if operation was succesful. public bool UpdateWithStatefullSession(object obj) { try { using (ISession session = sessionFactory.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { session.Update(obj); transaction.Commit(); return true; } } } catch (Exception e) { m_log.Error("[NHIBERNATE] issue updating object ", e); return false; } } /// /// Deletes given object from database. /// /// Object to be deleted. /// True if operation was succesful. public bool Delete(object obj) { try { using (IStatelessSession session = sessionFactory.OpenStatelessSession()) { using (ITransaction transaction = session.BeginTransaction()) { session.Delete(obj); transaction.Commit(); return true; } } } catch (Exception e) { m_log.Error("[NHIBERNATE] issue deleting object ", e); return false; } } /// /// Returns statefull session which can be used to execute custom nhibernate or sql queries. /// /// Statefull session public ISession GetSession() { return sessionFactory.OpenSession(); } /// /// Drops the database schema. This exist for unit tests. It should not be invoked from other than test teardown. /// public void DropSchema() { SchemaExport export = new SchemaExport(this.configuration); export.Drop(true, true); using (ISession session = sessionFactory.OpenSession()) { ISQLQuery sqlQuery = session.CreateSQLQuery("drop table migrations"); sqlQuery.ExecuteUpdate(); } } } }