Author: gert
Date: 2007-10-19 09:36:40 -0400 (Fri, 19 Oct 2007)
New Revision: 87827

Modified:
   trunk/mcs/class/System.Data/System.Data.Odbc/ChangeLog
   trunk/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs
   trunk/mcs/class/System.Data/System.Data.Odbc/libodbc.cs
Log:
* OdbcTransaction.cs: Use OdbcIsolationLevel enum value instead of
magic numbers. For Snapshot isolation level, the attribute
SQL_COPT_SS_TXN_ISOLATION must be used instead. When isolation level
is Unspecified, then do not modify the isolation level at all and
lazy initlization the IsolationLevel property. Modified exceptions
for invalid / not supported isolation levels to match MS.
* libodbc.cs: Added attribute for changing SQL Server specific
connection option. Added enum for ODBC isolation level options.
Added SQLGetConnectAttr method.


Modified: trunk/mcs/class/System.Data/System.Data.Odbc/ChangeLog
===================================================================
--- trunk/mcs/class/System.Data/System.Data.Odbc/ChangeLog      2007-10-19 
13:35:58 UTC (rev 87826)
+++ trunk/mcs/class/System.Data/System.Data.Odbc/ChangeLog      2007-10-19 
13:36:40 UTC (rev 87827)
@@ -1,5 +1,17 @@
 2007-10-19  Gert Driesen  <[EMAIL PROTECTED]>
 
+       * OdbcTransaction.cs: Use OdbcIsolationLevel enum value instead of
+       magic numbers. For Snapshot isolation level, the attribute
+       SQL_COPT_SS_TXN_ISOLATION must be used instead. When isolation level
+       is Unspecified, then do not modify the isolation level at all and
+       lazy initlization the IsolationLevel property. Modified exceptions
+       for invalid / not supported isolation levels to match MS.
+       * libodbc.cs: Added attribute for changing SQL Server specific
+       connection option. Added enum for ODBC isolation level options.
+       Added SQLGetConnectAttr method.
+
+2007-10-19  Gert Driesen  <[EMAIL PROTECTED]>
+
        * libodbc.cs: Spaces to tabs. Code formatting.
        * OdbcConnection.cs: Spaces to tabs. Code formatting.
        * OdbcTransaction.cs: Code formatting.

Modified: trunk/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs
===================================================================
--- trunk/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs     
2007-10-19 13:35:58 UTC (rev 87826)
+++ trunk/mcs/class/System.Data/System.Data.Odbc/OdbcTransaction.cs     
2007-10-19 13:36:40 UTC (rev 87827)
@@ -29,6 +29,7 @@
 //
 using System;
 using System.Data;
+using System.Globalization;
 
 #if NET_2_0
 using System.Data.Common;
@@ -51,34 +52,76 @@
                        // Set Auto-commit (102) to false
                        SetAutoCommit (conn, false);
                        // Handle isolation level
