DbConnectionStringCommon.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. //------------------------------------------------------------------------------
  2. // <copyright file="DbConnectionStringBuilder.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. using System;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Data;
  13. using System.Data.Common;
  14. using System.Diagnostics;
  15. using System.Globalization;
  16. using System.Runtime.Serialization;
  17. using System.Security.Permissions;
  18. using System.Text;
  19. using System.Text.RegularExpressions;
  20. using System.Data.SqlClient;
  21. namespace System.Data.Common {
  22. /*
  23. internal sealed class NamedConnectionStringConverter : StringConverter {
  24. public NamedConnectionStringConverter() {
  25. }
  26. public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
  27. return true;
  28. }
  29. public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
  30. // Although theoretically this could be true, some people may want to just type in a name
  31. return false;
  32. }
  33. public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
  34. StandardValuesCollection standardValues = null;
  35. if (null != context) {
  36. DbConnectionStringBuilder instance = (context.Instance as DbConnectionStringBuilder);
  37. if (null != instance) {
  38. string myProviderName = instance.GetType().Namespace;
  39. List<string> myConnectionNames = new List<string>();
  40. foreach(System.Configuration.ConnectionStringSetting setting in System.Configuration.ConfigurationManager.ConnectionStrings) {
  41. if (myProviderName.EndsWith(setting.ProviderName)) {
  42. myConnectionNames.Add(setting.ConnectionName);
  43. }
  44. }
  45. standardValues = new StandardValuesCollection(myConnectionNames);
  46. }
  47. }
  48. return standardValues;
  49. }
  50. }
  51. */
  52. internal class DbConnectionStringBuilderDescriptor : PropertyDescriptor {
  53. private Type _componentType;
  54. private Type _propertyType;
  55. private bool _isReadOnly;
  56. private bool _refreshOnChange;
  57. internal DbConnectionStringBuilderDescriptor(string propertyName, Type componentType, Type propertyType, bool isReadOnly, Attribute[] attributes) : base(propertyName, attributes) {
  58. //Bid.Trace("<comm.DbConnectionStringBuilderDescriptor|INFO> propertyName='%ls', propertyType='%ls'\n", propertyName, propertyType.Name);
  59. _componentType = componentType;
  60. _propertyType = propertyType;
  61. _isReadOnly = isReadOnly;
  62. }
  63. internal bool RefreshOnChange {
  64. get {
  65. return _refreshOnChange;
  66. }
  67. set {
  68. _refreshOnChange = value;
  69. }
  70. }
  71. public override Type ComponentType {
  72. get {
  73. return _componentType;
  74. }
  75. }
  76. public override bool IsReadOnly {
  77. get {
  78. return _isReadOnly;
  79. }
  80. }
  81. public override Type PropertyType {
  82. get {
  83. return _propertyType;
  84. }
  85. }
  86. public override bool CanResetValue(object component) {
  87. DbConnectionStringBuilder builder = (component as DbConnectionStringBuilder);
  88. return ((null != builder) && builder.ShouldSerialize(DisplayName));
  89. }
  90. public override object GetValue(object component) {
  91. DbConnectionStringBuilder builder = (component as DbConnectionStringBuilder);
  92. if (null != builder) {
  93. object value;
  94. if (builder.TryGetValue(DisplayName, out value)) {
  95. return value;
  96. }
  97. }
  98. return null;
  99. }
  100. public override void ResetValue(object component) {
  101. DbConnectionStringBuilder builder = (component as DbConnectionStringBuilder);
  102. if (null != builder) {
  103. builder.Remove(DisplayName);
  104. if (RefreshOnChange) {
  105. builder.ClearPropertyDescriptors();
  106. }
  107. }
  108. }
  109. public override void SetValue(object component, object value) {
  110. DbConnectionStringBuilder builder = (component as DbConnectionStringBuilder);
  111. if (null != builder) {
  112. // via the editor, empty string does a defacto Reset
  113. if ((typeof(string) == PropertyType) && String.Empty.Equals(value)) {
  114. value = null;
  115. }
  116. builder[DisplayName] = value;
  117. if (RefreshOnChange) {
  118. builder.ClearPropertyDescriptors();
  119. }
  120. }
  121. }
  122. public override bool ShouldSerializeValue(object component) {
  123. DbConnectionStringBuilder builder = (component as DbConnectionStringBuilder);
  124. return ((null != builder) && builder.ShouldSerialize(DisplayName));
  125. }
  126. }
  127. [Serializable()]
  128. internal sealed class ReadOnlyCollection<T> : System.Collections.ICollection, ICollection<T> {
  129. private T[] _items;
  130. internal ReadOnlyCollection(T[] items) {
  131. _items = items;
  132. #if DEBUG
  133. for(int i = 0; i < items.Length; ++i) {
  134. Debug.Assert(null != items[i], "null item");
  135. }
  136. #endif
  137. }
  138. public void CopyTo(T[] array, int arrayIndex) {
  139. Array.Copy(_items, 0, array, arrayIndex, _items.Length);
  140. }
  141. void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
  142. Array.Copy(_items, 0, array, arrayIndex, _items.Length);
  143. }
  144. IEnumerator<T> IEnumerable<T>.GetEnumerator() {
  145. return new Enumerator<T>(_items);
  146. }
  147. public System.Collections.IEnumerator GetEnumerator() {
  148. return new Enumerator<T>(_items);
  149. }
  150. bool System.Collections.ICollection.IsSynchronized {
  151. get { return false; }
  152. }
  153. Object System.Collections.ICollection.SyncRoot {
  154. get { return _items; }
  155. }
  156. bool ICollection<T>.IsReadOnly {
  157. get { return true;}
  158. }
  159. void ICollection<T>.Add(T value) {
  160. throw new NotSupportedException();
  161. }
  162. void ICollection<T>.Clear() {
  163. throw new NotSupportedException();
  164. }
  165. bool ICollection<T>.Contains(T value) {
  166. return Array.IndexOf(_items, value) >= 0;
  167. }
  168. bool ICollection<T>.Remove(T value) {
  169. throw new NotSupportedException();
  170. }
  171. public int Count {
  172. get { return _items.Length; }
  173. }
  174. [Serializable()]
  175. internal struct Enumerator<K> : IEnumerator<K>, System.Collections.IEnumerator { // based on List<T>.Enumerator
  176. private K[] _items;
  177. private int _index;
  178. internal Enumerator(K[] items) {
  179. _items = items;
  180. _index = -1;
  181. }
  182. public void Dispose() {
  183. }
  184. public bool MoveNext() {
  185. return (++_index < _items.Length);
  186. }
  187. public K Current {
  188. get {
  189. return _items[_index];
  190. }
  191. }
  192. Object System.Collections.IEnumerator.Current {
  193. get {
  194. return _items[_index];
  195. }
  196. }
  197. void System.Collections.IEnumerator.Reset() {
  198. _index = -1;
  199. }
  200. }
  201. }
  202. internal static class DbConnectionStringBuilderUtil
  203. {
  204. internal static bool ConvertToBoolean(object value)
  205. {
  206. Debug.Assert(null != value, "ConvertToBoolean(null)");
  207. string svalue = (value as string);
  208. if (null != svalue)
  209. {
  210. if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes"))
  211. return true;
  212. else if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "false") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "no"))
  213. return false;
  214. else
  215. {
  216. string tmp = svalue.Trim(); // Remove leading & trailing white space.
  217. if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes"))
  218. return true;
  219. else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no"))
  220. return false;
  221. }
  222. return Boolean.Parse(svalue);
  223. }
  224. try
  225. {
  226. return ((IConvertible)value).ToBoolean(CultureInfo.InvariantCulture);
  227. }
  228. catch (InvalidCastException e)
  229. {
  230. throw ADP.ConvertFailed(value.GetType(), typeof(Boolean), e);
  231. }
  232. }
  233. internal static bool ConvertToIntegratedSecurity(object value)
  234. {
  235. Debug.Assert(null != value, "ConvertToIntegratedSecurity(null)");
  236. string svalue = (value as string);
  237. if (null != svalue)
  238. {
  239. if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes"))
  240. return true;
  241. else if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "false") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "no"))
  242. return false;
  243. else
  244. {
  245. string tmp = svalue.Trim(); // Remove leading & trailing white space.
  246. if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes"))
  247. return true;
  248. else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no"))
  249. return false;
  250. }
  251. return Boolean.Parse(svalue);
  252. }
  253. try
  254. {
  255. return ((IConvertible)value).ToBoolean(CultureInfo.InvariantCulture);
  256. }
  257. catch (InvalidCastException e)
  258. {
  259. throw ADP.ConvertFailed(value.GetType(), typeof(Boolean), e);
  260. }
  261. }
  262. internal static int ConvertToInt32(object value)
  263. {
  264. try
  265. {
  266. return ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture);
  267. }
  268. catch (InvalidCastException e)
  269. {
  270. throw ADP.ConvertFailed(value.GetType(), typeof(Int32), e);
  271. }
  272. }
  273. internal static string ConvertToString(object value)
  274. {
  275. try
  276. {
  277. return ((IConvertible)value).ToString(CultureInfo.InvariantCulture);
  278. }
  279. catch (InvalidCastException e)
  280. {
  281. throw ADP.ConvertFailed(value.GetType(), typeof(String), e);
  282. }
  283. }
  284. const string ApplicationIntentReadWriteString = "ReadWrite";
  285. const string ApplicationIntentReadOnlyString = "ReadOnly";
  286. internal static bool TryConvertToApplicationIntent(string value, out ApplicationIntent result)
  287. {
  288. Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed");
  289. Debug.Assert(null != value, "TryConvertToApplicationIntent(null,...)");
  290. if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadOnlyString))
  291. {
  292. result = ApplicationIntent.ReadOnly;
  293. return true;
  294. }
  295. else if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadWriteString))
  296. {
  297. result = ApplicationIntent.ReadWrite;
  298. return true;
  299. }
  300. else
  301. {
  302. result = DbConnectionStringDefaults.ApplicationIntent;
  303. return false;
  304. }
  305. }
  306. internal static bool IsValidApplicationIntentValue(ApplicationIntent value)
  307. {
  308. Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed");
  309. return value == ApplicationIntent.ReadOnly || value == ApplicationIntent.ReadWrite;
  310. }
  311. internal static string ApplicationIntentToString(ApplicationIntent value)
  312. {
  313. Debug.Assert(IsValidApplicationIntentValue(value));
  314. if (value == ApplicationIntent.ReadOnly)
  315. {
  316. return ApplicationIntentReadOnlyString;
  317. }
  318. else
  319. {
  320. return ApplicationIntentReadWriteString;
  321. }
  322. }
  323. /// <summary>
  324. /// This method attempts to convert the given value tp ApplicationIntent enum. The algorithm is:
  325. /// * if the value is from type string, it will be matched against ApplicationIntent enum names only, using ordinal, case-insensitive comparer
  326. /// * if the value is from type ApplicationIntent, it will be used as is
  327. /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum
  328. /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException
  329. ///
  330. /// in any case above, if the conerted value is out of valid range, the method raises ArgumentOutOfRangeException.
  331. /// </summary>
  332. /// <returns>applicaiton intent value in the valid range</returns>
  333. internal static ApplicationIntent ConvertToApplicationIntent(string keyword, object value)
  334. {
  335. Debug.Assert(null != value, "ConvertToApplicationIntent(null)");
  336. string sValue = (value as string);
  337. ApplicationIntent result;
  338. if (null != sValue)
  339. {
  340. // We could use Enum.TryParse<ApplicationIntent> here, but it accepts value combinations like
  341. // "ReadOnly, ReadWrite" which are unwelcome here
  342. // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method.
  343. if (TryConvertToApplicationIntent(sValue, out result))
  344. {
  345. return result;
  346. }
  347. // try again after remove leading & trailing whitespaces.
  348. sValue = sValue.Trim();
  349. if (TryConvertToApplicationIntent(sValue, out result))
  350. {
  351. return result;
  352. }
  353. // string values must be valid
  354. throw ADP.InvalidConnectionOptionValue(keyword);
  355. }
  356. else
  357. {
  358. // the value is not string, try other options
  359. ApplicationIntent eValue;
  360. if (value is ApplicationIntent)
  361. {
  362. // quick path for the most common case
  363. eValue = (ApplicationIntent)value;
  364. }
  365. else if (value.GetType().IsEnum)
  366. {
  367. // explicitly block scenarios in which user tries to use wrong enum types, like:
  368. // builder["ApplicationIntent"] = EnvironmentVariableTarget.Process;
  369. // workaround: explicitly cast non-ApplicationIntent enums to int
  370. throw ADP.ConvertFailed(value.GetType(), typeof(ApplicationIntent), null);
  371. }
  372. else
  373. {
  374. try
  375. {
  376. // Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
  377. eValue = (ApplicationIntent)Enum.ToObject(typeof(ApplicationIntent), value);
  378. }
  379. catch (ArgumentException e)
  380. {
  381. // to be consistent with the messages we send in case of wrong type usage, replace
  382. // the error with our exception, and keep the original one as inner one for troubleshooting
  383. throw ADP.ConvertFailed(value.GetType(), typeof(ApplicationIntent), e);
  384. }
  385. }
  386. // ensure value is in valid range
  387. if (IsValidApplicationIntentValue(eValue))
  388. {
  389. return eValue;
  390. }
  391. else
  392. {
  393. throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue);
  394. }
  395. }
  396. }
  397. const string SqlPasswordString = "Sql Password";
  398. const string ActiveDirectoryPasswordString = "Active Directory Password";
  399. const string ActiveDirectoryIntegratedString = "Active Directory Integrated";
  400. internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result)
  401. {
  402. Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 4, "SqlAuthenticationMethod enum has changed, update needed");
  403. bool isSuccess = false;
  404. if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlPasswordString))
  405. {
  406. result = SqlAuthenticationMethod.SqlPassword;
  407. isSuccess = true;
  408. }
  409. else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryPasswordString))
  410. {
  411. result = SqlAuthenticationMethod.ActiveDirectoryPassword;
  412. isSuccess = true;
  413. }
  414. else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryIntegratedString))
  415. {
  416. result = SqlAuthenticationMethod.ActiveDirectoryIntegrated;
  417. isSuccess = true;
  418. }
  419. else
  420. {
  421. result = DbConnectionStringDefaults.Authentication;
  422. }
  423. return isSuccess;
  424. }
  425. /// <summary>
  426. /// Column Encryption Setting.
  427. /// </summary>
  428. const string ColumnEncryptionSettingEnabledString = "Enabled";
  429. const string ColumnEncryptionSettingDisabledString = "Disabled";
  430. /// <summary>
  431. /// Convert a string value to the corresponding SqlConnectionColumnEncryptionSetting.
  432. /// </summary>
  433. /// <param name="value"></param>
  434. /// <param name="result"></param>
  435. /// <returns></returns>
  436. internal static bool TryConvertToColumnEncryptionSetting(string value, out SqlConnectionColumnEncryptionSetting result) {
  437. bool isSuccess = false;
  438. if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingEnabledString)) {
  439. result = SqlConnectionColumnEncryptionSetting.Enabled;
  440. isSuccess = true;
  441. }
  442. else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingDisabledString)) {
  443. result = SqlConnectionColumnEncryptionSetting.Disabled;
  444. isSuccess = true;
  445. }
  446. else {
  447. result = DbConnectionStringDefaults.ColumnEncryptionSetting;
  448. }
  449. return isSuccess;
  450. }
  451. /// <summary>
  452. /// Is it a valid connection level column encryption setting ?
  453. /// </summary>
  454. /// <param name="value"></param>
  455. /// <returns></returns>
  456. internal static bool IsValidColumnEncryptionSetting(SqlConnectionColumnEncryptionSetting value) {
  457. Debug.Assert(Enum.GetNames(typeof(SqlConnectionColumnEncryptionSetting)).Length == 2, "SqlConnectionColumnEncryptionSetting enum has changed, update needed");
  458. return value == SqlConnectionColumnEncryptionSetting.Enabled || value == SqlConnectionColumnEncryptionSetting.Disabled;
  459. }
  460. /// <summary>
  461. /// Convert connection level column encryption setting value to string.
  462. /// </summary>
  463. /// <param name="value"></param>
  464. /// <returns></returns>
  465. internal static string ColumnEncryptionSettingToString(SqlConnectionColumnEncryptionSetting value) {
  466. Debug.Assert(IsValidColumnEncryptionSetting(value), "value is not a valid connection level column encryption setting.");
  467. switch (value) {
  468. case SqlConnectionColumnEncryptionSetting.Enabled:
  469. return ColumnEncryptionSettingEnabledString;
  470. case SqlConnectionColumnEncryptionSetting.Disabled:
  471. return ColumnEncryptionSettingDisabledString;
  472. default:
  473. return null;
  474. }
  475. }
  476. internal static bool IsValidAuthenticationTypeValue(SqlAuthenticationMethod value) {
  477. Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 4, "SqlAuthenticationMethod enum has changed, update needed");
  478. return value == SqlAuthenticationMethod.SqlPassword
  479. || value == SqlAuthenticationMethod.ActiveDirectoryPassword
  480. || value == SqlAuthenticationMethod.ActiveDirectoryIntegrated
  481. || value == SqlAuthenticationMethod.NotSpecified;
  482. }
  483. internal static string AuthenticationTypeToString(SqlAuthenticationMethod value)
  484. {
  485. Debug.Assert(IsValidAuthenticationTypeValue(value));
  486. switch (value)
  487. {
  488. case SqlAuthenticationMethod.SqlPassword:
  489. return SqlPasswordString;
  490. case SqlAuthenticationMethod.ActiveDirectoryPassword:
  491. return ActiveDirectoryPasswordString;
  492. case SqlAuthenticationMethod.ActiveDirectoryIntegrated:
  493. return ActiveDirectoryIntegratedString;
  494. default:
  495. return null;
  496. }
  497. }
  498. internal static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value)
  499. {
  500. if (null == value)
  501. {
  502. return DbConnectionStringDefaults.Authentication;
  503. }
  504. string sValue = (value as string);
  505. SqlAuthenticationMethod result;
  506. if (null != sValue)
  507. {
  508. if (TryConvertToAuthenticationType(sValue, out result))
  509. {
  510. return result;
  511. }
  512. // try again after remove leading & trailing whitespaces.
  513. sValue = sValue.Trim();
  514. if (TryConvertToAuthenticationType(sValue, out result))
  515. {
  516. return result;
  517. }
  518. // string values must be valid
  519. throw ADP.InvalidConnectionOptionValue(keyword);
  520. }
  521. else
  522. {
  523. // the value is not string, try other options
  524. SqlAuthenticationMethod eValue;
  525. if (value is SqlAuthenticationMethod)
  526. {
  527. // quick path for the most common case
  528. eValue = (SqlAuthenticationMethod)value;
  529. }
  530. else if (value.GetType().IsEnum)
  531. {
  532. // explicitly block scenarios in which user tries to use wrong enum types, like:
  533. // builder["ApplicationIntent"] = EnvironmentVariableTarget.Process;
  534. // workaround: explicitly cast non-ApplicationIntent enums to int
  535. throw ADP.ConvertFailed(value.GetType(), typeof(SqlAuthenticationMethod), null);
  536. }
  537. else
  538. {
  539. try
  540. {
  541. // Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
  542. eValue = (SqlAuthenticationMethod)Enum.ToObject(typeof(SqlAuthenticationMethod), value);
  543. }
  544. catch (ArgumentException e)
  545. {
  546. // to be consistent with the messages we send in case of wrong type usage, replace
  547. // the error with our exception, and keep the original one as inner one for troubleshooting
  548. throw ADP.ConvertFailed(value.GetType(), typeof(SqlAuthenticationMethod), e);
  549. }
  550. }
  551. // ensure value is in valid range
  552. if (IsValidAuthenticationTypeValue(eValue))
  553. {
  554. return eValue;
  555. }
  556. else
  557. {
  558. throw ADP.InvalidEnumerationValue(typeof(SqlAuthenticationMethod), (int)eValue);
  559. }
  560. }
  561. }
  562. /// <summary>
  563. /// Convert the provided value to a SqlConnectionColumnEncryptionSetting.
  564. /// </summary>
  565. /// <param name="keyword"></param>
  566. /// <param name="value"></param>
  567. /// <returns></returns>
  568. internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSetting(string keyword, object value) {
  569. if (null == value) {
  570. return DbConnectionStringDefaults.ColumnEncryptionSetting;
  571. }
  572. string sValue = (value as string);
  573. SqlConnectionColumnEncryptionSetting result;
  574. if (null != sValue) {
  575. if (TryConvertToColumnEncryptionSetting(sValue, out result)) {
  576. return result;
  577. }
  578. // try again after remove leading & trailing whitespaces.
  579. sValue = sValue.Trim();
  580. if (TryConvertToColumnEncryptionSetting(sValue, out result)) {
  581. return result;
  582. }
  583. // string values must be valid
  584. throw ADP.InvalidConnectionOptionValue(keyword);
  585. }
  586. else {
  587. // the value is not string, try other options
  588. SqlConnectionColumnEncryptionSetting eValue;
  589. if (value is SqlConnectionColumnEncryptionSetting) {
  590. // quick path for the most common case
  591. eValue = (SqlConnectionColumnEncryptionSetting)value;
  592. }
  593. else if (value.GetType().IsEnum) {
  594. // explicitly block scenarios in which user tries to use wrong enum types, like:
  595. // builder["SqlConnectionColumnEncryptionSetting"] = EnvironmentVariableTarget.Process;
  596. // workaround: explicitly cast non-SqlConnectionColumnEncryptionSetting enums to int
  597. throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionColumnEncryptionSetting), null);
  598. }
  599. else {
  600. try {
  601. // Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
  602. eValue = (SqlConnectionColumnEncryptionSetting)Enum.ToObject(typeof(SqlConnectionColumnEncryptionSetting), value);
  603. }
  604. catch (ArgumentException e) {
  605. // to be consistent with the messages we send in case of wrong type usage, replace
  606. // the error with our exception, and keep the original one as inner one for troubleshooting
  607. throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionColumnEncryptionSetting), e);
  608. }
  609. }
  610. // ensure value is in valid range
  611. if (IsValidColumnEncryptionSetting(eValue)) {
  612. return eValue;
  613. }
  614. else {
  615. throw ADP.InvalidEnumerationValue(typeof(SqlConnectionColumnEncryptionSetting), (int)eValue);
  616. }
  617. }
  618. }
  619. }
  620. internal static class DbConnectionStringDefaults {
  621. // all
  622. // internal const string NamedConnection = "";
  623. // Odbc
  624. internal const string Driver = "";
  625. internal const string Dsn = "";
  626. // OleDb
  627. internal const bool AdoNetPooler = false;
  628. internal const string FileName = "";
  629. internal const int OleDbServices = ~(/*DBPROPVAL_OS_AGR_AFTERSESSION*/0x00000008 | /*DBPROPVAL_OS_CLIENTCURSOR*/0x00000004); // -13
  630. internal const string Provider = "";
  631. // OracleClient
  632. internal const bool Unicode = false;
  633. internal const bool OmitOracleConnectionName = false;
  634. // SqlClient
  635. internal const ApplicationIntent ApplicationIntent = System.Data.SqlClient.ApplicationIntent.ReadWrite;
  636. internal const string ApplicationName = ".Net SqlClient Data Provider";
  637. internal const bool AsynchronousProcessing = false;
  638. internal const string AttachDBFilename = "";
  639. internal const int ConnectTimeout = 15;
  640. internal const bool ConnectionReset = true;
  641. internal const bool ContextConnection = false;
  642. internal const string CurrentLanguage = "";
  643. internal const string DataSource = "";
  644. internal const bool Encrypt = false;
  645. internal const bool Enlist = true;
  646. internal const string FailoverPartner = "";
  647. internal const string InitialCatalog = "";
  648. internal const bool IntegratedSecurity = false;
  649. internal const int LoadBalanceTimeout = 0; // default of 0 means don't use
  650. internal const bool MultipleActiveResultSets = false;
  651. internal const bool MultiSubnetFailover = false;
  652. internal const bool TransparentNetworkIPResolution = true;
  653. internal const int MaxPoolSize = 100;
  654. internal const int MinPoolSize = 0;
  655. internal const string NetworkLibrary = "";
  656. internal const int PacketSize = 8000;
  657. internal const string Password = "";
  658. internal const bool PersistSecurityInfo = false;
  659. internal const bool Pooling = true;
  660. internal const bool TrustServerCertificate = false;
  661. internal const string TypeSystemVersion = "Latest";
  662. internal const string UserID = "";
  663. internal const bool UserInstance = false;
  664. internal const bool Replication = false;
  665. internal const string WorkstationID = "";
  666. internal const string TransactionBinding = "Implicit Unbind";
  667. internal const int ConnectRetryCount = 1;
  668. internal const int ConnectRetryInterval = 10;
  669. internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified;
  670. internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
  671. }
  672. internal static class DbConnectionOptionKeywords {
  673. // Odbc
  674. internal const string Driver = "driver";
  675. internal const string Pwd = "pwd";
  676. internal const string UID = "uid";
  677. // OleDb
  678. internal const string DataProvider = "data provider";
  679. internal const string ExtendedProperties = "extended properties";
  680. internal const string FileName = "file name";
  681. internal const string Provider = "provider";
  682. internal const string RemoteProvider = "remote provider";
  683. // common keywords (OleDb, OracleClient, SqlClient)
  684. internal const string Password = "password";
  685. internal const string UserID = "user id";
  686. }
  687. internal static class DbConnectionStringKeywords {
  688. // all
  689. // internal const string NamedConnection = "Named Connection";
  690. // Odbc
  691. internal const string Driver = "Driver";
  692. internal const string Dsn = "Dsn";
  693. internal const string FileDsn = "FileDsn";
  694. internal const string SaveFile = "SaveFile";
  695. // OleDb
  696. internal const string FileName = "File Name";
  697. internal const string OleDbServices = "OLE DB Services";
  698. internal const string Provider = "Provider";
  699. // OracleClient
  700. internal const string Unicode = "Unicode";
  701. internal const string OmitOracleConnectionName = "Omit Oracle Connection Name";
  702. // SqlClient
  703. internal const string ApplicationIntent = "ApplicationIntent";
  704. internal const string ApplicationName = "Application Name";
  705. internal const string AsynchronousProcessing = "Asynchronous Processing";
  706. internal const string AttachDBFilename = "AttachDbFilename";
  707. internal const string ConnectTimeout = "Connect Timeout";
  708. internal const string ConnectionReset = "Connection Reset";
  709. internal const string ContextConnection = "Context Connection";
  710. internal const string CurrentLanguage = "Current Language";
  711. internal const string Encrypt = "Encrypt";
  712. internal const string FailoverPartner = "Failover Partner";
  713. internal const string InitialCatalog = "Initial Catalog";
  714. internal const string MultipleActiveResultSets = "MultipleActiveResultSets";
  715. internal const string MultiSubnetFailover = "MultiSubnetFailover";
  716. internal const string TransparentNetworkIPResolution = "TransparentNetworkIPResolution";
  717. internal const string NetworkLibrary = "Network Library";
  718. internal const string PacketSize = "Packet Size";
  719. internal const string Replication = "Replication";
  720. internal const string TransactionBinding = "Transaction Binding";
  721. internal const string TrustServerCertificate = "TrustServerCertificate";
  722. internal const string TypeSystemVersion = "Type System Version";
  723. internal const string UserInstance = "User Instance";
  724. internal const string WorkstationID = "Workstation ID";
  725. internal const string ConnectRetryCount = "ConnectRetryCount";
  726. internal const string ConnectRetryInterval = "ConnectRetryInterval";
  727. internal const string Authentication = "Authentication";
  728. internal const string Certificate = "Certificate";
  729. internal const string ColumnEncryptionSetting = "Column Encryption Setting";
  730. // common keywords (OleDb, OracleClient, SqlClient)
  731. internal const string DataSource = "Data Source";
  732. internal const string IntegratedSecurity = "Integrated Security";
  733. internal const string Password = "Password";
  734. internal const string PersistSecurityInfo = "Persist Security Info";
  735. internal const string UserID = "User ID";
  736. // managed pooling (OracleClient, SqlClient)
  737. internal const string Enlist = "Enlist";
  738. internal const string LoadBalanceTimeout = "Load Balance Timeout";
  739. internal const string MaxPoolSize = "Max Pool Size";
  740. internal const string Pooling = "Pooling";
  741. internal const string MinPoolSize = "Min Pool Size";
  742. }
  743. internal static class DbConnectionStringSynonyms {
  744. //internal const string AsynchronousProcessing = Async;
  745. internal const string Async = "async";
  746. //internal const string ApplicationName = APP;
  747. internal const string APP = "app";
  748. //internal const string AttachDBFilename = EXTENDEDPROPERTIES+","+INITIALFILENAME;
  749. internal const string EXTENDEDPROPERTIES = "extended properties";
  750. internal const string INITIALFILENAME = "initial file name";
  751. //internal const string ConnectTimeout = CONNECTIONTIMEOUT+","+TIMEOUT;
  752. internal const string CONNECTIONTIMEOUT = "connection timeout";
  753. internal const string TIMEOUT = "timeout";
  754. //internal const string CurrentLanguage = LANGUAGE;
  755. internal const string LANGUAGE = "language";
  756. //internal const string OraDataSource = SERVER;
  757. //internal const string SqlDataSource = ADDR+","+ADDRESS+","+SERVER+","+NETWORKADDRESS;
  758. internal const string ADDR = "addr";
  759. internal const string ADDRESS = "address";
  760. internal const string SERVER = "server";
  761. internal const string NETWORKADDRESS = "network address";
  762. //internal const string InitialCatalog = DATABASE;
  763. internal const string DATABASE = "database";
  764. //internal const string IntegratedSecurity = TRUSTEDCONNECTION;
  765. internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in everett
  766. //internal const string LoadBalanceTimeout = ConnectionLifetime;
  767. internal const string ConnectionLifetime = "connection lifetime";
  768. //internal const string NetworkLibrary = NET+","+NETWORK;
  769. internal const string NET = "net";
  770. internal const string NETWORK = "network";
  771. internal const string WorkaroundOracleBug914652 = "Workaround Oracle Bug 914652";
  772. //internal const string Password = Pwd;
  773. internal const string Pwd = "pwd";
  774. //internal const string PersistSecurityInfo = PERSISTSECURITYINFO;
  775. internal const string PERSISTSECURITYINFO = "persistsecurityinfo";
  776. //internal const string UserID = UID+","+User;
  777. internal const string UID = "uid";
  778. internal const string User = "user";
  779. //internal const string WorkstationID = WSID;
  780. internal const string WSID = "wsid";
  781. }
  782. }