Make the MySqlGeneric layer transaction aware

melanie
Melanie Thielker 2017-03-23 23:00:48 +00:00
parent 3e880cee45
commit 680231d7e7
2 changed files with 159 additions and 87 deletions

View File

@ -36,7 +36,7 @@ using MySql.Data.MySqlClient;
namespace OpenSim.Data.MySQL namespace OpenSim.Data.MySQL
{ {
/// <summary> /// <summary>
/// A database interface class to a user profile storage system /// Common code for a number of database modules
/// </summary> /// </summary>
public class MySqlFramework public class MySqlFramework
{ {
@ -44,14 +44,24 @@ namespace OpenSim.Data.MySQL
log4net.LogManager.GetLogger( log4net.LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected string m_connectionString; protected string m_connectionString = String.Empty;
protected object m_dbLock = new object(); protected MySqlTransaction m_trans = null;
// Constructor using a connection string. Instances constructed
// this way will open a new connection for each call.
protected MySqlFramework(string connectionString) protected MySqlFramework(string connectionString)
{ {
m_connectionString = connectionString; m_connectionString = connectionString;
} }
// Constructor using a connection object. Instances constructed
// this way will use the connection object and never create
// new connections.
protected MySqlFramework(MySqlTransaction trans)
{
m_trans = trans;
}
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// //
// All non queries are funneled through one connection // All non queries are funneled through one connection
@ -59,33 +69,48 @@ namespace OpenSim.Data.MySQL
// //
protected int ExecuteNonQuery(MySqlCommand cmd) protected int ExecuteNonQuery(MySqlCommand cmd)
{ {
lock (m_dbLock) if (m_trans == null)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
try dbcon.Open();
{ return ExecuteNonQueryWithConnection(cmd, dbcon);
dbcon.Open();
cmd.Connection = dbcon;
try
{
return cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error(e.Message, e);
m_log.Error(Environment.StackTrace.ToString());
return 0;
}
}
catch (Exception e)
{
m_log.Error(e.Message, e);
return 0;
}
} }
} }
else
{
return ExecuteNonQueryWithTransaction(cmd, m_trans);
}
}
private int ExecuteNonQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans)
{
cmd.Transaction = trans;
return ExecuteNonQueryWithConnection(cmd, trans.Connection);
}
private int ExecuteNonQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon)
{
try
{
cmd.Connection = dbcon;
try
{
return cmd.ExecuteNonQuery();
}
catch (Exception e)
{
m_log.Error(e.Message, e);
m_log.Error(Environment.StackTrace.ToString());
return 0;
}
}
catch (Exception e)
{
m_log.Error(e.Message, e);
return 0;
}
} }
} }
} }

View File