-                       int lev = 0;
+                       OdbcIsolationLevel lev = 
OdbcIsolationLevel.ReadCommitted;
+                       OdbcConnectionAttribute attr = 
OdbcConnectionAttribute.TransactionIsolation;
                        switch (isolationlevel) {
                        case IsolationLevel.ReadUncommitted:
-                               lev = 1;
+                               lev = OdbcIsolationLevel.ReadUncommitted;
                                break;
                        case IsolationLevel.ReadCommitted:
-                               lev = 2;
+                               lev = OdbcIsolationLevel.ReadCommitted;
                                break;
                        case IsolationLevel.RepeatableRead:
-                               lev = 3;
+                               lev = OdbcIsolationLevel.RepeatableRead;
                                break;
                        case IsolationLevel.Serializable:
-                               lev = 4;
+                               lev = OdbcIsolationLevel.Serializable;
                                break;
+#if NET_2_0
+                       case IsolationLevel.Snapshot:
+                               // badly broken on MS:
+                               // 
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=305736
+                               lev = OdbcIsolationLevel.Snapshot;
+
+                               // SQL_ATTR_TXN_ISOLATION can be used to set 
all other isolation
+                               // levels except for SQL_TXN_SS_SNAPSHOT. If 
you want to use snapshot
+                               // isolation, you must set SQL_TXN_SS_SNAPSHOT 
through
+                               // SQL_COPT_SS_TXN_ISOLATION. However, you can 
retrieve the
+                               // isolation level by using either 
SQL_ATTR_TXN_ISOLATION or
+                               // SQL_COPT_SS_TXN_ISOLATION.
+                               // Source:
+                               // 
http://msdn2.microsoft.com/en-us/library/ms131709.aspx
+                               attr = 
OdbcConnectionAttribute.CoptTransactionIsolation;
+                               break;
+#endif
                        case IsolationLevel.Unspecified:
-                               lev = 0;
+                               // when isolationlevel is not specified, then 
use
+                               // default isolation level of the driver and
+                               // lazy initialize it in the IsolationLevel 
property
                                break;
+#if NET_2_0
+                       case IsolationLevel.Chaos:
+                               throw new ArgumentOutOfRangeException 
("IsolationLevel",
+                                       string.Format 
(CultureInfo.CurrentCulture,
+                                               "The IsolationLevel enumeration 
" +
+                                               "value, {0}, is not supported 
by " +
+                                               "the .Net Framework Odbc Data " 
+
+                                               "Provider.", (int) 
isolationlevel));
+#endif
                        default:
-                               throw new NotSupportedException();
+#if NET_2_0
+                               throw new ArgumentOutOfRangeException 
("IsolationLevel",
+                                       string.Format 
(CultureInfo.CurrentCulture,
+                                               "The IsolationLevel enumeration 
value, {0}, is invalid.",
+                                               (int) isolationlevel));
+#else
+                               throw new ArgumentException (string.Format (
+                                       CultureInfo.InvariantCulture,
+                                       "Not supported isolationlevel - {0}",
+                                       isolationlevel));
+#endif
                        }
-                       // mbd: Getting the return code of the second call to 
SQLSetConnectAttr is missing from original code!
-                       OdbcReturn ret = libodbc.SQLSetConnectAttr (conn.hDbc,
-                               OdbcConnectionAttribute.TransactionIsolation,
-                               (IntPtr) lev, 0);
-                       if (ret != OdbcReturn.Success && ret != 
OdbcReturn.SuccessWithInfo)
-                               throw new OdbcException (new OdbcError 
("SQLSetConnectAttr", OdbcHandleType.Dbc, conn.hDbc));
+
+                       // only change isolation level if it was explictly set
+                       if (isolationlevel != IsolationLevel.Unspecified) {
+                               // mbd: Getting the return code of the second 
call to SQLSetConnectAttr is missing from original code!
+                               OdbcReturn ret = libodbc.SQLSetConnectAttr 
(conn.hDbc,
+                                       attr, (IntPtr) lev, 0);
+                               if (ret != OdbcReturn.Success && ret != 
OdbcReturn.SuccessWithInfo)
+                                       throw new OdbcException (new OdbcError 
("SQLSetConnectAttr", OdbcHandleType.Dbc, conn.hDbc));
+                       }
                        this.isolationlevel = isolationlevel;
-                       connection=conn;
+                       connection = conn;
                }
 
                // Set Auto-commit (102) connection attribute
@@ -92,6 +135,51 @@
                                throw new OdbcException (new OdbcError 
("SQLSetConnectAttr", OdbcHandleType.Dbc, conn.hDbc));
                }
 
