-
Notifications
You must be signed in to change notification settings - Fork 934
/
Copy pathIDriver.cs
167 lines (151 loc) · 7.29 KB
/
IDriver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
namespace NHibernate.Driver
{
/// <summary>
/// A strategy for describing how NHibernate should interact with the different .NET Data
/// Providers.
/// </summary>
/// <remarks>
/// <para>
/// The <c>IDriver</c> interface is not intended to be exposed to the application.
/// Instead it is used internally by NHibernate to obtain connection objects, command objects, and
/// to generate and prepare <see cref="DbCommand">DbCommands</see>. Implementors should provide a
/// public default constructor.
/// </para>
/// <para>
/// This is the interface to implement, or you can inherit from <see cref="DriverBase"/>
/// if you have an ADO.NET data provider that NHibernate does not have built in support for.
/// To use the driver, NHibernate property <c>connection.driver_class</c> should be
/// set to the assembly-qualified name of the driver class.
/// </para>
/// <code>
/// key="connection.driver_class"
/// value="FullyQualifiedClassName, AssemblyName"
/// </code>
/// </remarks>
public interface IDriver
{
/// <summary>
/// Configure the driver using <paramref name="settings"/>.
/// </summary>
void Configure(IDictionary<string, string> settings);
/// <summary>
/// Creates an uninitialized DbConnection object for the specific Driver
/// </summary>
DbConnection CreateConnection();
/// <summary>
/// Does this Driver support having more than 1 open DbDataReader with
/// the same DbConnection.
/// </summary>
/// <remarks>
/// <para>
/// A value of <see langword="false" /> indicates that an exception would be thrown if NHibernate
/// attempted to have 2 DbDataReaders open using the same DbConnection. NHibernate
/// (since this version is a close to straight port of Hibernate) relies on the
/// ability to recursively open 2 DbDataReaders. If the Driver does not support it
/// then NHibernate will read the values from the DbDataReader into an <see cref="NDataReader"/>.
/// </para>
/// <para>
/// A value of <see langword="true" /> will result in greater performance because an DbDataReader can be used
/// instead of the <see cref="NDataReader"/>. So if the Driver supports it then make sure
/// it is set to <see langword="true" />.
/// </para>
/// </remarks>
bool SupportsMultipleOpenReaders { get; }
/// <summary>
/// Generates an DbCommand from the SqlString according to the requirements of the DataProvider.
/// </summary>
/// <param name="type">The <see cref="CommandType"/> of the command to generate.</param>
/// <param name="sqlString">The SqlString that contains the SQL.</param>
/// <param name="parameterTypes">The types of the parameters to generate for the command.</param>
/// <returns>An DbCommand with the CommandText and Parameters fully set.</returns>
DbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes);
/// <summary>
/// Prepare the <paramref name="command" /> by calling <see cref="DbCommand.Prepare()" />.
/// May be a no-op if the driver does not support preparing commands, or for any other reason.
/// </summary>
/// <param name="command">The command.</param>
void PrepareCommand(DbCommand command);
/// <summary>
/// Generates an DbParameter for the DbCommand. It does not add the DbParameter to the DbCommand's
/// Parameter collection.
/// </summary>
/// <param name="command">The DbCommand to use to create the DbParameter.</param>
/// <param name="name">The name to set for DbParameter.Name</param>
/// <param name="sqlType">The SqlType to set for DbParameter.</param>
/// <returns>An DbParameter ready to be added to an DbCommand.</returns>
DbParameter GenerateParameter(DbCommand command, string name, SqlType sqlType);
/// <summary>
/// Remove 'extra' parameters from the DbCommand
/// </summary>
/// <remarks>
/// We sometimes create more parameters than necessary (see NH-2792 & also comments in SqlStringFormatter.ISqlStringVisitor.Parameter)
/// </remarks>
void RemoveUnusedCommandParameters(DbCommand cmd, SqlString sqlString);
/// <summary>
/// Expand the parameters of the cmd to have a single parameter for each parameter in the
/// sql string
/// </summary>
/// <remarks>
/// This is for databases that do not support named parameters. So, instead of a single parameter
/// for 'select ... from MyTable t where t.Col1 = @p0 and t.Col2 = @p0' we can issue
/// 'select ... from MyTable t where t.Col1 = ? and t.Col2 = ?'
/// </remarks>
void ExpandQueryParameters(DbCommand cmd, SqlString sqlString, SqlType[] parameterTypes);
IResultSetsCommand GetResultSetsCommand(ISessionImplementor session);
bool SupportsMultipleQueries { get; }
/// <summary>
/// Make any adjustments to each DbCommand object before it is added to the batcher.
/// </summary>
/// <param name="command">The command.</param>
/// <remarks>
/// This method should be executed before add each single command to the batcher.
/// If you have to adjust parameters values/type (when the command is full filled) this is a good place where do it.
/// </remarks>
void AdjustCommand(DbCommand command);
/// <summary>
/// Does this driver mandates <see cref="TimeSpan"/> values for time?
/// </summary>
bool RequiresTimeSpanForTime { get; }
/// <summary>
/// Does this driver support <see cref="System.Transactions.Transaction"/>?
/// </summary>
bool SupportsSystemTransactions { get; }
/// <summary>
/// Does this driver connections support enlisting with a <see langword="null" /> transaction?
/// </summary>
/// <remarks>Enlisting with <see langword="null" /> allows to leave a completed transaction and
/// starts accepting auto-committed statements.</remarks>
bool SupportsNullEnlistment { get; }
/// <summary>
/// Does this driver connections support explicitly enlisting with a transaction when auto-enlistment
/// is disabled?
/// </summary>
bool SupportsEnlistmentWhenAutoEnlistmentIsDisabled { get; }
/// <summary>
/// Does sometimes this driver finish distributed transaction after end of scope disposal?
/// </summary>
/// <remarks>
/// See https://github.com/npgsql/npgsql/issues/1571#issuecomment-308651461 discussion with a Microsoft
/// employee: MSDTC considers a transaction to be committed once it has collected all participant votes
/// for committing from prepare phase. It then immediately notifies all participants of the outcome.
/// This causes TransactionScope.Dispose to leave while the second phase of participants may still
/// be executing. This means the transaction from the db view point can still be pending and not yet
/// committed after the scope disposal. This is by design of MSDTC and we have to cope with that.
/// Some data provider may have a global locking mechanism causing any subsequent use to wait for the
/// end of the commit phase, but this is not a general case. Some other, as Npgsql < v3.2.5, may
/// crash due to this, because they re-use the connection in the second phase.
/// </remarks>
bool HasDelayedDistributedTransactionCompletion { get; }
/// <summary>
/// The minimal date supplied as a <see cref="DateTime" /> supported by this driver.
/// </summary>
DateTime MinDate { get; }
}
}