@ -53,14 +53,27 @@ namespace OpenSim.Data.MySQL
get { return GetType().Assembly; } get { return GetType().Assembly; }
} }
public MySQLGenericTableHandler(MySqlTransaction trans,
string realm, string storeName) : base(trans)
{
m_Realm = realm;
CommonConstruct(storeName);
}
public MySQLGenericTableHandler(string connectionString, public MySQLGenericTableHandler(string connectionString,
string realm, string storeName) : base(connectionString) string realm, string storeName) : base(connectionString)
{ {
m_Realm = realm; m_Realm = realm;
m_connectionString = connectionString;
CommonConstruct(storeName);
}
protected void CommonConstruct(string storeName)
{
if (storeName != String.Empty) if (storeName != String.Empty)
{ {
// We always use a new connection for any Migrations
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
dbcon.Open(); dbcon.Open();
@ -110,6 +123,11 @@ namespace OpenSim.Data.MySQL
} }
public virtual T[] Get(string[] fields, string[] keys) public virtual T[] Get(string[] fields, string[] keys)
{
return Get(fields, keys, String.Empty);
}
public virtual T[] Get(string[] fields, string[] keys, string options)
{ {
if (fields.Length != keys.Length) if (fields.Length != keys.Length)
return new T[0]; return new T[0];
@ -126,8 +144,8 @@ namespace OpenSim.Data.MySQL
string where = String.Join(" and ", terms.ToArray()); string where = String.Join(" and ", terms.ToArray());
string query = String.Format("select * from {0} where {1}", string query = String.Format("select * from {0} where {1} {2}",
m_Realm, where); m_Realm, where, options);
cmd.CommandText = query; cmd.CommandText = query;
@ -136,73 +154,93 @@ namespace OpenSim.Data.MySQL
} }
protected T[] DoQuery(MySqlCommand cmd) protected T[] DoQuery(MySqlCommand cmd)
{
if (m_trans == null)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
return DoQueryWithConnection(cmd, dbcon);
}
}
else
{
return DoQueryWithTransaction(cmd, m_trans);
}
}
protected T[] DoQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans)
{
cmd.Transaction = trans;
return DoQueryWithConnection(cmd, trans.Connection);
}
protected T[] DoQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon)
{ {
List<T> result = new List<T>(); List<T> result = new List<T>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) cmd.Connection = dbcon;
using (IDataReader reader = cmd.ExecuteReader())
{ {
dbcon.Open(); if (reader == null)
cmd.Connection = dbcon; return new T[0];
using (IDataReader reader = cmd.ExecuteReader()) CheckColumnNames(reader);
while (reader.Read())
{ {
if (reader == null) T row = new T();
return new T[0];
CheckColumnNames(reader); foreach (string name in m_Fields.Keys)
while (reader.Read())
{ {
T row = new T(); if (reader[name] is DBNull)
foreach (string name in m_Fields.Keys)
{ {
if (reader[name] is DBNull) continue;
{
continue;
}
if (m_Fields[name].FieldType == typeof(bool))
{
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v != 0 ? true : false);
}
else if (m_Fields[name].FieldType == typeof(UUID))
{
m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name]));
}
else if (m_Fields[name].FieldType == typeof(int))
{
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v);
}
else if (m_Fields[name].FieldType == typeof(uint))
{
uint v = Convert.ToUInt32(reader[name]);
m_Fields[name].SetValue(row, v);
}
else
{
m_Fields[name].SetValue(row, reader[name]);
}
} }
if (m_Fields[name].FieldType == typeof(bool))
if (m_DataField != null)
{ {
Dictionary<string, string> data = int v = Convert.ToInt32(reader[name]);
new Dictionary<string, string>(); m_Fields[name].SetValue(row, v != 0 ? true : false);
}
foreach (string col in m_ColumnNames) else if (m_Fields[name].FieldType == typeof(UUID))
{ {
data[col] = reader[col].ToString(); m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name]));
if (data[col] == null) }
data[col] = String.Empty; else if (m_Fields[name].FieldType == typeof(int))
} {
int v = Convert.ToInt32(reader[name]);
m_DataField.SetValue(row, data); m_Fields[name].SetValue(row, v);
}
else if (m_Fields[name].FieldType == typeof(uint))
{
uint v = Convert.ToUInt32(reader[name]);
m_Fields[name].SetValue(row, v);
}
else
{
m_Fields[name].SetValue(row, reader[name]);
} }
result.Add(row);
} }
if (m_DataField != null)
{
Dictionary<string, string> data =
new Dictionary<string, string>();
foreach (string col in m_ColumnNames)
{
data[col] = reader[col].ToString();
if (data[col] == null)
data[col] = String.Empty;
}
m_DataField.SetValue(row, data);
}
result.Add(row);
} }
} }
@ -357,14 +395,23 @@ namespace OpenSim.Data.MySQL
public object DoQueryScalar(MySqlCommand cmd) public object DoQueryScalar(MySqlCommand cmd)
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) if (m_trans == null)
{ {
dbcon.Open(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
cmd.Connection = dbcon; {
dbcon.Open();
cmd.Connection = dbcon;
return cmd.ExecuteScalar();
}
}
else
{
cmd.Connection = m_trans.Connection;
cmd.Transaction = m_trans;
return cmd.ExecuteScalar(); return cmd.ExecuteScalar();
} }
} }
} }
} }