+               private static IsolationLevel GetIsolationLevel (OdbcConnection 
conn)
+               {
+                       int lev;
+                       int length;
+                       OdbcReturn ret = libodbc.SQLGetConnectAttr (conn.hDbc,
+                               OdbcConnectionAttribute.TransactionIsolation,
+                               out lev, 0, out length);
+                       if (ret != OdbcReturn.Success && ret != 
OdbcReturn.SuccessWithInfo)
+                               throw new OdbcException (new OdbcError 
("SQLGetConnectAttr",
+                                       OdbcHandleType.Dbc, conn.hDbc));
+                       return MapOdbcIsolationLevel ((OdbcIsolationLevel) lev);
+               }
+
+               private static IsolationLevel MapOdbcIsolationLevel 
(OdbcIsolationLevel odbcLevel)
+               {
+                       IsolationLevel isoLevel = IsolationLevel.Unspecified;
+
+                       switch (odbcLevel) {
+                       case OdbcIsolationLevel.ReadUncommitted:
+                               isoLevel = IsolationLevel.ReadUncommitted;
+                               break;
+                       case OdbcIsolationLevel.ReadCommitted:
+                               isoLevel = IsolationLevel.ReadCommitted;
+                               break;
+                       case OdbcIsolationLevel.RepeatableRead:
+                               isoLevel = IsolationLevel.RepeatableRead;
+                               break;
+                       case OdbcIsolationLevel.Serializable:
+                               isoLevel = IsolationLevel.Serializable;
+                               break;
+#if NET_2_0
+                       case OdbcIsolationLevel.Snapshot:
+                               isoLevel = IsolationLevel.Snapshot;
+                               break;
+#else
+                       default:
+                               throw new NotSupportedException (string.Format (
+                                       CultureInfo.InvariantCulture,
+                                       "Isolation level {0} is not supported.",
+                                       odbcLevel));
+#endif
+                       }
+                       return isoLevel;
+               }
+
                #region Implementation of IDisposable
 
 #if NET_2_0
@@ -169,6 +257,8 @@
 #endif
                IsolationLevel IsolationLevel {
                        get {
+                               if (isolationlevel == 
IsolationLevel.Unspecified)
+                                       isolationlevel = GetIsolationLevel 
(Connection);
                                return isolationlevel;
                        }
                }

Modified: trunk/mcs/class/System.Data/System.Data.Odbc/libodbc.cs
===================================================================
--- trunk/mcs/class/System.Data/System.Data.Odbc/libodbc.cs     2007-10-19 
13:35:58 UTC (rev 87826)
+++ trunk/mcs/class/System.Data/System.Data.Odbc/libodbc.cs     2007-10-19 
13:36:40 UTC (rev 87827)
@@ -65,7 +65,10 @@
        {
                AutoCommit = 102,
                TransactionIsolation = 108,
-               CurrentCatalog = 109
+               CurrentCatalog = 109,
+#if NET_2_0
+               CoptTransactionIsolation = 1227         /* 
SQL_COPT_SS_TXN_ISOLATION */
+#endif
        }
 
        internal enum OdbcInfo : ushort
@@ -86,6 +89,15 @@
                ReturnValue = 5
        }
 
+       internal enum OdbcIsolationLevel
+       {
+               ReadUncommitted = 1,
+               ReadCommitted = 2,
+               RepeatableRead = 4,
+               Serializable = 8,
+               Snapshot = 32           /* SQL_TXN_SS_SNAPSHOT */
+       }
+
        internal enum OdbcLengthIndicator : short
        {
                NoTotal = -4,
@@ -339,6 +351,14 @@
                internal static extern OdbcReturn SQLExecute (
                        IntPtr StatementHandle);
 
+               [DllImport ("odbc32.dll")]
+               internal static extern OdbcReturn SQLGetConnectAttr (
+                       IntPtr ConnectionHandle,
+                       OdbcConnectionAttribute Attribute,
+                       out int value,
+                       int BufferLength,
+                       out int StringLength);
+
                [DllImport("odbc32.dll")]
                internal static extern OdbcReturn SQLSetConnectAttr (
                        IntPtr ConnectionHandle,

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to