1 //------------------------------------------------------------------------------
2 // <copyright file="OdbcConnectionFactory.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8 
9 namespace System.Data.Odbc
10 {
11     using System;
12     using System.Data.Common;
13     using System.Data.ProviderBase;
14     using System.Diagnostics;
15     using System.Collections.Specialized;
16     using System.Configuration;
17     using System.IO;
18     using System.Runtime.Versioning;
19 
20     sealed internal class OdbcConnectionFactory : DbConnectionFactory {
OdbcConnectionFactory()21         private OdbcConnectionFactory() : base() {}
22         // At this time, the ODBC Provider doesn't have any connection pool counters
23         // because we'd only confuse people with "non-pooled" connections that are
24         // actually being pooled by the native pooler.
25 
26         private const string _MetaData           = ":MetaDataXml";
27         private const string _defaultMetaDataXml = "defaultMetaDataXml";
28 
29         public static readonly OdbcConnectionFactory SingletonInstance = new OdbcConnectionFactory();
30 
31         override public DbProviderFactory ProviderFactory {
32             get {
33                 return OdbcFactory.Instance;
34             }
35         }
36 
CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)37         override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) {
38             DbConnectionInternal result = new OdbcConnectionOpen(owningObject as OdbcConnection, options as OdbcConnectionString);
39             return result;
40         }
41 
CreateConnectionOptions(string connectionString, DbConnectionOptions previous)42         override protected DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) {
43             Debug.Assert(!ADP.IsEmpty(connectionString), "empty connectionString");
44             OdbcConnectionString result = new OdbcConnectionString(connectionString, (null != previous));
45             return result;
46         }
47 
CreateConnectionPoolGroupOptions( DbConnectionOptions connectionOptions )48         override protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions( DbConnectionOptions connectionOptions ) {
49             // At this time, the ODBC provider only supports native pooling so we
50             // simply return NULL to indicate that.
51             return null;
52         }
53 
CreateConnectionPoolGroupProviderInfo(DbConnectionOptions connectionOptions)54         override internal DbConnectionPoolGroupProviderInfo CreateConnectionPoolGroupProviderInfo (DbConnectionOptions connectionOptions) {
55             return new OdbcConnectionPoolGroupProviderInfo();
56         }
57 
58         // SxS (VSDD 545786): metadata files are opened from <.NetRuntimeFolder>\CONFIG\<metadatafilename.xml>
59         // this operation is safe in SxS because the file is opened in read-only mode and each NDP runtime accesses its own copy of the metadata
60         // under the runtime folder.
61         [ResourceExposure(ResourceScope.None)]
62         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory)63         override protected DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory){
64 
65             Debug.Assert (internalConnection != null,"internalConnection may not be null.");
66             cacheMetaDataFactory = false;
67 
68             OdbcConnection odbcOuterConnection = ((OdbcConnectionOpen)internalConnection).OuterConnection;
69             Debug.Assert(odbcOuterConnection != null,"outer connection may not be null.");
70 
71             NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection("system.data.odbc");
72             Stream XMLStream =null;
73 
74             // get the DBMS Name
75             object driverName = null;
76             string stringValue = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DRIVER_NAME);
77             if (stringValue != null) {
78                 driverName = stringValue;
79             }
80 
81             if (settings != null){
82 
83                 string [] values = null;
84                 string metaDataXML = null;
85                 // first try to get the provider specific xml
86 
87                 // if driver name is not supported we can't build the settings key needed to
88                 // get the provider specific XML path
89                 if (driverName != null){
90                     metaDataXML =  ((string)driverName) + _MetaData;
91                     values = settings.GetValues(metaDataXML);
92                 }
93 
94                 // if we did not find provider specific xml see if there is new default xml
95                 if (values == null) {
96                     metaDataXML = _defaultMetaDataXml;
97                     values = settings.GetValues(metaDataXML);
98                 }
99 
100                 // If there is an XML file get it
101                 if (values != null) {
102                     XMLStream = ADP.GetXmlStreamFromValues(values,metaDataXML);
103                 }
104             }
105 
106             // use the embedded xml if the user did not over ride it
107             if (XMLStream == null){
108                 XMLStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("System.Data.Odbc.OdbcMetaData.xml");
109                 cacheMetaDataFactory = true;
110             }
111 
112             Debug.Assert (XMLStream != null,"XMLstream may not be null.");
113 
114             String versionString = odbcOuterConnection.GetInfoStringUnhandled(ODBC32.SQL_INFO.DBMS_VER);
115 
116             return new OdbcMetaDataFactory (XMLStream,
117                                             versionString,
118                                             versionString,
119                                             odbcOuterConnection);
120         }
121 
GetConnectionPoolGroup(DbConnection connection)122         override internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection) {
123             OdbcConnection c = (connection as OdbcConnection);
124             if (null != c) {
125                 return c.PoolGroup;
126             }
127             return null;
128         }
129 
GetInnerConnection(DbConnection connection)130         override internal DbConnectionInternal GetInnerConnection(DbConnection connection) {
131             OdbcConnection c = (connection as OdbcConnection);
132             if (null != c) {
133                 return c.InnerConnection;
134             }
135             return null;
136         }
137 
GetObjectId(DbConnection connection)138         override protected int GetObjectId(DbConnection connection) {
139             OdbcConnection c = (connection as OdbcConnection);
140             if (null != c) {
141                 return c.ObjectID;
142             }
143             return 0;
144         }
145 
PermissionDemand(DbConnection outerConnection)146         override internal void PermissionDemand(DbConnection outerConnection) {
147             OdbcConnection c = (outerConnection as OdbcConnection);
148             if (null != c) {
149                 c.PermissionDemand();
150             }
151         }
152 
SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup)153         override internal void SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup) {
154             OdbcConnection c = (outerConnection as OdbcConnection);
155             if (null != c) {
156                 c.PoolGroup = poolGroup;
157             }
158         }
159 
SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to)160         override internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to) {
161             OdbcConnection c = (owningObject as OdbcConnection);
162             if (null != c) {
163                 c.SetInnerConnectionEvent(to);
164             }
165         }
166 
SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from)167         override internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from) {
168             OdbcConnection c = (owningObject as OdbcConnection);
169             if (null != c) {
170                 return c.SetInnerConnectionFrom(to, from);
171             }
172             return false;
173         }
174 
SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to)175         override internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to) {
176             OdbcConnection c = (owningObject as OdbcConnection);
177             if (null != c) {
178                 c.SetInnerConnectionTo(to);
179             }
180         }
181 
182 
183 
184     }
185 }
186 
187