346 lines
13 KiB
C#
346 lines
13 KiB
C#
/*
|
|
* 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
|
|
|
|
/// <summary>
|
|
/// Initiate NHibernate Manager
|
|
/// </summary>
|
|
/// <param name="connect">NHibernate dialect, driver and connection string separated by ';'</param>
|
|
/// <param name="store">Name of the store</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initiate NHibernate Manager with spesific assembly
|
|
/// </summary>
|
|
/// <param name="connect">NHibernate dialect, driver and connection string separated by ';'</param>
|
|
/// <param name="store">Name of the store</param>
|
|
/// <param name="assembly">Outside assembly to be included </param>
|
|
public NHibernateManager(string connect, string store, Assembly assembly)
|
|
{
|
|
ParseConnectionString(connect);
|
|
|
|
configuration.AddAssembly(assembly);
|
|
sessionFactory = configuration.BuildSessionFactory();
|
|
RunMigration(dialect, assembly, store);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses the connection string and creates the NHibernate configuration
|
|
/// </summary>
|
|
/// <param name="connect">NHibernate dialect, driver and connection string separated by ';'</param>
|
|
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");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs migration for the the store in assembly
|
|
/// </summary>
|
|
/// <param name="dialect">Dialect in use</param>
|
|
/// <param name="assembly">Assembly where migration files exist</param>
|
|
/// <param name="store">Name of the store in use</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Gets object of given type from database with given id.
|
|
/// Uses stateless session for efficiency.
|
|
/// </summary>
|
|
/// <param name="type">Type of the object.</param>
|
|
/// <param name="id">Id of the object.</param>
|
|
/// <returns>The object or null if object was not found.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="type">Type of the object.</param>
|
|
/// <param name="id">Id of the object.</param>
|
|
/// <returns>The object or null if object was not found.</returns>
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserts given object to database.
|
|
/// Uses stateless session for efficiency.
|
|
/// </summary>
|
|
/// <param name="obj">Object to be insterted.</param>
|
|
/// <returns>Identifier of the object. Useful for situations when NHibernate generates the identifier.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserts given object to database.
|
|
/// Use this method for objects containing collections. For flat objects stateless mode is more efficient.
|
|
/// </summary>
|
|
/// <param name="obj">Object to be insterted.</param>
|
|
/// <returns>Identifier of the object. Useful for situations when NHibernate generates the identifier.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates given object to database.
|
|
/// Uses stateless session for efficiency.
|
|
/// </summary>
|
|
/// <param name="obj">Object to be updated.</param>
|
|
/// <returns>True if operation was succesful.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates given object to database.
|
|
/// Use this method for objects containing collections. For flat objects stateless mode is more efficient.
|
|
/// </summary>
|
|
/// <param name="obj">Object to be updated.</param>
|
|
/// <returns>True if operation was succesful.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes given object from database.
|
|
/// </summary>
|
|
/// <param name="obj">Object to be deleted.</param>
|
|
/// <returns>True if operation was succesful.</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns statefull session which can be used to execute custom nhibernate or sql queries.
|
|
/// </summary>
|
|
/// <returns>Statefull session</returns>
|
|
public ISession GetSession()
|
|
{
|
|
return sessionFactory.OpenSession();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drops the database schema. This exist for unit tests. It should not be invoked from other than test teardown.
|
|
/// </summary>
|
|
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();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|