using Devart.Common;
using Devart.Data.Universal;
using FirebirdSql.Data.FirebirdClient;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1 {
// =========================================================================
// An example of IUniProvider interface implementation for .NET Data Provider for Firebird 3
// MyFirebirdProvider - is a wrapper for Firebird ADO.NET Data Provider
public class MyFirebirdProvider : IUniProvider {
private string assemblyVersion = "Not available";
public MyFirebirdProvider() {
}
public string ProviderName {
get {
return "MyFirebirdClient";
}
}
public string ProviderPrefix {
get {
return "FB";
}
}
public char ParameterPlaceholder {
get {
return '@';
}
}
public bool AllowUnnamedParameters {
get {
return false;
}
}
public bool PortSupported {
get {
return true;
}
}
public bool DatabaseSupported {
get {
return true;
}
}
public string WebAssemblyName {
get {
return "System.Web";
}
}
public string ProviderAssemblyVersion {
get {
return assemblyVersion;
}
}
public string ProviderDescription {
get {
return "Firebird ADO.NET Data Provider";
}
}
public DbProviderFactory GetProviderFactory() {
return FirebirdClientFactory.Instance;
}
public System.Data.Common.RowUpdatingEventArgs CreateRowUpdatingEventArgs(System.Data.Common.RowUpdatingEventArgs e) {
return new FbRowUpdatingEventArgs(e.Row, e.Command, e.StatementType, e.TableMapping);
}
public IDbConnection CreateConnection() {
IDbConnection connection = new FbConnection();
assemblyVersion = connection.GetType().Assembly.GetName().Version.ToString();
return connection;
}
public IDbCommand CreateCommand() {
return new FbCommand();
}
public IDbDataAdapter CreateDataAdapter() {
return new FbDataAdapter();
}
public IUniCommandBuilder CreateCommandBuilder() {
return new FbCommandBuilderWrapper();
}
public void DeriveParameters(IDbCommand command) {
FbCommand fbCommand = command as FbCommand;
FbCommandBuilder.DeriveParameters(fbCommand);
}
// sets the native type for FbParameter, corresponding to UniDbType
public void SetNativeDbType(IDbDataParameter nativeParameter, UniDbType uniDbType) {
FbParameter fbParameter = nativeParameter as FbParameter;
if (fbParameter != null)
fbParameter.FbDbType = FirebirdTypeMapping.GetSpecificType(uniDbType);
}
// get uni db type corresponding native db type
public UniDbType GetUniDbType(IDbDataParameter nativeParameter) {
FbParameter fbParameter = nativeParameter as FbParameter;
if (fbParameter != null)
return FirebirdTypeMapping.GetUniDbType(fbParameter.FbDbType);
else
throw new ArgumentException("nativeParameter");
}
// convert native provider value to uni value
public object ConvertProviderValue(UniConnection connection, object value, IDbDataParameter nativeParameter) {
return value;
}
// convert uni value to native provider value
public object ConvertUniValue(object value) {
return value;
}
// is used by UniDataReader for getting provider-specific data
public object GetProviderSpecificValue(IDataReader nativeReader, int i) {
FbDataReader fbReader = nativeReader as FbDataReader;
if (fbReader != null)
return fbReader.GetValue(i);
else
throw new ArgumentException("nativeReader");
}
// allows modifying sql taking into consideration provider peculiarities
// allows using Uni macros
public string FormatSql(string sql, IDbConnection innerConnection, UniMacroCollection userMacros) {
return sql;
}
// some interface methods, used mostly by Uni components,
// can be implemented explicitly,
// this will allow keeping clear the provider's public interface visible to the user
#region explicity implement interface
object IUniProvider.CreateConnectionStringBuilder() {
return new FbConnectionStringBuilder();
}
// it is necessary to switch pooling off for the native provider, to avoid duplication with
// Uni pooling
void IUniProvider.DisablePooling(IDbConnection nativeConnection) {
FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
csb.ConnectionString = nativeConnection.ConnectionString;
try {
csb.Pooling = false;
nativeConnection.ConnectionString = csb.ToString();
}
catch {
}
}
// required for design-time
private static UniPropertyDescriptorCollection connectionPropertyDescriptors = null;
UniPropertyDescriptorCollection IUniProvider.GetConnectionStringPropertyDescriptors(ref string refreshKeyword, object refreshKeywordValue) {
if (connectionPropertyDescriptors == null) {
UniPropertyDescriptorCollection descs = new UniPropertyDescriptorCollection();
descs.Add(new UniPropertyDescriptor("Charset", "Misc", "", typeof(System.String), null, null,
"Devart.Data.Universal.CharsetTypeConverter, Devart.Data.Universal.Firebird"));
descs.Add(new UniPropertyDescriptor("Connection Lifetime", "Pooling", "Connection lifetime",
typeof(System.Int32), 0));
descs.Add(new UniPropertyDescriptor("Connection Timeout", "Advanced",
"The time (in seconds) to wait for a connection to open, 'Connect Timeout=X' in the ConnectionString.", typeof(System.Int32), 15));
descs.Add(new UniPropertyDescriptor("Database", "Source",
"Current data source catalog value, 'Database=X' in the connection string", typeof(System.String), String.Empty));
descs.Add(new UniPropertyDescriptor("Data Source", "Source",
"Current data source, 'Data Source=X' in the connection string", typeof(System.String), String.Empty));
descs.Add(new UniPropertyDescriptor("Dialect", "Advanced",
"SQL dialect: an indicator that instructs a Firebird/InterBase server how to interpret the features whose meanings have changed between Firebird/InterBase versions",
typeof(System.Int32), null));
descs.Add(new UniPropertyDescriptor("Fetch Size", "Advanced", "", typeof(System.Int32), null));
descs.Add(new UniPropertyDescriptor("IsolationLevel", "Misc", "", typeof(System.Data.IsolationLevel), null));
descs.Add(new UniPropertyDescriptor("Max Pool Size", "Pooling",
"The maximum number of connections allowed in the pool", typeof(System.Int32), 100));
descs.Add(new UniPropertyDescriptor("Min Pool Size", "Pooling",
"The minimum number of connections allowed in the pool", typeof(System.Int32), 0));
descs.Add(new UniPropertyDescriptor("Packet Size", "Advanced",
"Size in bytes of the network packets used to communicate with an instance of Firebird/Interbase server.", typeof(System.Int32), null));
descs.Add(new UniPropertyDescriptor("User ID", "Security", "The name of user to connect.", typeof(System.String), String.Empty));
descs.Add(new UniPropertyDescriptor("Password", "Security", "The user password.", typeof(System.String), String.Empty));
descs.Add(new UniPropertyDescriptor("Persist Security Info", "Security",
"When false, security-sensitive information, like password, is not returned as a part of the connection if the connection is open or has ever been open.",
typeof(System.Boolean), false));
descs.Add(new UniPropertyDescriptor("Pooling", "Pooling",
"When true, the connection object is drawn from the approptiate pool, or, if necessary, is created and added to the appropriate pool",
typeof(System.Boolean), true));
descs.Add(new UniPropertyDescriptor("Port", "Source",
"The port of Firebird/Interbase database to which to connect, 'Port=X' in the ConnectionString.", typeof(System.Int32), 3050));
descs.Add(new UniPropertyDescriptor("ReturnRecordsAffected", "Misc", "", typeof(System.Boolean), null));
descs.Add(new UniPropertyDescriptor("Role", "Security",
"Specifies the role that the user adopts on connection to the database.", typeof(System.String), String.Empty));
descs.Add(new UniPropertyDescriptor("ServerType", "Misc", "", typeof(FirebirdSql.Data.FirebirdClient.FbServerType),
FirebirdSql.Data.FirebirdClient.FbServerType.Default));
connectionPropertyDescriptors = descs;
}
UniPropertyDescriptorCollection descriptors = new UniPropertyDescriptorCollection();
foreach (UniPropertyDescriptor propertyDescriptor in connectionPropertyDescriptors) {
descriptors.Add(propertyDescriptor);
}
return descriptors;
}
// synonyms for connection string parameters
System.Collections.IDictionary IUniProvider.GetConnectionStringSynonyms() {
Hashtable Synonyms = new Hashtable(StringComparer.InvariantCultureIgnoreCase);
Synonyms.Add("User", "User Id");
Synonyms.Add("Uid", "User Id");
Synonyms.Add("pwd", "Password");
Synonyms.Add("Host", "Data Source");
Synonyms.Add("Server", "Data Source");
Synonyms.Add("Connect timeout", "Connection Timeout");
return Synonyms;
}
#endregion
}
#region FbCommandBuilderWrapper
// IUniCommandBuilder wrapper is required, because UniDbCommandBuilder uses
// specific properties existing only in our providers, and absent in other ones.
internal class FbCommandBuilderWrapper : IUniCommandBuilder {
private FbCommandBuilder commandBuilder = new FbCommandBuilder();
private CatalogLocation catalogLocation = CatalogLocation.Start;
void IDisposable.Dispose() {
commandBuilder.Dispose();
}
public IDbCommand GetInsertCommand() {
return commandBuilder.GetInsertCommand();
}
public IDbCommand GetUpdateCommand() {
return commandBuilder.GetUpdateCommand();
}
public IDbCommand GetDeleteCommand() {
return commandBuilder.GetDeleteCommand();
}
public void RefreshSchema() {
commandBuilder.RefreshSchema();
}
public IDbDataAdapter DataAdapter {
get {
return commandBuilder.DataAdapter;
}
set {
commandBuilder.DataAdapter = (FbDataAdapter)value;
}
}
public string QuotePrefix {
get {
return commandBuilder.QuotePrefix;
}
set {
commandBuilder.QuotePrefix = value;
}
}
public string QuoteSuffix {
get {
return commandBuilder.QuoteSuffix;
}
set {
commandBuilder.QuoteSuffix = value;
}
}
// Devart DbCommandBuilder specific properties
public bool Quoted {
get {
return true;
}
set {
}
}
public ConflictOption ConflictOption {
get {
return commandBuilder.ConflictOption;
}
set {
commandBuilder.ConflictOption = value;
}
}
protected string GetParameterName(int parameterOrdinal) {
return "@p" + parameterOrdinal.ToString();
}
protected string GetParameterName(string parameterName) {
if (parameterName.Length > 0 && parameterName[0] == '@') {
return parameterName;
}
else {
return "@" + parameterName;
}
}
protected string GetParameterPlaceholder(int parameterOrdinal) {
return "@p" + parameterOrdinal.ToString();
}
public string UpdatingTable {
get {
return String.Empty;
}
set {
}
}
public string UpdatingFields {
get {
return String.Empty;
}
set {
}
}
public string RefreshingFields {
get {
return String.Empty;
}
set {
}
}
public RefreshRowMode RefreshMode {
get {
return RefreshRowMode.None;
}
set {
}
}
public CatalogLocation CatalogLocation {
get {
return catalogLocation;
}
set {
catalogLocation = value;
}
}
public bool UseSchema {
get {
return true;
}
set {
}
}
public bool UseCatalog {
get {
return true;
}
set {
}
}
}
#endregion
#region FirebirdTypeMapping
// example of possible mapping implementation, used for correct conversion of
// Uni - NativeProvider parameters
// this class is used in methods SetNativeDbType and GetUniDbType
internal class FirebirdTypeMapping {
private static Hashtable uniType = null;
private static Hashtable specType = null;
static FirebirdTypeMapping() {
uniType = new Hashtable(50);
specType = new Hashtable(50);
AssignNative(UniDbType.Decimal, FbDbType.Numeric);
AssignNative(UniDbType.VarChar, FbDbType.VarChar);
AssignNative(UniDbType.Char, FbDbType.Char);
AssignNative(UniDbType.Binary, FbDbType.Binary);
AssignNative(UniDbType.Binary, FbDbType.Binary);
AssignNative(UniDbType.Boolean, FbDbType.Boolean);
AssignNative(UniDbType.Byte, FbDbType.SmallInt, false);
AssignNative(UniDbType.Currency, FbDbType.Decimal, false);
AssignNative(UniDbType.Date, FbDbType.Date, false);
AssignNative(UniDbType.DateTime, FbDbType.Date);
AssignNative(UniDbType.Decimal, FbDbType.Decimal);
AssignNative(UniDbType.Double, FbDbType.Double);
AssignNative(UniDbType.Guid, FbDbType.Guid);
AssignNative(UniDbType.SmallInt, FbDbType.SmallInt);
AssignNative(UniDbType.Int, FbDbType.Integer);
AssignNative(UniDbType.BigInt, FbDbType.BigInt);
AssignNative(UniDbType.TinyInt, FbDbType.SmallInt, false);
AssignNative(UniDbType.Single, FbDbType.Float);
AssignNative(UniDbType.NVarChar, FbDbType.VarChar, false);
AssignNative(UniDbType.NChar, FbDbType.Char, false);
AssignNative(UniDbType.Time, FbDbType.Time);
AssignNative(UniDbType.Xml, FbDbType.VarChar, false);
AssignNative(UniDbType.TimeStamp, FbDbType.TimeStamp);
AssignNative(UniDbType.IntervalDS, FbDbType.Time, false);
AssignNative(UniDbType.IntervalYM, FbDbType.Date, false);
AssignNative(UniDbType.DateTime2, FbDbType.TimeStamp, false);
AssignNative(UniDbType.Blob, FbDbType.Binary, false);
AssignNative(UniDbType.Clob, FbDbType.Text);
AssignNative(UniDbType.NClob, FbDbType.Text, false);
AssignNative(UniDbType.Array, FbDbType.Array);
AssignNative(UniDbType.Bit, FbDbType.SmallInt, false);
}
static void AssignNative(UniDbType uniDbType, FbDbType nativeType) {
AssignNative(uniDbType, nativeType, true);
}
static void AssignNative(UniDbType uniDbType, FbDbType nativeType, bool isDefault) {
uniType[(int)uniDbType] = nativeType;
if (isDefault) {
specType[nativeType] = (int)uniDbType;
}
}
public static UniDbType GetUniDbType(FbDbType nativeType) {
if (specType.ContainsKey((int)nativeType))
return (UniDbType)specType[(int)nativeType];
else
throw new ArgumentException(string.Format("{0} data type is not supported by dotConnect Universal", nativeType.ToString()));
}
public static FbDbType GetSpecificType(UniDbType uniDbType) {
if (uniType.ContainsKey((int)uniDbType))
return (FbDbType)uniType[(int)uniDbType];
else
throw new ArgumentException(string.Format("{0} data type id not supported by Firebird Data Provider", uniDbType.ToString()));
}
}
#endregion
}