Skip to content

Instantly share code, notes, and snippets.

@pedoc
Created December 29, 2021 05:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pedoc/808a11b8bc06284f5ea2ec75ec090955 to your computer and use it in GitHub Desktop.
Save pedoc/808a11b8bc06284f5ea2ec75ec090955 to your computer and use it in GitHub Desktop.
MySqlConnectorConnectionProvider for DevExpress.Xpo
using System;
using System.Data;
using System.Globalization;
using System.Reflection;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.DB.Helpers;
// ReSharper disable InconsistentNaming
namespace SN.Instrument.DataAccess.Xpo.ConnectionProviders
{
public class MySqlConnectorConnectionProvider : MySqlConnectionProvider
{
public new const string XpoProviderTypeString = "MySqlConnector";
ReflectConnectionHelper helper;
ReflectConnectionHelper ConnectionHelper
{
get
{
if (helper == null)
helper = new ReflectConnectionHelper(Connection, "MySqlConnector.MySqlException");
return helper;
}
}
DbTypeMapperBase dbTypeMapper;
protected override DbTypeMapperBase DbTypeMapper
{
get
{
if (dbTypeMapper == null)
{
Type mySqlParameterType = ConnectionHelper.GetType("MySqlConnector.MySqlParameter");
Type mySqlDbTypeType = ConnectionHelper.GetType("MySqlConnector.MySqlDbType");
bool isSupport80 = SupportVersion(8, 0);
dbTypeMapper = (DbTypeMapperBase)Activator.CreateInstance(typeof(DbTypeMapperMySql<,>).MakeGenericType(mySqlDbTypeType, mySqlParameterType), new object[] { isSupport80 });
}
return dbTypeMapper;
}
}
decimal? versionMajor;
int versionMinor;
MethodInfo miServerVersion;
void ReadDbVersion(IDbConnection conn)
{
if (miServerVersion == null)
{
Type connType = conn.GetType();
PropertyInfo pi = connType.GetProperty("ServerVersion", BindingFlags.Instance | BindingFlags.Public);
if (pi != null && pi.CanRead)
{
miServerVersion = pi.GetGetMethod();
}
}
if (miServerVersion != null)
{
string versionString = (string)miServerVersion.Invoke(conn, new object[0]);
SetServerVersionInternal(versionString);
}
else
{
versionMajor = 5.0m;
versionMinor = 0;
}
}
void SetServerVersionInternal(string versionString)
{
string[] versionParts = versionString.Split('.');
decimal versionMajorLocal;
if (versionParts.Length >= 3 && decimal.TryParse(string.Concat(versionParts[0], ".", versionParts[1]), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out versionMajorLocal))
{
versionMajor = versionMajorLocal;
string versionMinorString = versionParts[2];
int p = versionMinorString.IndexOf('-');
if (p != -1)
{
versionMinorString = versionMinorString.Substring(0, p);
}
Int32.TryParse(versionMinorString, NumberStyles.Integer, CultureInfo.InvariantCulture, out versionMinor);
}
}
bool SupportVersion(decimal major, int minor)
{
if (!versionMajor.HasValue)
return true;
if (versionMajor.Value > major)
return true;
if (versionMajor.Value == major && versionMinor >= minor)
return true;
return false;
}
public new static void Register()
{
RegisterDataStoreProvider(XpoProviderTypeString, CreateProviderFromString);
RegisterDataStoreProvider("MySqlConnector.MySqlConnection", CreateProviderFromConnection);
RegisterFactory(new MySqlConnectorConnectionProviderFactory());
}
public new static IDataStore CreateProviderFromString(string connectionString, AutoCreateOption autoCreateOption, out IDisposable[] objectsToDisposeOnDisconnect)
{
IDbConnection connection = CreateConnection(connectionString);
objectsToDisposeOnDisconnect = new IDisposable[] { connection };
return CreateProviderFromConnection(connection, autoCreateOption);
}
public new static IDataStore CreateProviderFromConnection(IDbConnection connection, AutoCreateOption autoCreateOption)
{
return new MySqlConnectorConnectionProvider(connection, autoCreateOption);
}
public MySqlConnectorConnectionProvider(IDbConnection connection, AutoCreateOption autoCreateOption)
: base(connection, autoCreateOption)
{
ReadDbVersion(connection);
}
public new static IDbConnection CreateConnection(string connectionString)
{
return ReflectConnectionHelper.GetConnection("MySqlConnector", "MySqlConnector.MySqlConnection", connectionString);
}
ExecMethodDelegate commandBuilderDeriveParametersHandler;
protected override void CommandBuilderDeriveParameters(IDbCommand command)
{
if (commandBuilderDeriveParametersHandler == null)
{
commandBuilderDeriveParametersHandler = ReflectConnectionHelper.GetCommandBuilderDeriveParametersDelegate("MySqlConnector", "MySqlConnector.MySqlCommandBuilder");
}
commandBuilderDeriveParametersHandler(command);
}
}
public class MySqlConnectorConnectionProviderFactory : MySqlProviderFactory
{
public override string ProviderKey => MySqlConnectorConnectionProvider.XpoProviderTypeString;
}
interface IDbTypeMapperMySql
{
bool IsByteArraySqlDbType(IDataParameter parameter);
bool IsBoolSqlDbType(IDataParameter parameter);
}
class DbTypeMapperMySql<TSqlDbTypeEnum, TSqlParameter> : DbTypeMapper<TSqlDbTypeEnum, TSqlParameter>, IDbTypeMapperMySql
where TSqlDbTypeEnum : struct
where TSqlParameter : IDbDataParameter
{
bool isSupport80;
static readonly TSqlDbTypeEnum mySqlTypeLongText;
static readonly TSqlDbTypeEnum mySqlTypeMediumText;
static readonly TSqlDbTypeEnum mySqlTypeText;
static readonly TSqlDbTypeEnum mySqlTypeLongBlob;
static readonly TSqlDbTypeEnum mySqlTypeMediumBlob;
static readonly TSqlDbTypeEnum mySqlTypeTinyBlob;
static readonly TSqlDbTypeEnum mySqlTypeBlob;
static readonly TSqlDbTypeEnum mySqlTypeBit;
static DbTypeMapperMySql()
{
mySqlTypeLongText = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "LongText");
mySqlTypeMediumText = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "MediumText");
mySqlTypeText = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "Text");
mySqlTypeLongBlob = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "LongBlob");
mySqlTypeMediumBlob = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "MediumBlob");
mySqlTypeTinyBlob = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "TinyBlob");
mySqlTypeBlob = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "Blob");
mySqlTypeBit = (TSqlDbTypeEnum)Enum.Parse(typeof(TSqlDbTypeEnum), "Bit");
}
public DbTypeMapperMySql(bool isSupport80)
{
this.isSupport80 = isSupport80;
}
protected override string ParameterDbTypePropertyName { get { return "MySqlDbType"; } }
protected override string GetParameterTypeNameForBoolean(out int? size, out byte? precision, out byte? scale)
{
size = 1;
precision = scale = null;
return "Bit";
}
protected override string GetParameterTypeNameForByte(out byte? precision, out byte? scale)
{
precision = scale = null;
return "UByte";
}
protected override string GetParameterTypeNameForByteArray(out int? size)
{
size = null;
return "LongBlob";
}
protected override string GetParameterTypeNameForChar(out int? size)
{
size = 1;
return "String";
}
protected override string GetParameterTypeNameForDateTime()
{
return "DateTime";
}
protected override string GetParameterTypeNameForDecimal(out byte? precision, out byte? scale)
{
precision = 28;
scale = 8;
return "Decimal";
}
protected override string GetParameterTypeNameForDouble(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Double";
}
protected override string GetParameterTypeNameForGuid(out int? size)
{
size = 38;
return "String";
}
protected override string GetParameterTypeNameForInt16(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Int16";
}
protected override string GetParameterTypeNameForInt32(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Int32";
}
protected override string GetParameterTypeNameForInt64(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Int64";
}
protected override string GetParameterTypeNameForSByte(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Byte";
}
protected override string GetParameterTypeNameForSingle(out byte? precision, out byte? scale)
{
precision = scale = null;
return "Float";
}
protected override string GetParameterTypeNameForString(out int? size)
{
size = null;
return "VarChar";
}
protected override string GetParameterTypeNameForTimeSpan()
{
return "Double";
}
protected override string GetParameterTypeNameForUInt16(out byte? precision, out byte? scale)
{
precision = scale = null;
return "UInt16";
}
protected override string GetParameterTypeNameForUInt32(out byte? precision, out byte? scale)
{
precision = scale = null;
return "UInt32";
}
protected override string GetParameterTypeNameForUInt64(out byte? precision, out byte? scale)
{
precision = scale = null;
return "UInt64";
}
protected override string ConvertSqlTypeToParameterType(string sqlType)
{
switch (sqlType.ToUpperInvariant())
{
case "TINYINT":
return "Byte";
case "TINYINT UNSIGNED":
return "UByte";
case "SMALLINT":
return "Int16";
case "SMALLINT UNSIGNED":
return "UInt16";
case "MEDIUMINT":
return "Int24";
case "MEDIUMINT UNSIGNED":
return "UInt24";
case "INT":
case "INTEGER":
return "Int32";
case "INT UNSIGNED":
case "INTEGER UNSIGNED":
return "UInt32";
case "BIGINT":
return "Int64";
case "BIGINT UNSIGNED":
return "UInt64";
case "FLOAT":
return "Float";
case "DOUBLE":
case "REAL":
return "Double";
case "DECIMAL":
case "NUMERIC":
return "Decimal";
case "BIT":
return "Bit";
case "YEAR":
return "Year";
case "DATE":
return "Date";
case "TIME":
return "Time";
case "DATETIME":
return "DateTime";
case "TIMESTAMP":
return "Timestamp";
case "CHAR":
case "NCHAR":
return "String";
case "BINARY":
return "Binary";
case "VARCHAR":
case "NVARCHAR":
return "VarChar";
case "VARBINARY":
return "VarBinary";
case "TINYBLOB":
return "TinyBlob";
case "TINYTEXT":
return "TinyText";
case "BLOB":
return "Blob";
case "TEXT":
return "Text";
case "MEDIUMBLOB":
return "MediumBlob";
case "MEDIUMTEXT":
return "MediumText";
case "LONGBLOB":
return "LongBlob";
case "LONGTEXT":
return "LongText";
case "ENUM":
return "Enum";
case "SET":
return "Set";
default:
return null;
}
}
public override void SetParameterTypeAndSize(IDbDataParameter parameter, DBColumnType dbColumnType, int size)
{
if (dbColumnType == DBColumnType.String)
{
if (size <= 0 || size > 16777215)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeLongText);
return;
}
else if (size > 65535)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeMediumText);
return;
}
else if (size > 255)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeText);
return;
}
}
else if (dbColumnType == DBColumnType.ByteArray)
{
if (size <= 0 || size > 16777215)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeLongBlob);
}
else if (size > 65535)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeMediumBlob);
}
else if (size > 127)
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeBlob);
}
else
{
SetSqlDbTypeHandler((TSqlParameter)parameter, mySqlTypeTinyBlob);
}
return;
}
else if (isSupport80 && dbColumnType == DBColumnType.DateTime)
{
size = 6;
}
base.SetParameterTypeAndSize(parameter, dbColumnType, size);
}
public bool IsByteArraySqlDbType(IDataParameter parameter)
{
TSqlDbTypeEnum type = GetSqlDbTypeHandler((TSqlParameter)parameter);
return Equals(type, mySqlTypeBlob) || Equals(type, mySqlTypeLongBlob) || Equals(type, mySqlTypeMediumBlob) || Equals(type, mySqlTypeTinyBlob);
}
public bool IsBoolSqlDbType(IDataParameter parameter)
{
TSqlDbTypeEnum type = GetSqlDbTypeHandler((TSqlParameter)parameter);
return Equals(type, mySqlTypeBit);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment