Created
December 29, 2021 05:35
-
-
Save pedoc/808a11b8bc06284f5ea2ec75ec090955 to your computer and use it in GitHub Desktop.
MySqlConnectorConnectionProvider for DevExpress.Xpo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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