From 5b53b5e7dcfec059377030eeee27f718dac4a520 Mon Sep 17 00:00:00 2001 From: vadymkutsenko Date: Fri, 11 Oct 2024 18:55:47 +0300 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2f0de19396721dd10ca8587c73ba1e1347d444a5 Author: SqlClient DevOps Date: Fri Oct 11 02:13:34 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 88086308fc36c1e570f230e4e1a83303461857c8 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed Oct 9 06:13:20 2024 +0100 Merged DbConnectionPool (#2812) commit 40206cd514bb5eed80fca84ff2934fc1aac17a4c Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed Oct 9 05:22:04 2024 +0100 Enrol GetSchema commands into current transaction (#2876) commit 2a015d2197177791bac2d454ed5dc27d08af9ae2 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed Oct 9 05:21:49 2024 +0100 Allow errors with negative numbers to be considered transient (#2896) commit bfb2579e3e59e2a7d3d229104bc151eaa3b997ee Author: David Engel Date: Tue Oct 8 21:21:04 2024 -0700 CertificateTests are broken (#2805) commit a852709376e34f7bbeb2c3942795dc7c04d831ce Author: David Engel Date: Tue Oct 8 21:18:41 2024 -0700 Retry Build Ext Utilities and Nuget Restore on failure (#2906) commit 467701e0bb6786e7bd7fd49b8e14db2003162ac1 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue Oct 8 21:57:04 2024 +0100 Merge SqlColumnEncryptionEnclaveProvider, SqlColumnEncryptionCspProvider, SqlColumnEncryptionCngProvider (#2501) Thanks @edwardneal ! * Merged SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs * Merged SqlColumnEncryptionEnclaveProvider * Merged SqlColumnEncryptionCspProvider * Merged SqlColumnEncryptionCngProvider * Corrected project files post-merge commit 9b9bdc1c0348d272fab1d2a6586beb482c7fc5b6 Author: Benjamin Russell Date: Tue Oct 8 13:51:33 2024 -0500 Cleanup | Flatten Interop Folders (#2900) * Remove the extra src folder in interop, etc. * Move netfx common files out of src folder * Fixing a couple file includes * Delete files that weren't part of the project commit b0433f019fa0daeba141aa7e6548a0c72be20b38 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue Oct 8 17:49:56 2024 +0100 Merge AAsyncCallContext, cleanup for SqlDataReader merge (#2383) Thanks again to @edwardneal ! * Merged AAsyncCallContext. Also changed netfx SqlDataReader to use the common class hierarchy, and made whitespace changes to SqlDataReader to make the netcore/netfx diff slightly shorter * Expanding use of CallerMemberName in SqlDataReader * Adjusted comments and variable names, added conditional compilation blocks. These aren't functional changes, but they do pare down the diff between netcore and netfx. Also sealed the Snapshot class in both codebases for performance improvements. * Reverted change to ObjectID following compilation and testing * Corrected a failing manual test * Further post-merge changes Keeps SqlDataReader in sync with main * Code review comments Also one AlwaysEncrypted sync/bugfix in SqlDataReader from netfx to netcore * Corrected conditional compilation directive commit ca9272d1eb1db843119ef120ff02f7067b0f4e4a Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon Oct 7 21:26:27 2024 +0100 Add test coverage for PR 2873 (#2897) commit 7a7b247aa66c5eafb5a39f750d819084b1d551a9 Author: SqlClient DevOps Date: Mon Oct 7 19:54:17 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 76338d3800ed7c906e00220294e8b353c0bb5735 Author: Benjamin Russell Date: Mon Oct 7 11:14:59 2024 -0500 Merge | Bring netcore Interop to Common Project (#2893) * Move ntdll interop files from netcore to common folder * Moving enough interop files into the common project to enable SqlFileStream migration * Move Interop.FileTypes and Interop.SetThreadErrorMode into common interop folder. * Move Interop.IoControlCodeAccess * Moving Interop.Libraries into the common project * Removing files that were moved commit 9433389ebba4528a192abaa386dea97da202d166 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon Oct 7 17:01:01 2024 +0100 Removed references to CTAIP and client certificate authentication (#2831) commit 4e118ae2b792a51a9866a94ad5cbf198fee9bba7 Author: Maxim Markelow Date: Mon Oct 7 18:56:46 2024 +0300 Fixed incorrect string format at event tracing when OutOfMemory exception thrown (#2797) commit c0ae757809fa43441832d6ac220bb310e5102cc2 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat Oct 5 08:36:52 2024 +0100 Merge AlwaysEncryptedHelperClasses, TdsParserHelperClasses (#2376) commit 32b5a67fe6b95a4e15ace8fae7a20e6db6421136 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sat Oct 5 08:30:43 2024 +0100 Removed unreferenced/unused code (#2814) commit d3772fcb8c9fb48cad577abce1f3f6474d97da48 Author: Javad Rahnama Date: Sat Oct 5 00:28:23 2024 -0700 Fix | Increase routing attempt to 10 in netcore for LoginNoFailover and adding routing support to LoginWithFailover (#2873) commit cab54224419ae81c30f05eb2ea3aebc154ca99be Author: Benjamin Russell Date: Tue Oct 1 11:32:12 2024 -0500 Project for Common Files (#2887) * Project file for common files. Not built in any configuration. * Removing root namespace to prevent warnings for wrong namespace. commit 72951f45468e0944db64440f15718b7d3094ede8 Author: Deepak Saini Date: Tue Oct 1 19:59:23 2024 +0530 Fix SqlDataReader.IsDBNull() for json (#2892) commit cc58d7923952a8b2e9e397490dca2b08f7f3ce80 Author: Deepak Saini Date: Tue Oct 1 00:42:28 2024 +0530 Enhancement tasks for json support (#2891) * some enhancements tasks for json support * added some missing drop table funtion * remove unique naming for tables and SPs commit 0266b4a2209f732ead650181ae924a74a0c4cf40 Author: Deepak Saini Date: Sun Sep 29 01:38:33 2024 +0530 Adding SqlJson and Data write with SqlJson (#2752) (#2880) * Adding SqlJson and Data write with SqlJson (#2752) * Adding the SqlJson type Remove unused Adding all the json tests Revert "Remove unused" This reverts commit c448b6e2e810630d217826e73a644f7f9815d366. Remove unused * Change to static * Adding the SqlJson support * Adding the assert for column encryption * Adding the support for Json writes * Adding more support * Enabling the following SqlString sqlString = reader.GetSqlString(0); Assert.NotNull(sqlString.Value); var sqlJson = reader.GetSqlJson(0); Assert.NotNull(sqlJson); string fieldval = reader.GetFieldValue(0); Assert.NotNull(fieldval); JsonDocument jsondoc = reader.GetFieldValue(0); Assert.NotNull(jsondoc); * Revert "Enabling the following" This reverts commit 6739e455b62c88a56100552072eea368d05e23ea. * ref update for SqlJson * resolve PR comments --------- Co-authored-by: Saurabh Singh <1623701+saurabh500@users.noreply.github.com> commit 4806059d1d2a40f00c2f9adfc2d9d4f0f3a02eae Author: Javad Rahnama Date: Fri Sep 27 12:42:57 2024 -0700 Fix | Addressing documentation issues along with spelling errors (#2889) commit 6064d026858fc2585e81bda5600ac60388be75ea Author: Apoorv Deshmukh Date: Fri Sep 27 09:52:33 2024 +0530 Add streaming support for JSON (#2882) This commit adds support for streaming JSON data to and from Sql Server. JsonStreamTest has been added to demonstrate this functionality. commit ed0a132d365611afaf114ab2281e71c402e32f37 Author: Benjamin Russell Date: Tue Sep 24 18:01:51 2024 -0500 Fix build breaks (#2885) commit 135120af6556ca0151cd834450e54751d0f6e84f Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue Sep 24 16:51:55 2024 +0100 XML documentation corrections - batch 1 (#2836) Thanks @edwardneal! * Rollup of feedback from Batch 1 PR * Respond to code review Also expanded SqlBatch corrections to code files and other instances in the XML documentation. commit c690120925476280542e38a28c7d3b1be8478455 Author: Benjamin Russell Date: Mon Sep 23 11:22:31 2024 -0500 XML Documentation Fixes - Batch 7 (#2869) * Batch 7 w/o testing * Spot checking! * Fixing build issue commit 3d9c1e4178034cc1c709ad18832b056fc1c380a2 Author: Benjamin Russell Date: Mon Sep 23 11:22:07 2024 -0500 XML Documentation Fixes - Batch 8 (#2871) * Batch 8.1 * Batch 8.2 * Batch 8.3 * Batch 8.4? * Checking things over commit cb11317441e091d9ad40ad8f6e738831f252476c Author: Benjamin Russell Date: Fri Sep 20 16:54:30 2024 -0500 XML Documentation Fixes - Batch 5 (#2864) * Batch 5 part 1 * Batch 5 part 2 * Finishing up changes to batch 5 * PR Comments commit bc08543c1d3380b1ef6cac7e27761ce568cfb010 Author: Deepak Saini Date: Fri Sep 20 11:58:08 2024 +0530 Implement read and write functionality for JSON (#2829) * Implement read and write functionality for JSON col (#2722) * Implement read functionality for JSON col * Remove SqlJson class * Implement JSON write functionality * Remove code comment for new datatypes * Json read and write tests (#2744) * Json read and write tests * added sp tests * remove AppContext Switch * resolve some PR comments * refactored tests * add async testing * fix build errors * Ref update for SqlDbTypeExtensions (#2745) * resolve PR comments * Apply suggestions from code review Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> --------- Co-authored-by: Apoorv Deshmukh Co-authored-by: Saurabh Singh <1623701+saurabh500@users.noreply.github.com> Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> commit 95cd389878cc8f9f638eafff9e7f64be577c36d2 Author: Benjamin Russell Date: Thu Sep 19 13:06:45 2024 -0500 XML Documentation Fixes - Batch 6 (#2865) * Batch 6 part 1 * Finishing up batch 6 commit 3416ad92b9107d2618bc7ffdf1d595a86cf0e7d0 Author: Benjamin Russell Date: Thu Sep 19 12:26:42 2024 -0500 XML Documentation Fixes - Batch 4 (#2863) * Batch 4 * Touching up and fixing mistakes * Tabs to spaces * Using new sample file commit cdc33d91a64308e4861844da755ffbe9a407cc1c Author: David Engel Date: Mon Sep 16 11:19:18 2024 -0700 Sync sample changes into snippet doc (#2837) commit 68a5be4eee9224c9c6007398e952d1f7f02c2570 Author: Benjamin Russell Date: Mon Sep 16 11:49:04 2024 -0500 XML Documentation Fixes - Batch 3 (#2851) * Batch 3 * Fixing issue from last PR * Making sure everything is ready for PR (left off at sqlcommand.xml) * Finishing up work for batch 3 * PR comments commit 321080e2b25b39e42b3aadc325610a96654c298b Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Fri Sep 13 10:57:12 2024 -0700 Update CDP_BUILD_TYPE condition in AKV provider (#2854) commit 764add38972945f5212c9cc5cf346c493c310187 Author: Benjamin Russell Date: Thu Sep 12 12:53:43 2024 -0500 XML Documentation Fix - Batch #2 (#2834) * Batch #2 * Reverting removal of the snippet files. * Fixing build break caused by parameter not having a comment. * These changes should fix the broken comments commit b1d3a8297a8d7d3b62e35cb87924feb90afa4cb3 Author: Malcolm Daigle Date: Tue Sep 10 11:01:37 2024 -0700 Port double clean fix to netfx (#2843) commit 069c052922c7183ec66f39904bfaf77fa2622c1f Merge: db64574c eb4c0f04 Author: SqlClient Azure DevOps Date: Mon Sep 9 23:01:05 2024 +0000 Merge in 'main' changes commit db64574c63daff25026000d9c84e3b3822b11263 Merge: f8f2a964 8412215e Author: Daniel Au Date: Mon Sep 9 21:16:08 2024 +0000 Merged PR 4909: eng | Fix strong name in AKV provider Bug fix to address the missing strong name in the Azure Key Vault (AKV) provider. This pull request fixes the strong name issue in the AKV provider for various .NET frameworks. - `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj`: Added strong name generation configurations. - `build-all-configurations-signed-dlls-step.yml`: Updated MSBuild arguments to use `SigningKeyPath`. - `code-analyze-step.yml`: Updated MSBuild command line to include `SigningKeyPath`. Related work items: #31596 commit eb4c0f043bff30c7f3bb58704b41c73faef9d63b Author: Malcolm Daigle Date: Mon Sep 9 11:04:55 2024 -0700 Advance column index to avoid double clean. (#2825) commit 8412215e9f8231bb10e4ef8ba98d113450025aaa Author: dauinsight Date: Mon Sep 9 08:39:32 2024 -0700 Simplify assembly key file condition commit 62af3b51318ebba36327aa61b014264fd57a4130 Author: Javad Rahnama Date: Fri Sep 6 11:16:27 2024 -0700 Fix | Adding readme to nuget package (#2826) commit cf92a05fd5ba458c1001dcd4af1b5bfba93dde66 Author: David Engel Date: Thu Sep 5 11:30:55 2024 -0700 Sample code improvements around token caching (#2821) commit 5dc7b06e16705f6dcb8a0f437b28cd320ee2a719 Author: Benjamin Russell Date: Thu Sep 5 13:06:13 2024 -0500 Reverting removal of the snippet files. (#2835) commit 77b2c7aae21a4953c816d5426513471dccb8370b Author: dauinsight Date: Thu Sep 5 10:21:05 2024 -0700 Remove sign assembly from AKV build command commit b6a28f7f9b65a36af41533a44b4d4fb7bf0c1c65 Author: Benjamin Russell Date: Thu Sep 5 10:56:20 2024 -0500 XML Documentation Fix - Batch 1 (#2822) * Batch 1 of fixing xml files * Removing CDATA blocks, fixing cref links * Fixing a couple more issues commit dbe09f1152f448ec7b6037579d9bcbf98b016fce Author: dauinsight Date: Wed Sep 4 14:34:17 2024 -0700 Update AKV strong name commit d89372af4153ec41f320b912748e032b160160c9 Author: Deepak Saini Date: Sat Aug 31 04:04:13 2024 +0530 Add Feature Extension for Json Support (#2773) * Add Feature Extension for Json Support (#2696) * change json hexa code and fix invalid login error * Change name to match other naming conventions * process JSONSUpport acknowledgement * Fix naming conventions * Processing 2nd byte from server * Changes for netfx * Json support feature ack in Test TDS server * Remove enabled flag * address PR comments * Enable JSON only in debug bits * Enable json tests in debug mode only * resolve PR comments --------- Co-authored-by: saurabh500 <1623701+saurabh500@users.noreply.github.com> commit 8ff48a707ca0db95a18449c108a37e073f04b640 Author: Javad Rahnama Date: Fri Aug 30 10:39:34 2024 -0700 Update README file (#2809) commit aa0db93336511390b9e389123f25a5ae74e55c62 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Aug 29 17:59:42 2024 +0000 Test | Fix Unit Tests for GetSqlServerSPN (#2442) commit 9573da26fbab3de0ab75110f769b3c5b2f55199a Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Aug 28 10:51:41 2024 -0700 Doc | Release notes v6.0 preview1 (#2813) commit 5ea0e25d68b18e14e4446bd783fb91c4bc7cdf19 Author: David Engel Date: Tue Aug 27 16:24:24 2024 -0700 Add porting information about NLS to ICU .NET 5+ change (#2820) commit c223dfb9c301812a4a73cad80d9f3c15d58c6a9b Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Tue Aug 27 15:48:48 2024 -0700 Hotfix v5.2.2 Release notes (#2770) commit 12d5391686bb2795670d749a97b563e2da4f84d4 Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Tue Aug 27 14:56:09 2024 -0700 Hotfix v5.1.6 Release notes (#2769) commit f8f2a96403e99c008f5beb3a56e43f554af24db1 Merge: b50c074d bea3e67f Author: SqlClient Azure DevOps Date: Tue Aug 27 19:07:19 2024 +0000 Merge in 'main' changes commit b50c074d9bb5cb5e19b0256bbe4f848b92d06f9f Author: Davoud Eshtehari Date: Tue Aug 27 17:33:34 2024 +0000 Merged PR 4888: eng | Fix package validation stage against the preview commit bea3e67f3ee2b7f12cc3547455868c084a5d9e40 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue Aug 27 00:37:42 2024 +0100 Merged DbConnectionClosed, DbConnectionFactory, SqlAuthenticationProviderManager (#2410) commit 71deba6427dbb4d50c4329508de827e2fd0ef15e Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Aug 26 12:41:19 2024 -0700 Refine version.props and nuspec files (#2811) commit 50767d79069226816b8b3367fae6db4c375a48ea Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Fri Aug 23 09:01:12 2024 -0700 Hotfix v4.0.6 Release notes (#2768) commit 6d33e9d20e95f5f8d8eebe7db1458f88ca4dbd78 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed Aug 21 23:34:00 2024 +0100 Merged PoolWaitHandles, DbConnectionPoolIdentity, removed DbBuffer (#2390) commit 85b9407e4ee699b3229c5bb1629f4219e52fdf74 Author: Javad Rahnama Date: Wed Aug 21 15:14:16 2024 -0700 Eng | Add strong name validation to package validator (#2802) commit cc144a8a1c383106264cf348c5f889bd051d7463 Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Wed Aug 21 15:10:58 2024 -0700 Hotfix v3.1.7 Release notes (#2800) * Add release notes for 3.1.7 commit ef8d6cc6629395801aeca5a53571cdbd1b84fb5e Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Aug 19 18:04:46 2024 -0700 Doc | Reorder release notes (#2791) commit 4eafe1f7715ae00c94d898a583d0e6f9e9b75779 Author: Davoud Eshtehari Date: Mon Aug 19 16:27:33 2024 +0000 Merged PR 4847: eng | Add support preview on MDS commit ac1012a6b7ddaf0b14526ced7cea8c16e0791b23 Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Fri Aug 16 13:22:55 2024 -0700 Hotfix v3.1.6 Release notes (#2767) commit 619fa749551ed0d9e387d75cb3e6d85fe00a3df4 Author: Javad Rahnama Date: Thu Aug 15 13:48:15 2024 -0700 Fix | Fix the issue with Socke.Connect in managed SNI (#2777) commit d3658edfcda0d7eecabc09afb5459bb3f79e6290 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Aug 14 17:18:51 2024 -0700 Update SNI version to 6.0.0-preview1.24226.4 (#2772) commit 7216e84fb9819b56df1d51ca13969d4f89bf507a Author: Benjamin Russell Date: Fri Aug 9 12:40:30 2024 -0500 `null != x` => `x != null` (#2751) commit 6fbbb787cd7ea35c06e292bb83d01ae94900b0bf Author: Benjamin Russell Date: Sat Aug 3 11:47:53 2024 -0500 Code Cleanup | `null == x` to `x == null` (#2749) - With one approval and CI success, I think that's enough to move ahead on this one. * `null == x` to `x == null` * Update src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs Co-authored-by: David Engel --------- Co-authored-by: David Engel commit 6f177e30f2a8bbd59a7ec093ef934e29e0578004 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Tue Jul 30 19:52:38 2024 +0000 Fix | Fixed some Azure managed identity authentication unit test failures (#2652) commit 85956440bb0886c59dfa31475b9a6f5c510e3ac0 Author: Benjamin Russell Date: Mon Jul 29 16:05:41 2024 -0500 Replace unused out arguments with discards (#2726) * Replace unused out arguments with discards * Removing unnecessary types in discarded out arguments commit 0c4519871c9b69f7e05fe90f59d224d5f9ab3e3e Author: Cédric Luthi Date: Sat Jul 27 05:30:08 2024 +0700 Avoid "early" access to SqlAuthenticationProviderManager.Instance (#2636) commit 38ce399a77115a6f95fbe8ef54ee300aac58370b Author: Javad Rahnama Date: Fri Jul 26 11:33:47 2024 -0700 FIX | Revert the change to TargetFrameworkMonikerAssemblyAttributesPath from PR #2497 (#2725) commit 04d610211027be0ea70eb2c1e55c24ffa3a5704f Merge: 9e3bbacc 9d8062f1 Author: SqlClient Azure DevOps Date: Thu Jul 25 07:29:05 2024 +0000 Merge in 'main' changes commit 9e3bbaccc448d708a0d1ff96032f890c9a2045b6 Author: Davoud Eshtehari Date: Wed Jul 24 21:23:40 2024 +0000 Merged PR 4782: eng | Secure symbols publishing commit 9d8062f135d9b0491668eb40af5b7caeda2df5f2 Author: Javad Rahnama Date: Wed Jul 24 14:18:17 2024 -0700 Minor adjustment to sourcelink translation (#2713) commit 1152fcf0c628ee84862779d86b9348376f64f4a8 Merge: f7313f81 c4fa6827 Author: SqlClient Azure DevOps Date: Wed Jul 24 00:45:12 2024 +0000 Merge in 'main' changes commit f7313f81542228f5fea1c974e5fda12bb4d5e2c0 Merge: be5fba23 e3cf4149 Author: SqlClient Azure DevOps Date: Tue Jul 23 23:46:13 2024 +0000 Merge in 'main' changes commit c4fa682749110f030d4f43caa488ec4832e04df1 Author: Wraith Date: Wed Jul 24 00:46:09 2024 +0100 Change internal read functions to return TdsOperationResult (#2690) commit e3cf4149a202218919fb9b83e275765aa908a40b Author: David Engel Date: Tue Jul 23 10:38:25 2024 -0700 Fix macOS CI (#2699) commit 79adbc23e786c1b07d3995d5e6717700324555ad Author: Saurabh Singh <1623701+saurabh500@users.noreply.github.com> Date: Tue Jul 23 06:29:52 2024 -0700 Adding the SqlDbTypeExtensions (#2688) commit cf8cc22ae7c4e22764d8561e99cc3dbaa2325a78 Author: SqlClient DevOps Date: Tue Jul 23 02:09:52 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 56c07c627e75fa8a9531b76d02ec8e0113ff3e08 Author: Javad Rahnama Date: Mon Jul 22 13:59:01 2024 -0700 2698) commit 3d7896ff7f656e35d987ce43bc1cb91d95eac5ae Author: Javad Rahnama Date: Mon Jul 22 11:28:25 2024 -0700 set DisableSourceLinkTranslation to false (#2691) commit 7110d29922e402a722ec5bc32fdc8f7bcdf596a4 Author: SqlClient DevOps Date: Mon Jul 22 02:09:38 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit a9621bdc411002f15adba0c849a4ccfbfa210707 Author: SqlClient DevOps Date: Sun Jul 21 02:17:48 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit be5fba235947f2712df3267ccf3654cede5be4f6 Merge: aa0a39be e2273713 Author: SqlClient Azure DevOps Date: Thu Jul 18 21:48:11 2024 +0000 Merge in 'main' changes commit e22737137ad2d7387c452af79d6c95ef9f6549d0 Author: Javad Rahnama Date: Thu Jul 18 14:47:08 2024 -0700 eng | Add Delay sign to ref csprojs (#2684) commit aa0a39be63d7240ec3eac315eadd0aba9d3230ad Merge: 49e4da77 5c0ce12d Author: SqlClient Azure DevOps Date: Tue Jul 16 00:39:23 2024 +0000 Merge in 'main' changes commit 5c0ce12d19972824f0e6b118812de916a6e90c49 Author: SqlClient DevOps Date: Fri Jul 12 19:00:13 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 766b72a752a8df9670e273012b6a6b3718baee80 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Jul 11 10:53:48 2024 -0700 Fix | Fix decrypt failure to drain data (#2618) commit 784046fdbf02e97fb7190542e81ba20d93843261 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jul 11 10:42:56 2024 -0700 eng | Initial YAML CI pipeline (#2575) commit ce7393b4d12dbd35c0b4ad61acbfc1f14a4edc8e Author: Javad Rahnama Date: Wed Jul 10 11:34:17 2024 -0700 eng | Add delay signed to official builds (#2653) commit a34ec48fb8b4cabbe349ef8019a0a885d3aefab1 Author: David Engel Date: Mon Jul 8 12:44:40 2024 -0700 Fix - Don't error when using infinte connect timeout and Entra auth (#2651) commit bad621f7c141079c77574f1eb5b929ed195921a8 Author: David Engel Date: Fri Jul 5 10:32:31 2024 -0700 Test fixes to accommodate recent infra changes (#2646) * Test fixes to accomodate recent infra changes commit 0352a50f779b7977d87714c1934d1f21ea231b6d Author: Benjamin Russell Date: Tue Jul 2 17:36:55 2024 -0500 3 Small Changes (#2594) * * Port sqlclientx datasource changes * Remove link to missing nuget.config file * Remove root namespaces from sqlclient csproj files * Test to see if namespace changes are breaking the pr build * Reinstate removing the root namespace and fix resource filename generation commit f55c5a2065f947942d11c52f2a62a349419278cb Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Jun 27 16:34:57 2024 +0000 Merged common code base for AlwaysEncryptedKeyConverter (#2538) * Merged AlwaysEncryptedKeyConverter.CrossPlatform and AlwaysEncryptedKeyConverter.Cng. commit aece3669a9ae47145d9d68e91c47119079ba7cf8 Author: Erik Ejlskov Jensen Date: Thu Jun 27 14:53:48 2024 +0200 Add test for issue 2456 (#2457) commit f91dc82ca52957ee1bc3d4f233a6e950a8a8dcbb Author: Erik Ejlskov Jensen Date: Wed Jun 26 22:06:33 2024 +0200 Change | Remove some unneeded references and update Azure.Identity (#2577) commit eb46c58805e562a59c1f8d9fb2338645e1a39b05 Author: Erik Ejlskov Jensen Date: Wed Jun 26 16:29:52 2024 +0200 Add | No-op if engineedition is 6 or 11 due to lack of support for ASSEMBLYPROPERTY function (#2593) commit 8777fceef974e95697728f9889e6ce734add759d Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue Jun 25 13:58:15 2024 +0100 Merge SqlColumnEncryptionCertificateStoreProvider (#2521) commit 49e4da777e33d81e4b7c551bd007a240f28207cb Author: Davoud Eshtehari Date: Fri Jun 21 21:48:23 2024 +0000 Merged PR 4673: eng | Upgrade ESRP to v5.0 - [Sample run](https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=91327&view=results) Related work items: #30897 commit 55f48c57a9b2a200c266b8739a2a477f974ab41d Merge: 1dfd4833 d4b2bb32 Author: SqlClient Azure DevOps Date: Wed Jun 12 21:30:06 2024 +0000 Merge in 'main' changes commit d4b2bb32ac2ab2f9ecd12c441733f8d179bf255d Author: Javad Rahnama Date: Wed Jun 12 14:28:37 2024 -0700 Addressing conflict (#2560) commit a240c2432614c156f0f81b9beb7994f2d35ebc52 Author: Javad Rahnama Date: Wed Jun 12 13:15:39 2024 -0700 Address conflicts (#2562) commit d7f84eb09dd8e70ac73f190f913e1dd1a9641138 Author: David Engel Date: Wed Jun 12 12:11:41 2024 -0700 Add scope trace for GenerateSspiClientContext (#2497) commit c822b6917da7e38445777869acdaf13634a826f8 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Wed Jun 12 17:16:35 2024 +0000 Merged common code base for SqlUtil.cs (#2533) commit 080e66950d9d0b6d113c8eae3a2056372159f258 Author: David Engel Date: Wed Jun 12 09:20:14 2024 -0700 Add | Cache TokenCredential objects to take advantage of token caching (#2380) commit a7405ded70a0139a41e97c2ace76977b3a5260a4 Author: Javad Rahnama Date: Tue Jun 11 14:53:27 2024 -0700 Add | Add SourceLink translation (#2552) commit 689cc257fa250d42728c5d240b888b1f151cfd7c Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Tue Jun 11 21:05:07 2024 +0000 Fix | Replaced System.Runtime.Caching with Microsoft.Extensions.Caching.Memory (#2493) commit ffd8771a599f90557facdebd983cd4e60dbb6f83 Author: Wraith Date: Tue Jun 11 21:46:23 2024 +0100 Strong typed diagnostics (#2226) commit 3f0c4b1a706136e417efa3a49bc168342470513e Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Tue Jun 11 19:14:48 2024 +0000 Fix | Fixed GenerateSspiClientContext to retry negotiation with default port (#2559) commit f7ab11591d6fe736f26e1d21756e29e2a2d259d2 Author: Javad Rahnama Date: Sat Jun 8 10:44:31 2024 -0700 Fix | Adjust path for .AssemblyAttributes in obj folder (#2550) commit 1dfd48333c30d031f2f96cd0a40dcf0954cd0ba4 Author: Daniel Au Date: Fri May 31 22:36:06 2024 +0000 Merged PR 4621: eng | Fix policheck commit 348ae2ee13ddccd64fe5fe4220ff22ba04ef9a4b Author: Scott Addie <10702007+scottaddie@users.noreply.github.com> Date: Fri May 31 17:07:36 2024 -0500 Improve AccessTokenCallback sample code (#2543) commit 42e9f08f91a3e1a1602d6b632df00f89abe04760 Author: dauinsight <145612907+dauinsight@users.noreply.github.com> Date: Fri May 31 14:57:21 2024 -0700 Hotfix v5.2.1 Release notes (#2534) commit 7af2438ee177738131c6b13dc37743a2dafe6910 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu May 30 12:11:53 2024 -0700 Fix | Enhance certificate validation (#2487) commit 808d4c3b5a935e6954c96ce02d99c53b624099dc Author: Benjamin Russell Date: Wed May 29 18:45:55 2024 -0500 Change | Separate tests for NetFx and NetCore - NetFx-Only Connection String Properties (#2466) * Adding TransparentNetworkIpResolution to list of unsupported on platform connection string error messages Splitting unit test for netfx-only connection string properties such that test does not fail on netcore * Remove DeprecatedSynonymCount since referencing the unsupported array is not possible commit 815e5ab19e9e096bc52f13a82170aa1c5e641826 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue May 28 09:37:31 2024 -0700 Doc | Fix SNI dependencies of 5.1 and 5.2 release notes (#2537) commit 4c088eb47c80209ed4506237b201a276f552f5bf Author: Aris Rellegue Date: Fri May 24 20:05:54 2024 +0000 Merged PR 4583: eng | Fix policheck errors. Fix policheck errors. Sample pipeline run which did not have policheck errors: https://sqlclientdrivers.visualstudio.com/ADO.Net/_build/results?buildId=88114&view=sariftools.scans.build-tab Related work items: #30279 commit b7c4007d0deb2c2ffa8281f7f731a59f42a5fce1 Author: David Engel Date: Fri May 24 10:21:39 2024 -0700 Enhancement | Add trace logs for packet size (#2522) commit b178ba5d324cfc77a4ff68cf7c250895f766dbeb Author: David Engel Date: Thu May 23 12:10:21 2024 -0700 Fix | Clone of SqlConnection should include AccessTokenCallback (#2525) commit cd7a3d10e88a15e6151afca1d0f2b972d6058fcb Author: Javad Rahnama Date: Thu May 23 09:20:03 2024 -0700 Updating Azure.Identity version to 1.11.3 (#2526) commit 5cb73fdc9fa408fcd033510b2e2182085c1f14c9 Author: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Tue May 14 19:31:10 2024 +0100 Merged SqlClientFactory between .NET Core and Framework (#2369) commit cc6ea2181af5473648d5c7f79b71be30132d0ac0 Author: Erik Ejlskov Jensen Date: Tue May 14 20:30:08 2024 +0200 Streamline conditional compilation symbols (#2486) commit 9a71c94c172fd5b231e9673525e95c7079528fa9 Author: Saurabh Singh <1623701+saurabh500@users.noreply.github.com> Date: Mon May 13 15:37:01 2024 -0700 Update build guide for Linux (#2499) Adding the detail about installing powershell on linux to build the driver commit 4c0f013bac63d8bd928c985440acb1e2bc13d3c6 Author: Erik Ejlskov Jensen Date: Tue May 7 18:02:12 2024 +0200 Remove UWP (uap) references and special cased code (#2483) commit b4f38f50d4fb03e49956b8007496c50c22fbbea2 Author: Taylor Southwick Date: Mon May 6 16:27:12 2024 -0700 Use ReadOnlyMemory in (#2447) commit 55d30c71b9c17b804710b4d7ba83d92f2b2676be Author: Javad Rahnama Date: Mon May 6 10:58:22 2024 -0700 Test | Remove AAS - VBS tests from test pipelines (#2474) commit 48ab625f82bc2f147276e02862b47b24f06d576c Author: SqlClient DevOps Date: Sat May 4 02:08:39 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 05d51bf26732a1784eb4a0b2d96b50bea6989486 Merge: 7def235d 910bdb47 Author: SqlClient Azure DevOps Date: Fri May 3 21:58:12 2024 +0000 Merge in 'main' changes commit 7def235d764c1b1fa12db242afecf146a18a60f6 Author: Davoud Eshtehari Date: Fri May 3 21:51:35 2024 +0000 Merged PR 4490: eng | Remove netstandard from production pipeline - Complementary code change of PR [#2386](https://github.com/dotnet/SqlClient/pull/2386). - This should be merged after merging the related PR to remove support of .NET Standard in the production pipeline. - The first commit has the related PR's changes(review them on GH). - After having merged the related GH PR and updating the CI pipeline, I'll sync with this PR to unify the changes and get passed the pipeline. - Only the YAML changes under the `eng` folder should be reviewed (ignore the other changes as they are identical to the GH). - Introduced `oneBranchType` parameter to switch between **Official** and **NonOfficial** templates - [new sample run](https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=86908&view=results) Related work items: #30122 commit 910bdb4754bfd11c2043c8f8b89b91df49e46888 Author: Wraith Date: Fri May 3 21:10:35 2024 +0100 make EnableOptimizedParameterBinding only apply to text mode commands and update documentation to match. (#2417) commit ba288ef35c09101e0d3b8e96b4003dffbaae7c98 Merge: f05be20e cd4805b1 Author: SqlClient Azure DevOps Date: Fri May 3 20:03:36 2024 +0000 Merge in 'main' changes commit cd4805b144e170c946602d5c54d65ef649bce9a5 Author: Erik Ejlskov Jensen Date: Fri May 3 21:42:21 2024 +0200 Remove support for .NET Standard 2.0 and 2.1 (#2386) commit 792479efaa7155143f3276965fac42c84de35e2e Author: Javad Rahnama Date: Fri May 3 09:22:31 2024 -0700 Test | Remove field with ClientSecretCredential (#2479) commit 226bdb8e4cedd3933ca415a91d69b8c814b5b9df Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu May 2 09:50:38 2024 -0700 Fix | Fix DateTimeOffset size in TdsValueSetter.cs class file. (#2453) commit aefd723026e75e68cea6bc98173404a5c765ab60 Author: Javad Rahnama Date: Tue Apr 30 11:00:01 2024 -0700 Test | Updating tests to acquire token from user-assigned managed identity (#2473) commit f05be20efe40d356f6313f810123a2e5870714dc Author: Davoud Eshtehari Date: Fri Apr 26 20:34:02 2024 +0000 Merged PR 4529: eng | fix a few issues and improvements - Fixed a typo, publish symbols, and commit number - Updated the cron for daily run in case of any code changes, besides the weekly run - Added parameters instead of pipeline's variables - TSA, SBOM, and CodeQL tools moved out of the `syncSdl` for compatibility with OneBranch's NonOfficial template Related work items: #29920 commit c33bde24d4b68116938423c728903ebb3fa74b34 Author: Javad Rahnama Date: Fri Apr 26 11:12:08 2024 -0700 Change | Updating Azure.Identity version to 1.11.2 (#2462) commit 3f3380ccde46102987e527be18b26aee3e9b2026 Author: Javad Rahnama Date: Thu Apr 25 12:25:42 2024 -0700 Test | Address XUnit failure on Windows Principal functionality is not supported on this platform (#2469) commit 4bce7de7bef52823e7733e553c3fd29c3ac6f4ae Merge: abff6630 68d35bb5 Author: SqlClient Azure DevOps Date: Tue Apr 23 17:21:01 2024 +0000 Merge in 'main' changes commit 68d35bb5f116feb2fd10f6b0b2d09a4a835562d5 Author: Benjamin Russell Date: Thu Apr 18 15:35:25 2024 -0500 Change | Simplify Conditional File Inclusion (#2425) * Wrap files in appropriate `#if` and simplify project file * Sorting file includes * Pulling over changes from a different branch from before rebase * Merge changes that should've come in during merge ... * Add true * Change that should've been brought in on merge :thinking: commit abff6630e79ed9fa15c63355a88a5f90819ba199 Author: MerlinBot Date: Wed Apr 17 15:42:10 2024 +0000 Merge pull request 4357 from dependabot/docker/dotnet_docker_images/1708216907 into internal/main commit ea7ad53b26ce24fcb22e643691f50eb6627f35a4 Author: Davoud Eshtehari Date: Mon Apr 15 19:57:54 2024 +0000 Merged PR 4474: eng | Add AKV provider signed package commit ae988c3e6c09725f1190cfb399c6d51835357aa7 Merge: 0c46cd7e 61e89f95 Author: SqlClient Azure DevOps Date: Fri Apr 12 19:49:16 2024 +0000 Merge in 'main' changes commit 61e89f9570bbe53dff0e4c750ccbdb7a46b274b0 Author: Erik Ejlskov Jensen Date: Tue Apr 9 21:27:44 2024 +0200 Fix | ArgumentNullException on SqlDataRecord.GetValue when using Udt data type (#2448) commit f5df519f5e9783d6a726fb370678e05a04a3084b Author: Evgeny Akhtimirov Date: Tue Apr 9 15:04:53 2024 -0400 Fix | SqlBuffer.SqlGuid (#2310) commit 8c9b6992aa812cad39d21460314cd68f5a989b45 Author: Erik Ejlskov Jensen Date: Tue Apr 9 20:33:07 2024 +0200 Extend DateOnly/TimeOnly support to include DataTable as structured parameter (#2258) commit 4e6853e2dd61be2d0cde181c4c85e61dd7a2d2b5 Author: Erik Ejlskov Jensen Date: Tue Apr 9 20:32:27 2024 +0200 Update Microsoft.Identity dependencies (#2429) commit 1bf025afeb76eef9eddfdddd306241730d1d61af Author: Trayan Zapryanov Date: Mon Apr 8 22:19:37 2024 +0300 Rent byte buffers in SqlSequentialTextReader (#2356) commit 0c46cd7e019fa67465cf9ca6ba63254f3e7ac206 Merge: 294f8666 9811c657 Author: SqlClient Azure DevOps Date: Fri Apr 5 22:04:44 2024 +0000 Merge in 'main' changes commit 9811c657db1cd1ddc270addc9221579df32af6ba Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Apr 5 22:03:34 2024 +0000 eng | Fix production pipeline (#2450) commit 294f8666aebbe713b9d634dbc8b17c2f5617d02d Merge: af118d72 9645c01a Author: SqlClient Azure DevOps Date: Fri Apr 5 22:02:38 2024 +0000 Merge in 'main' changes commit 9645c01a1ef235cb2342a3847f508f5887dc76b7 Author: Benjamin Russell Date: Fri Apr 5 13:37:36 2024 -0500 Add true (#2446) commit bc2a83414804ffe6f21f6778df73cfc6367cd95e Author: Taylor Southwick Date: Thu Apr 4 16:32:45 2024 -0700 Consolidate SSPI context generation to single abstraction (#2255) * Abstract the SSPI context generation This change introduces SSPIContextProvider that can generate payloads for SSPI. Specifically, this change plumbs the current SSPI context generation into this object, while later changes will continue to update the shape to be a more general purpose, public API. commit af118d72e4d60bbe26a824c0dd9de6400d2753f7 Merge: 226b83ec 4778b876 Author: SqlClient Azure DevOps Date: Thu Apr 4 18:48:59 2024 +0000 Merge in 'main' changes commit 226b83ec0f94e2ea00834c0127886ca97a517d2d Author: Davoud Eshtehari Date: Thu Apr 4 16:19:50 2024 +0000 Merged PR 4462: eng | Fix pipeline netfx build change Addressing the failure on [dotnet-sqlclient-Official](https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=84259&view=logs&j=a59e3b7b-7df8-53a3-7568-e4c5ffd2c23d&t=fa94fa55-e846-59ba-ffea-8e9b3df3ad3a) commit 4778b8760dfc83037e259e5f79845b21ac844c7d Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Apr 4 01:02:40 2024 +0000 Moved NuGet.config to the root (#2443) commit 537eba862d6c2a6e8793cbf874515424df2e8bab Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Apr 2 21:06:05 2024 +0000 Doc | update a sample description in SqlConnection (#2440) commit 908f563699989d8d118c5cc3d330e59a45e9428d Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Mon Apr 1 07:47:03 2024 -0700 Fix | Suppress CodeQL warning for usage of deprecated Ssl2. (#2428) commit 740069d657d8e201973fc7b650965a830280abc1 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Mon Apr 1 07:42:04 2024 -0700 Fix | Suppress CodeQL X509RevocationMode warning. (#2432) commit 74084b010eb0c4834476eade199f6e5e0307286b Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Sat Mar 30 03:24:58 2024 +0530 Fixes UdtTestDb creating script (#2421) commit 1594cc5fa02a942346deffb0064313b130758f6a Author: Javad Rahnama Date: Fri Mar 29 14:23:43 2024 -0700 Merge common code base for DBReferenceCollection (#2403) commit 0d455647cdad87d32beea3173eef421bd1a88264 Author: Davoud Eshtehari Date: Thu Mar 28 16:49:55 2024 +0000 Merged PR 4422: Pipeline | Initiate YAML pipelines - A successful sample run can be found with the non-official template [here](https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=82875&view=results) without SDL tools. - There are a few errors reported by code analyzer that need to be addressed as well. - Due to the known issue with APIScan and Onebranch, it's temporarily deactivated. Related work items: #28134 commit 30cd171e0129ccf80bd95add6191687e987bbd4d Author: Javad Rahnama Date: Mon Mar 25 11:57:36 2024 -0700 Change | Convert Netfx to SDK style (#2413) commit bdfa5d8dbe9acfc01d034bc1fe8b73ce8fe28109 Author: Javad Rahnama Date: Mon Mar 25 11:56:49 2024 -0700 Regression | Revert PR #2281 SNIProxy code change (#2395) commit 4e23bf94c566e04a2fa7fb930af05f3d76fb30c8 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Mar 21 10:44:40 2024 -0700 Fix | The SqlConnection.FireInfoMessageEventOnUserErrors when set to true throws an exception (#2399) commit 9056f13a18b82dc2698ad04da905c16ed5d4ed3f Author: Benjamin Russell Date: Tue Mar 12 13:31:06 2024 -0500 Downgrade Xunit, Improve exception handling for Diagnonstic Tests (#2379) **Description**: While doing some investigation into improving the diagnostic tracing tests, I noticed that test failures are logged very non-descriptly by remote executor. To resolve this issue, we have to downgrade xunit to v2.4.2. Here's the rationale for this change: * RemoteExecutor throws `XunitException`s from xunit.assert nuget and uses the `(string, string)` constructor * The `(string, string)` constructor was removed in >=2.5 of xunit.assert   * RemoteExecutor was fixed to inherit from Exception in newer versions, but for us to take this requires upgrading to .net 7 or 8 (which I imagine is a much larger lift) * In order to downgrade xunit.assert, we need to downgrade xunit * In order to downgrade xunit, we also need to downgrade Microsoft.DotNet.XunitExtensions * Without this change, exceptions from RemoteExecutor will fail to construct, masking all errors with "MethodNotFound" Although normally downgrading is bad for security reasons, I believe this to be a safe change since it only affects tests. This PR also makes a bunch of improvements to the `DiagnosticTest`s: * Remove conditional facts when test TDS server is used * Remove try/catch with empty catch block, replace with assert.throws * Ensure that connections are opened before trying test conditions * Document scenarios where test TDS server doesn't obey actual behavior, or where test TDS server cannot be used * Formatting improvements **Testing**: * All tests (that are expected to pass) continue to pass * In a synthetic failure of diagnostic tests, here's the before and after of the error messages: * Before: ``` System.MissingMethodException: Method not found: 'Void Xunit.Sdk.XunitException..ctor(System.String, System.String)'. System.MissingMethodException Method not found: 'Void Xunit.Sdk.XunitException..ctor(System.String, System.String)'. ``` * After: ``` Microsoft.DotNet.RemoteExecutor.RemoteExecutionException: Remote process failed with an unhandled exception. Microsoft.DotNet.RemoteExecutor.RemoteExecutionException Remote process failed with an unhandled exception. Child exception: Xunit.Sdk.FailException: Assert.Fail(): Foo at Microsoft.Data.SqlClient.ManualTesting.Tests.DiagnosticTest.<>c.b__1_0() in C:\Projects\benrr101\sqlclient\src\Microsoft.Data.SqlClient\tests\ManualTests\TracingTests\DiagnosticTest.cs:line 34 ``` * Downgrade xunit for better error logging from remote executor * All but one test improved ... ? * Understanding why test was failing * Add arcade and xunit nugets to .net8+ special versions * Remove xunitextensions version boost (which I spelled wrong anyhow) commit 769b982606bc97fee797d6c061973c28400aa362 Author: Javad Rahnama Date: Wed Mar 6 19:24:54 2024 -0800 Adding CommonSourceRoot variable to Directory.Build.Props (#2392) commit 4e341dcba8e5fe7248f2e3870e355aa78af46a3f Author: Javad Rahnama Date: Wed Mar 6 14:20:33 2024 -0800 Update | updating version props for MDS v6.0.0 (#2382) commit 5376a04adf786735422029e808333d2a3c6d1fef Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Tue Mar 5 09:12:26 2024 -0800 Fix | Fixed SqlBulkCopy.WriteToServer to ensure successful completion of consecutive calls to it. (#2375) commit 2ddf7237328b45a4a5a9d41dc7d7edf4f566ae9b Author: Jihoon Park Date: Mon Mar 4 13:44:09 2024 -0500 Doc | Fix typo in SqlConnectionEncryptOption.xml (#2381) commit ced726a3ee7b955be238267cc6dd7d61971731b4 Author: David Engel Date: Fri Mar 1 13:04:36 2024 -0800 Remove test reference to deprecated ADAL library (#2360) commit 1a009b46c9729080c477882b3ce4c26285964de5 Author: Erik Ejlskov Jensen Date: Fri Mar 1 18:49:25 2024 +0100 Test | Improve test quality of life (#2331) commit 8ef005a2ee67c55b2900bcbe32a931e3de64c556 Author: Benjamin Russell Date: Wed Feb 28 17:38:28 2024 -0600 Build Tweaks for Onboarding (#2366) commit 64bfe506d77e39ab31db5999b64253210907a59b Author: Javad Rahnama Date: Wed Feb 28 10:39:12 2024 -0800 Release Notes 5.2.0 (#2370) commit faf9b95995e6200a980bb6b1980f1d7af9f46cef Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Feb 28 03:17:52 2024 +0000 Fix | ExecuteReaderAsync API xml and ref files (#2373) commit 51ef22cd50eaa26432e6ec589bf70f7b72f5b60a Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Feb 27 22:41:32 2024 +0000 Fix | ExecuteReaderAsync API return type in ref file (#2372) commit e9cab013454b257ef70a004791f28682ac1f8019 Author: SqlClient DevOps Date: Tue Feb 27 20:30:02 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 10c9e17283f7a4f1cfefcb080f9499461cc31d21 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Feb 27 19:41:38 2024 +0000 Fix | Refine documents for GA v5.2 (#2371) commit 94c089e75842909efb2226edc248f41c3776a037 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Mon Feb 26 14:00:09 2024 -0800 Fix | Fix unit test for SPN to include port number with Managed SNI (#2281) commit 5cd9514cf27b78cf74f4d784b63246c5477552f2 Author: Javad Rahnama Date: Mon Feb 26 12:46:16 2024 -0800 Test | Adjust tests to read IsAzureSynapse value from database (#2367) commit 5a98166c6668b2d12e841d1dc9f69d9d2c0cbde2 Author: SqlClient DevOps Date: Thu Feb 22 03:11:15 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 8b1b7a94ab3560c6b78377d85239af71f80b904b Author: Javad Date: Wed Feb 21 13:06:55 2024 -0800 Fix | Removing non-breaking space from links inside some of exception messages. (#2364) commit ed949d5b3dc504e1dc822c07c2c8f14332305b29 Author: Javad Date: Wed Feb 21 10:13:47 2024 -0800 Change | Updating SNI version to 5.2.0 (#2363) commit e3cf59d226675acf7ae9169989ac692aea04f3da Author: SqlClient DevOps Date: Wed Feb 14 03:08:15 2024 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit af7d39d4496c23fa1660c828a84f31680c0079fc Author: Javad Date: Tue Feb 13 13:52:23 2024 -0800 Fix | Addressing typo in exception message (#2357) commit 237f260f600752b69eba05a65582d19f7f02e88d Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Feb 13 17:24:35 2024 +0000 Test | Docker test enhancement (#2345) commit ca5e3e835feff5836a06aff511acf7080ce76f49 Author: Javad Date: Fri Feb 9 20:17:21 2024 -0800 Removing DSA public key from SqlColumnEncryptionProvider to address CodeQL flags. (#2347) commit 91df016175f2b24fd210b641d3e35eb2a708ad27 Author: H. Yeo <138053434+H-Yeo@users.noreply.github.com> Date: Fri Feb 9 15:39:19 2024 -0800 Docs | Update Release Documentation for Contributors (#2351) commit 06632465470be52ab472d4eee9b6028c5cef5422 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Fri Feb 9 10:34:19 2024 -0800 Fix | Mismatch System.Diagnostics.DiagnosticSource between versions.props and nuspec (#2349) commit 507e8dd64d8c6235f81c9c1864013e7ee3f3f100 Author: Javad Date: Fri Feb 2 09:51:59 2024 -0800 AKV Release notes (#2335) commit 4a2522df26abd6b8818b3f765c3745211272b07d Author: Javad Date: Thu Feb 1 14:44:44 2024 -0800 Fix | Adding missing commitID to AKV nuspec (#2334) commit 5e07b2959a5cd07d0f920e0484ad5c549ea29ec9 Author: Javad Date: Wed Jan 31 00:09:16 2024 -0800 Change | Updating AKV dependencies (#2330) * Updating AKV dependencies commit 5d106fe8c543230df8fa2f8dd9db341c89bd196b Author: Javad Date: Mon Jan 29 16:20:53 2024 -0800 Release notes 5.1.5 (#2326) commit 644cabaeab2e78bfa4d33effcc8ecd278cff7722 Author: Javad Date: Mon Jan 29 13:55:53 2024 -0800 removing pdb from nuget's ref folder (#2329) commit 14d7292d9c22040be45a3d9e1f2c135ad013fc60 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jan 26 01:10:59 2024 +0000 Test | Fix test projects package dependencies (#2319) commit 586cf04cf5ee9deaa5c5263ba8e15810840a5587 Author: H. Yeo <138053434+H-Yeo@users.noreply.github.com> Date: Thu Jan 25 11:53:07 2024 -0800 Preview Release Notes 5.2.0-Preview5 (#2316) commit 348738961a88421629308a012fe7c2c3216d9108 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Wed Jan 24 13:02:59 2024 -0800 Fix | Fix driver to not send expired token and refresh token first before sending it. (#2273) commit 9347412583cbf7e25f84fcc9ab5995308224893f Author: Erik Ejlskov Jensen Date: Wed Jan 24 18:56:24 2024 +0100 Update nuspec on .net 6.0 (#2317) commit 7fd34dfeba9c864182d8e9d39830c4d1e1f1607c Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Wed Jan 24 08:47:53 2024 -0800 Enhance project and target files to generate debugging symbol package files (#2137) commit c8b70f1aa0870d0a927a0142735405077ebb11ec Author: Erik Ejlskov Jensen Date: Wed Jan 24 00:57:28 2024 +0100 Enhancement | Add explicit version for major .NET version dependencies (#2303) commit 4ca71d901a0f5d21b47195e0044279c2ac71878c Author: Erik Ejlskov Jensen Date: Tue Jan 23 17:44:57 2024 +0100 Revert "Perf | avoid boxing of SqlGuid in SqlBuffer (#2306)" (#2311) This reverts commit 9602271e20a1983cf4f0edf3fb8e18d8538e112c. commit 838b931809af6c6236a600d559a086cfe1e77593 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jan 19 23:44:26 2024 +0000 Fix | Invalid transaction exception against the connections and distributed transactions (#2301) commit 9602271e20a1983cf4f0edf3fb8e18d8538e112c Author: Evgeny Akhtimirov Date: Fri Jan 19 18:43:41 2024 -0500 Perf | avoid boxing of SqlGuid in SqlBuffer (#2306) commit b460fd098e94af6c12f3b3fdc9bb9dbe67fc2f10 Author: Erik Ejlskov Jensen Date: Fri Jan 19 03:01:28 2024 +0100 Fix | Add missing dependency update for netstandard2.0 (#2305) fixes #2304 commit 900d051965a630aba0c42e61fe9b843a67570d3e Author: panoskj <37297673+panoskj@users.noreply.github.com> Date: Wed Jan 17 21:57:31 2024 +0200 Merge common code bases for TdsParserStateObject.cs (4) (#2254) commit b12b15d6f61d99870e420c169e4a58711ebf9e0c Author: Erik Ejlskov Jensen Date: Sat Jan 13 00:56:22 2024 +0100 Fix | Enable reading AE date as DateOnly (#2275) commit 55aa1eeb620bcbd5f9c10f5305249af74ae3fac1 Author: H. Yeo <138053434+H-Yeo@users.noreply.github.com> Date: Fri Jan 12 13:31:01 2024 -0800 Tests | Fix Tests regarding Concurrency both Sync and Async versions. (#2279) commit eb68e1b52ac6acbce00d29b262ebd4d3140dd1e4 Author: Javad Date: Fri Jan 12 10:00:09 2024 -0800 Add | Adding net8 support (#2230) commit 8663853b4df831f3b52cd14b9ba3f94c2b9cd260 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jan 12 17:28:04 2024 +0000 CVE | Version bump Microsoft.IdentityModel.JsonWebTokens to 6.35.0 (#2290) commit 2e4d1b69793e7ca3d7d9f2bc85206b933808ef3c Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jan 9 21:58:25 2024 +0000 Fix | SQL auth method validation on debug (#2288) commit 84720a74fa640cf9cea7967a3b74d0220d00961b Merge: ee638d4f 5f00e1ce Author: SqlClient Azure DevOps Date: Tue Jan 9 19:30:41 2024 +0000 Merge in 'main' changes commit ee638d4ffd5bcb542998b706c7ba183853a0077e Author: Davoud Eshtehari Date: Mon Jan 8 17:05:13 2024 +0000 Merged PR 4233: Release notes 3.1.5 Add note commit 7cb40938b85cb3901f2c0e30c63da63ee531de1f Author: Davoud Date: Tue Jan 9 10:13:49 2024 -0800 Merged PR 4228: Address encryption downgrade issue commit 5ed0717b46e5901194504a03025ca06cea75eb88 Author: Davoud Eshtehari Date: Tue Jan 9 05:58:04 2024 +0000 Merged PR 4229: Certificate chain validation logic fix Ports PR [#4047](https://dev.azure.com/SqlClientDrivers/ADO.Net/_git/dotnet-sqlclient/pullrequest/4047) commit a1769cda2eac047f6a3a0042d754e6e14e9f8817 Author: Davoud Eshtehari Date: Mon Jan 8 23:02:22 2024 +0000 Merged PR 4236: Release notes 5.1.4 commit ce6526ac9db7c8b14421b0ad1f56752f75df1d8d Author: Davoud Eshtehari Date: Mon Jan 8 18:55:13 2024 +0000 Merged PR 4230: Release notes 5.1.3 commit 665af6cabe6e3bf6be0db7973377a3bd201202a1 Author: Davoud Eshtehari Date: Mon Jan 8 18:49:16 2024 +0000 Merged PR 4234: Release notes 2.1.7 add note commit 81a54d8233f7edf6c060218e162335963bd94faa Author: Davoud Eshtehari Date: Mon Jan 8 18:48:59 2024 +0000 Merged PR 4232: Release notes 4.0.5 Add notes commit 5f00e1ce77b17f548c658b19b31d60f5968f50d2 Author: Sanjam Panda <36253777+saitama951@users.noreply.github.com> Date: Fri Jan 5 02:22:43 2024 +0530 gc collect fix for mono (#2277) commit 5794ab3af5b58e66b2829a1355b692a73210ee9c Author: Javad Date: Fri Dec 15 15:37:03 2023 -0800 Test | Updating xunit version (#2271) commit 04b531bab5ad5c0bdf204d443b6f3da88c2429b9 Author: Javad Date: Tue Dec 12 09:02:50 2023 -0800 Release notes v5.2.0-preview4 (#2263) commit 923cad7d303de222ba0aa3630fbedfac96a71e82 Author: Javad Date: Fri Dec 8 09:56:23 2023 -0800 Update | Adding ActiveDirectoryWorkloadIdentity to ref folder and soring the n… (#2264) commit d18e5c1557c8bbe08b1a876cc137a6c207de5751 Author: Sanjam Panda <36253777+saitama951@users.noreply.github.com> Date: Fri Dec 8 05:46:56 2023 +0530 Support For Big Endian Systems (#2170) commit 59080c8e5eca0b3455aed362ec9ba913b59ef788 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Dec 7 23:38:26 2023 +0000 Fix | Linux SPN port number using named instance and Kerberos authentication does not return port# (#2240) commit 09c9588c760317a3115489c0c9875b951f02610e Author: Javad Date: Thu Dec 7 14:10:04 2023 -0800 Change | Change Azure.Core in M.D.S.AE.AKV (#2261) commit 17590d3c3f393d66717e0680fdb03fb09b0df409 Author: Will Sugarman Date: Thu Dec 7 12:01:19 2023 -0800 Add | Add Workload Identity Support (#2159) commit 4319661269be1fa15d7d2f819079b6840bfe11d3 Author: Javad Date: Wed Dec 6 14:08:32 2023 -0800 Change | Change SNI Version to v5.2.0-preview1 (#2257) commit 420323799b60c3d7b058fcf944eb46d06fcf9a43 Author: David Engel Date: Wed Nov 29 17:44:48 2023 -0800 Fix | Don't validate server certificate when using Authentication option but not encrypting (#2224) commit 1543998220fe81e372b484d48925c648c6a9b3c8 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Nov 29 18:15:09 2023 +0000 Doc | Improve connect retry count for high demand endpoints on Azure (#2233) commit 416afcdf5141d19716b9b94e8f3146998c29b538 Author: panoskj <37297673+panoskj@users.noreply.github.com> Date: Tue Nov 28 22:13:37 2023 +0200 Merge common code bases for TdsParserStateObject.cs (3) (#2168) commit e6109f8d60766bf9b9ed5e323f5bd50e221cb527 Author: Wraith Date: Wed Nov 22 16:57:10 2023 +0000 SqlBatch: Add missing overrides and tests (#2223) commit b02cf417a5e8a35bee3903d8b8229a25c61fb864 Author: Wraith Date: Tue Nov 21 21:13:30 2023 +0000 cache all appcontext switches (#2227) commit 4f7335550ef1c54910575855d199373ce2ee0a44 Author: David Engel Date: Thu Nov 16 15:33:05 2023 -0800 Test Fix | CertificateTests are only designed to run against localhost SQL installs (#2219) commit d30d9d107eca0f11b735a550aa187e57167858c9 Author: Wraith Date: Thu Nov 9 18:47:44 2023 +0000 Add | Feature: SqlBatch api (#1825) commit 7f203dd03875d1167425dcc92619c143e41f9e59 Author: Wraith Date: Tue Nov 7 20:01:46 2023 +0000 Remove duplicated ForceColumnEncryption property check (#2166) commit b3110be60d18e358ad23fa40e9ba9f952aadbca0 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Mon Nov 6 12:39:55 2023 -0800 Test | Fix HNIC tests to support named instance sql servers (#2205) commit 6456d71414347238d4bd519dbfdf1d936ca4cea6 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 31 22:40:24 2023 +0000 [3.1.4] Release notes (#2200) commit d5df671376b3114e8f7adc570b95073b796b6e16 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Tue Oct 31 11:20:17 2023 -0700 Fix | Fixing issue for SQL named Instances in Managed SNI using named pipes. (#2142) commit 5a4feed431149802c8497c2a720b1b721adbfba6 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Oct 30 20:02:40 2023 +0000 [4.0.4] Release notes (#2199) commit e719601a69070ca0f94f44b3345936603380826f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Oct 26 17:50:21 2023 +0000 [5.1.2] Release notes (#2197) commit 6beab6a69477959429f3f5905ca17c286b777113 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Oct 25 01:09:32 2023 +0000 Fix | Support Georgian collation (#2194) commit b86ddf19f992b8c5e6a0ff1b4b43ed37d31b19bf Author: Wraith Date: Wed Oct 25 02:07:19 2023 +0100 move PacketData and list management to shared and reimplement as doubly linked list. (#2164) commit 57d287c1ca0a4750b7421bc7a2a70b09ac71ca05 Author: Javad Date: Mon Oct 23 14:39:55 2023 -0700 Test | Removing internal build of XunitExtensions and using the nuget (#2033) commit 97863e59ad613ba275912bc93f1aef34f0ee0014 Author: Javad Date: Mon Oct 23 10:46:15 2023 -0700 Fix | Upgrade dependencies versions (#2189) commit b7167c02255a4785a400037f89060b3d275c53d3 Author: Daniel Marbach Date: Fri Oct 20 19:59:52 2023 +0000 Ports Fix deadlock in transaction (#1242) to .NET (#2161) commit 85ba241aaa0750089c1409a98220d88ef3e14146 Author: Viktor Hofer Date: Fri Oct 20 19:43:30 2023 +0200 Remove stale dependencies from SqlClient (#2186) commit 55eb1305bdf958767611b9a506d4ac4b94b8bb63 Author: JJ <103335846+computerscienceiscool@users.noreply.github.com> Date: Thu Oct 19 14:56:28 2023 -0700 Update README.md (#2185) Removed a double word commit 9e0d8b7095e051a6146904ed34738fb3497ceb62 Author: Wraith Date: Wed Sep 27 05:10:00 2023 +0100 deprioritize altmetadata and altrow tokens and annotate them as deprecated (#2165) commit 111033e65625c435295cea500508a13e00a3d764 Author: Wraith Date: Wed Sep 20 19:18:19 2023 +0100 move stateObj snapshot to a new class in shared (#2157) commit c1984b822f8d31794cd8c85245cc6d7bd1059526 Author: David Engel Date: Fri Sep 15 14:14:15 2023 -0700 Doc | Move attestation protocol remark to the correct place (#2153) commit cc5f05a8e18d188bfa49adb51f6df2e4f5533e48 Author: Wraith Date: Fri Sep 15 17:31:18 2023 +0100 Merge TDSParserStateObject.StateSnapshot state flags (#2132) commit 816a7d3dc8ae2f9c6a691d133723a73b54e5e628 Author: Javad Date: Thu Sep 14 12:36:32 2023 -0700 SDL | Changing ReadXml to a more secure overload. (#2147) commit 7b2e2fc9f002e8b270894595f5f92670670053d7 Author: Javad Date: Wed Sep 13 11:24:06 2023 -0700 Test | Fixing MARS manual tests on some debug field's names and some minor changes (#2145) commit 1e3cbfc77a5a688d2a3cb70f2c71c44691eb48d5 Author: Wraith Date: Wed Sep 13 17:21:55 2023 +0100 Merge TDSParserStateObject.StateSnapshot creation and clearing (#2144) commit 93d4398fbd2ac7aa3f031f8f8fdb908255e45316 Author: Javad Date: Mon Sep 11 10:47:16 2023 -0700 [Build-TSA] | Adding template to tsaoptions (#2143) commit 0b8680c1cd2057f81b5b5aa26972367bf407a7d4 Author: emidah <33547378+emidah@users.noreply.github.com> Date: Fri Sep 8 19:48:51 2023 +0300 Fix access violation when using Express user instances (#2101) commit 74cad69885c95cfc05f73401fc11afdf59cf96e3 Author: SqlClient DevOps Date: Wed Sep 6 02:11:00 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit f384d4a25d5c8bb23e8033cc9eec365e5b385cb5 Author: SqlClient DevOps Date: Tue Sep 5 02:10:38 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 51072d3c7fa3e4ec8d120de0d287ab807df21e4f Author: SqlClient DevOps Date: Sun Sep 3 02:08:25 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 4888f90662a5036bf05b0ecb445dd04c8ef0c727 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Sat Sep 2 16:05:38 2023 +0000 Fix | LocalDb and managed SNI (#2129) commit 04415954e991cb998d7d8fa6d9db656f674cc1e6 Author: Javad Date: Sat Sep 2 09:04:59 2023 -0700 Update | Update SSL certificate error messages (#2060) commit c17240d6d28488a03292b7f70ce278a14518985e Author: Javad Date: Tue Aug 29 11:56:30 2023 -0700 Build | Enable CodeQL with TSA (#2139) commit 552791b4b97ddeb417e438390fe1cbac4487f608 Author: David Engel Date: Thu Aug 24 11:51:11 2023 -0700 Doc|Add AccessToken remark (#2130) commit a1ef97360971218b339955b13afd3d8413f90981 Author: Javad Date: Tue Aug 22 20:54:05 2023 -0700 Remove empty statement (#2136) commit 591d929eca247eb064c7540ced2039444c21cf3d Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Aug 22 11:34:30 2023 -0700 Dev | Improved connection timeout (#2098) commit 3185ce235b1d01da51bddc98415a77983e54defb Author: Wraith Date: Mon Aug 21 22:36:27 2023 +0100 move snapshot plpdata to shared (#2126) commit 610a2c2b60e99781f8eb9050119c8e0271409703 Author: SqlClient DevOps Date: Sun Aug 20 02:10:33 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit c7cefee758f02cf0127f448e41e5c2f02022a062 Author: SqlClient DevOps Date: Fri Aug 18 02:11:32 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 8b55bc098db5a1e5cafe99fff63c6d54fa78d1d6 Author: SqlClient DevOps Date: Thu Aug 17 02:09:56 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 3202a3c5a8523ab5d18469564bf52b8a1fd21519 Author: Wraith Date: Thu Aug 17 00:39:21 2023 +0100 Merge TDSParserStateObject.StateSnapshot (#2122) * change TDSParserStateObject filenames so that they are visible and distinct in both projects * move identical StateSnapshot members to shared stateobject file commit 359c4ba15ffbb23c8ea6adce8876adfa496bea1a Author: Wraith Date: Tue Aug 15 23:34:26 2023 +0100 make array rental return after TryReadPlpUnicodeChars unconditional (#2121) commit 80905bd38267cb6e4a1bea32482dab7509dc7b95 Author: Erik Ejlskov Jensen Date: Wed Aug 16 00:34:15 2023 +0200 Skip UDT query on Azure SQL Edge (#2099) fixes #2086 commit 3c83f6c0dc222e17c737522ae4a2d67f3d83f4a9 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Aug 14 17:58:50 2023 -0700 Update SNI version (#2123) commit f1ba91deb0e5ee2cef4867f4e65af1674975cc94 Author: Davoud Date: Mon Aug 14 15:54:30 2023 -0700 Revert "[Scheduled Run] Localized resource files from OneLocBuild" This reverts commit 2d0146ea1b9f3a4d3373427ba7d684d7309de191. commit 2d0146ea1b9f3a4d3373427ba7d684d7309de191 Author: SqlClient DevOps Date: Mon Aug 14 22:33:43 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 96c56fb062b383074984a2e4438337cc5cf548ad Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Mon Aug 14 12:23:44 2023 -0700 Consolidation of localization (#2110) commit b82b1eb73c55c2befc6c59680c81f3d2ed3c7d26 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Fri Aug 11 09:13:44 2023 -0700 Update docs to include note about existing issues with Async APIs (#2118) commit 930133e2205d8f79a09b565faa005eae8256f69f Author: Wraith Date: Wed Aug 9 21:49:49 2023 +0100 Simplify internal async callback code (#2091) commit a709006541a1169f861ea2c3c6aeb5596cd1c286 Author: David Engel Date: Fri Jul 21 14:03:09 2023 -0700 Minor changes to release notes (#2097) commit 4c1b111ac935cdf8cf0323aaffd59eac5f63d192 Author: David Engel Date: Fri Jul 21 10:11:00 2023 -0700 Fix .NET and .NET standard file version (#2093) commit ceaf8ec92216e582b96fb7305c6a8f18da880f4f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jul 20 15:12:08 2023 -0700 Release Notes v5.2 preview 3 (#2094) commit 73143070366c2ab1a314604fe1df01181637102b Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Jul 20 10:30:00 2023 -0700 Fix | Take out the ignoreSniOpenTimeout in open connection (#2067) commit 9ac8cc8f7cad7e01c2dd41bd5779e0fc687ff368 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jul 19 12:38:30 2023 -0700 Test | Fix TdsParserStateObjectHelper debug mode (#2090) commit 3607fe2cc314d02d13f51126387e388c045519bc Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jul 17 12:10:51 2023 -0700 Remove redundant TdsParserSafeHandles.cs (#2088) commit 554fd2e9f1ba0676ae83825c7237165c93785c5f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jul 12 15:11:18 2023 -0700 Fix retry with SqlDataAdapter.Fill(SqlDataTable) on .NET Framework (#2084) commit ed0c3a3c7bbc2f1925607eb2fba70a24e136389b Author: Andrii Kurdiumov Date: Wed Jul 12 06:07:48 2023 +0600 Fix bunch of annontations (#1959) commit 3cb9730a848c919c765036d48cb79440030f3df5 Author: David Engel Date: Thu Jul 6 18:17:52 2023 -0700 Support SuperSocketNetLib registry option for Encrypt on NetCore Windows (#2047) commit 1aa9af6a6bc5679867fadd1832e34183bc795954 Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Thu Jul 6 15:24:51 2023 -0700 Fix | Adding type convertor support for SqlConnectionEncryptOption (#2057) commit ae9dada2a0b368ac6739eed6b955ac7b0d3c04cf Author: David Engel Date: Thu Jul 6 15:09:50 2023 -0700 Code Merge | TdsParserStateObject alignment (#2073) * Code Merge: Bring TdsParserStateObject closer together between netcore and netfx * Address feedback and remove excessive trace entry commit a924df3df7b17bcb1747914338f32a43ab550979 Author: SqlClient DevOps Date: Sat Jul 1 02:11:10 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 7700db0630534a4f9fdb45eb95929b37d63cdb30 Author: David Engel Date: Fri Jun 30 12:49:16 2023 -0700 Fix Kerberos kinit command execution (#2076) commit aa2d36a6f3233d29fff0a5c39f0ba11d8536f9f9 Author: SqlClient DevOps Date: Fri Jun 30 02:12:04 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 6fbb337e08f766cd32b92b2528a7aa56449398a5 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jun 29 13:17:02 2023 -0700 Dev | Add support of the new authentication API with SSPI token on Managed SNI (#2063) commit 20ab3b1610aac926d4695ec8a8a90e9b3c76515b Author: Aris Rellegue <134557572+arellegue@users.noreply.github.com> Date: Wed Jun 28 14:41:50 2023 -0700 Fix th-TH culture info issue on Managed SNI (#2066) commit bcba97cea81a916ea529da9b0d310cb088e7f099 Author: SqlClient DevOps Date: Wed Jun 28 02:10:55 2023 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 3ffc4f678379b637e24170d0ae5c05e053879908 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jun 27 14:33:17 2023 -0700 Code Health | Improve TdsParser (#2071) commit 3b45ee75be4852b7e6aba097192db8df3b7d0852 Author: Javad Date: Tue Jun 27 13:22:44 2023 -0700 Code Health | Enforcing Ordinal for StringComparison (#2068) commit 8fad4a4ffc3733aeede95e33b5c7c3887d9fce61 Author: Christopher Scott Date: Tue Jun 27 13:58:48 2023 -0500 API | AccessTokenCallback support (#1260) commit 2b31810ce69b88d707450e2059ee8fbde63f774f Author: David Engel Date: Mon Jun 12 11:42:41 2023 -0700 Fix | SqlDataSourceEnumeratorTest correct ConditionalFact (#2058) Skip test if SQLBrowser is missing or not running. commit 244a340a46cea7c8511bcfa3e92dd266cfa36cd3 Author: Javad Date: Thu Jun 8 17:36:24 2023 -0700 Release notes - 5.2.0-preview2 (#2056) commit 153c36d5ec0fc7d1db73960b63aa41f92ce3fbc7 Author: Javad Date: Thu Jun 8 09:54:23 2023 -0700 Change | updating Microsoft.Identity.Client version in nuspec from 4.47.2 to 4.53.0 (#2055) commit e3787ffb8bc28128ecc0352271fbed75968180a2 Author: Javad Date: Thu Jun 8 09:29:49 2023 -0700 Test | Replacing try/catch with xUnit Throws. (#2054) commit 288a70c7d3c3ff8d15409668a830ccae47d9f17f Author: Wraith Date: Tue Jun 6 23:42:09 2023 +0100 Add net8 compatibility (#1934) commit 9ec1f21d7c1124ace72b8ac05766f2306a9495d6 Author: azerios <93074569+azerios@users.noreply.github.com> Date: Mon Jun 5 19:31:38 2023 +0200 Update Microsoft.Identity.Client package version (#2031) commit de6390f5a3ec35b7d0acb0e7252ab02a4162580e Author: David Engel Date: Fri Jun 2 10:22:40 2023 -0700 Fix | Minor fixes to support different test environments (#2045) * Test Fixes: - Set correct condition on AE tests that require an available key store (Cert Store on Windows, else AKV) - ServerSPN test should get FQDN of target, not local machine - Instance name test shouldn't try to connect via IP if using integrated security in the context of a remote domain-based connection (Kerberos fails) commit f478be5bf3597f5c0f0940ac471c6b481c38416f Author: Evgeny Gorbovoy Date: Sat May 13 04:20:37 2023 +0530 SqlClient-826 Missed synchronization (#1029) commit 4cd43be549c51686f4cc42bd8b4e43a07872fc40 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu May 11 18:37:17 2023 -0700 Test | Disable TestUdtSchemaMetadata for NetFx (#2011) commit 91694d820177b3c775c1a966a736983a0fb0611d Author: Wraith Date: Thu May 4 02:09:28 2023 +0100 Add RowsCopied64 property, refs, and docs (#2004) commit cbdf41c2275289c4adb54109aa61f347032ffcef Author: Javad Date: Wed May 3 14:38:14 2023 -0700 Adding support for net 7.0 (#1981) commit bc0a1a6bc2aa0f6a5a69c8ebf9fce69224c3742d Author: Wraith Date: Wed May 3 21:00:49 2023 +0100 Code Health | Cleanup `SNIMARSConnection` (#1985) commit 997bf383e9ed801d2d0ecff9cca6aa201ef57119 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Wed May 3 12:58:29 2023 -0700 Add | Use Minimum Login Timeout as 1 sec in .NET Core and enable behavior by default (#2012) commit 472318138104e4ed254f60f6182680ab961c1b8b Author: Javad Date: Tue May 2 14:38:24 2023 -0700 Test | Address failure on Kerberos tests for class 20 exceptions (#2010) commit 5d5ac7ded10df75afa906a576ad6b061617ad904 Author: Javad Date: Thu Apr 27 19:03:40 2023 -0700 Fix | Adding non-string support to SqlConnectionStringBuilder property indexer (#2018) commit 141aa41433a550dcb9e51fbae73adcd01cb446c2 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Apr 27 14:35:01 2023 -0700 Release notes v2.1.6 (#2023) commit 4657311f9b3f308233bd8682d462351e35bc333e Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Apr 21 10:48:45 2023 -0700 Documentation | Release Notes 5.2.0-preview1 (#2009) commit 9a44ffaefd195ebfe8a4b99bab375a5ee68d9628 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Apr 20 12:16:50 2023 -0700 Release notes v4.0.3 (#2007) commit 4a91443169935799700fd424a36bd63265409556 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Wed Apr 19 11:09:16 2023 -0700 Fix Transient fault handling issue with OpenAsync (#1983) commit 938b166b011330d69b0121807e8a90f114556ffa Author: David Engel Date: Tue Apr 18 15:57:48 2023 -0700 Fix | AE enclave retry logic not working for async queries (#1988) commit ac8244a49f1b45b579b2a5e3727244051a87b6c3 Author: Wraith Date: Tue Apr 18 17:01:59 2023 +0100 Perf: add allocation free path for close notifications when task state is setup correctly (#1198) commit a6e7e0d9e17da424dcc9e5c50d1b593bcbf87fb2 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Mon Apr 17 12:52:44 2023 -0700 Fix activity correlator to continue using same GUID for current thread activity (#1997) commit 4d8f980434e6c144048f73ff5fe63da05f179395 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Apr 14 16:13:02 2023 -0700 Test | Disable SqlConnectionReliabilityTest.ConcurrentExecution test (#1998) commit 47024205494e1eef2fb78fda82798b556971af72 Author: Wraith Date: Mon Apr 10 06:00:35 2023 +0100 stop creating parameter prefixed names unless we really need the string (#1829) commit a5ad8382a390ea599740bd3ab51b19601bbd92e0 Author: David Engel Date: Tue Apr 4 08:57:26 2023 -0700 Update NuGet package description (#1973) Make the description clear that it is a replacement for SDS and is the latest library for SQL connectivity. commit 4e323a0740e4adff86c077cc8ab657392e295ab6 Author: Matt Johnson-Pint Date: Mon Apr 3 12:41:29 2023 -0700 Enable SqlDiagnosticListener on .NET Standard (#1931) commit b534f157be32663f9cc55a0268354e75f9adf5ce Author: Javad Date: Mon Apr 3 10:19:32 2023 -0700 Fix | Addressing the excepted behavior when error class is greater than 20 on retry connecting (#1953) commit 7550d411c257acb91dee8f7b116d53d5f9c138a8 Author: Javad Date: Mon Apr 3 09:47:03 2023 -0700 Fix | Dropping reference to Microsoft.Win32.Registry in netcore. (#1974) commit a9c2dbab9937df0586023168b6720d857d7c11a0 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Fri Mar 31 18:02:51 2023 -0400 Release notes 5.0.2 (#1979) commit 102ebb7877b43977136b058ba7f8adf52f61d073 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Tue Mar 28 18:30:46 2023 -0400 Release notes v5.1.1 (#1970) commit c5abb85900edbcb321ea872ab81dc6872a95de7e Author: Erik Ejlskov Jensen Date: Mon Mar 27 22:16:42 2023 +0200 Docs | Fix version order of README (#1969) commit 82353f819f6fecd020df421ae2fba3fe0aba0ad0 Author: Javad Date: Fri Mar 24 16:26:51 2023 -0700 Fix | Addressing failure on providing correct error message when symmetric key decryption fails using Always Encrypted. (#1948) commit 23ca8e75effa2b5e5b3dc81b6b72e2819bd4657f Author: Wraith Date: Fri Mar 24 19:31:41 2023 +0000 Remove linq (#1949) commit 0c0ae3777fc2bf5643e5cd40c2f0f92521168948 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Thu Mar 23 13:15:28 2023 -0400 Fix | TransactionScope connection issue when Enlist is enable, Pooling is disabled and network connection type is Redirect (#1960) commit 1bcdb235e3952331698cfa2d45402a627122b357 Author: Andrii Kurdiumov Date: Tue Mar 21 22:44:45 2023 +0600 Replace calls to `Method.GetCurrentMethod().Name` with `nameof()` (#1943) commit 3e52e42dbea85a721cca9c74d62d09af16b169cb Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Mon Mar 20 23:47:59 2023 -0400 Fix | TDS RPC error on large queries in SqlCommand.ExecuteReaderAsync (#1936) commit d9ab5a90387b9f7b94a818b8cafec5932160549f Author: David Engel Date: Tue Mar 14 13:05:01 2023 -0700 Fix | Throttling of token requests by calling AcquireTokenSilent (#1925) * Address throttling of token requests by calling AcquireTokenSilent in Integrated/Password flows when the account is already cached. Addresses issue #1915 Co-authored-by: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit 289a655c9c6fab15c5d479ace70cbb6b17d47742 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Mar 10 15:27:05 2023 -0800 Release Notes M.D.S v3.1.3 (#1951) commit c927caecb161e22a82e40d72937af6912f7376b3 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Mar 10 12:54:34 2023 -0800 Fix Linux code coverage result in Build proj (#1950) commit 73c6b2ff3ef3b55431cf187e72d5de918caccf76 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Fri Mar 3 11:20:14 2023 -0800 Update Notice (#1938) commit 85edec97efb8ee50d6d6103087390ad81e24e108 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Wed Feb 22 11:29:16 2023 -0800 Chore | Upgrade Azure Identity from 1.7.0 to 1.8.0 (#1921) commit a4f18ca2403598518c3b7aae9715d6722bf692da Author: Wraith Date: Sat Feb 11 08:39:48 2023 +0000 enhance invariant mode checks (#1917) commit 6db45d445fb0e6cd7b1ebb53b9b14251c32b8d0c Author: Wraith Date: Fri Feb 10 20:18:00 2023 +0000 Add and use TryReadChars method (#1544) commit 5ff68eb7505894ea65d8f93f5d2133d43e4c4143 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Feb 3 12:37:15 2023 -0800 Update 3.1.2.md commit 327d3cc37b81fc1b62b4f20444cab1363199e2bb Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Feb 3 12:10:12 2023 -0800 Release Notes M.D.S v3.1.2 (#1916) Release Notes M.D.S v3.1.2 #1916 commit 32e53641935fc7e6187f6a310b859f334616ddad Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jan 31 20:09:31 2023 -0800 Tests | Improve project reference batch file (#1892) commit e4bf520caf01e786efbea5cf8629160bba02bded Author: Wraith Date: Wed Feb 1 04:06:31 2023 +0000 Add array rental capability in TryReadPlpUnicodeChars (#1866) commit 1d7e01d1ea4daac757ca594c3c2ed7e513f565ea Author: Erik Ejlskov Jensen Date: Wed Feb 1 05:05:57 2023 +0100 Verifies support for SqlHierarchyId and Spatial for .NET Core (#1848) commit 518869e249af65abbfda2dcb3d60c094b86f14cc Author: Wraith Date: Mon Jan 30 21:24:22 2023 +0000 Fix NullReferenceException in GetBytesAsync (#1906) commit ee4ba7e24d81a1ed2f26c4ef2bb3a8f9f92063a0 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jan 26 17:26:02 2023 -0800 Tests | Update manual test run logs (#1904) commit 0156df230c4426be535ad6af32ac7d16188377d1 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Thu Jan 19 16:43:00 2023 -0500 Release notes v5.1.0 (#1893) commit 8156ff9939647a091611e9687719c3e8e8918605 Author: madelson <1269046+madelson@users.noreply.github.com> Date: Wed Jan 18 15:03:38 2023 -0500 Update docs for RowsCopied property (#1872) commit 8cb5913c2f42e250a927ff2b113ce23cd2118dde Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jan 18 11:56:40 2023 -0800 Tests | Skip unsupported platform x86 test and bump up Microsoft.NET.Test.Sdk version (#1890) commit 080e9e64257288a90bd7f7e18b44a07f1f8dfd3b Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Wed Jan 18 14:56:32 2023 -0500 docs | Update description for SqlBulkCopy.EnableStreaming (#1886) commit 8e9f3c02746a94a6cbac1722cf4b45a3857b01ba Author: Javad Date: Mon Jan 16 16:09:49 2023 -0800 Test | Fix managed instance TVP test source file (#1878) commit 35a029f11e98311fa7c884e4d9eb8716ba38e4b0 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Mon Jan 16 10:31:10 2023 -0800 Update SNI Version to 5.1.0 (#1889) commit 070ec72512ac8716601bbbe6be417be807aa54cf Author: Theodore Tsirpanis Date: Fri Jan 13 20:04:28 2023 +0200 Remove redundant NuGet package references. (#1849) commit af0a3763f81d34add64ea63386ac0120a9b36e17 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jan 11 11:29:31 2023 -0800 Test | Skip unsupported tests on Synapse (#1884) commit c585669feb392654a7cda35b14fc507c622deec4 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jan 11 10:49:22 2023 -0800 Fix | Add thread safety with transient error list on configurable retry logic (#1882) commit f0464896b59ec8c05e62a9f5bc2a5eb9463756e7 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jan 6 14:30:04 2023 -0800 adding Azure pipeline status badge. commit 97fc436224726c74e09edb597fd78c5cdd5d9f34 Author: Javad Date: Thu Jan 5 21:34:26 2023 -0800 commit (#1879) commit f0f2cbc54c6f8690d3e9cd87d3d7cb05c7bf0940 Author: Javad Date: Tue Dec 20 14:27:22 2022 -0800 Test | Change makecert to powershell (#1861) commit 064c835b6bd5edbd103c9435ea9a3ff5bc1f6f2f Author: Shay Rojansky Date: Tue Dec 20 22:07:09 2022 +0100 Release connection lock before signaling SinglePhaseCommit completion (#1801) commit ce70de95874e7b2358bee338e9f2f25843b9a52d Author: David Engel Date: Fri Dec 16 10:25:12 2022 -0800 Fix DAC connections to localhost in managed SNI (#1865) commit b3cfdbbbf9f126f2d0447feb97ae592f19d1b498 Author: Javad Date: Fri Dec 9 09:33:59 2022 -0800 adding correct built in constant (#1867) commit 22eb6c7a8e91c09de04b0f916d1b2151d57de8a9 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Dec 1 10:45:12 2022 -0800 Improved build project (#1850) commit 03f305389139eff2dfc2c67ad3b564a9f1dd3325 Author: Javad Date: Mon Nov 21 09:57:42 2022 -0800 Test | Fix akvtest issues (#1842) commit c765d838aad6dd6c384c12f55ab777ac75fdf0e8 Author: SqlClient DevOps Date: Tue Nov 15 03:11:02 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 54e9b30acf03a97a2157e560514e72316b25dc44 Author: SqlClient DevOps Date: Sun Nov 13 03:09:31 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit d745d571d7c1189c2af60f11f3af71dc700c115d Author: SqlClient DevOps Date: Sat Nov 12 03:23:57 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 6511535fe27c52590ef40ec254a7eea93f1f2f3d Author: SqlClient DevOps Date: Fri Nov 11 03:14:25 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit db73b4b71c58529801df4e8ab07c8cc25e8277a5 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Thu Nov 10 16:10:04 2022 -0800 Release notes v5.1.0-preview2 (#1832) commit f0f36f2170e458cdfb0af45938c81bdcd4ee5c75 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Thu Nov 10 11:42:06 2022 -0800 TDS8 Add Server Certificate Support (#1822) commit 2a54bc5c8b6a1f94b089b06d5017c5d4142791dc Author: SqlClient DevOps Date: Thu Nov 10 03:08:49 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit e316a68734878f9929d9835df621bc50ba25b108 Author: panoskj <37297673+panoskj@users.noreply.github.com> Date: Thu Nov 10 04:23:38 2022 +0200 Merge common code bases for TdsParserStateObject.cs (#1520) commit 1bb1890b6812199a13d611f5cc8b9e5bcb630feb Author: David Engel Date: Wed Nov 9 17:59:57 2022 -0800 Experimental: Add ARM64 support when targeting .NET Framework (#1828) commit 9876329e5f8d46afeaeb6cf1c12ede623e12339e Author: David Engel Date: Wed Nov 9 14:24:59 2022 -0800 SUPPORT doc tweak (#1830) commit f4568ce68da21db3fe88c0e72e1287368aaa1dc8 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Nov 8 09:30:48 2022 -0800 Update native SNI version (#1831) commit 760510ce231e5ecd1a4bd1dc616fabd4c7073090 Author: Wraith Date: Thu Nov 3 20:54:27 2022 +0000 Add | Adding disposable stack temp ref struct and use (#1818) commit f6841855c976a7b3cc713c67bec23f9226a17671 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Nov 3 10:58:57 2022 -0700 Revert excluding unsupported protocols (#1824) commit 1c03b1d0a1424ac0190568f0f71091f521ca27c7 Author: Erik Ejlskov Jensen Date: Thu Nov 3 17:52:01 2022 +0100 Add support for DateOnly and TimeOnly (SqlParameter value and GetFieldValue(Async) ) (#1813) commit 708cf3a2503886c4fa3b2d3d804fdf8c5df79193 Author: Javad Date: Wed Nov 2 16:03:58 2022 -0700 Test | Removing all net5 references from the driver (#1823) commit 146c34ead598ac8d97c410a1120dca8f8c6f1604 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Tue Nov 1 17:28:43 2022 -0700 TDS8 - Enable retrieval of TLS 1.3 SSL Protocol from SNI on .NET Core (#1821) commit fe403ffc0d05ba790469a91d8dac2a7b481d5d5e Author: Wraith Date: Wed Nov 2 00:23:13 2022 +0000 Port SqlParameter changes from netcore to netfx (#1812) commit c6821c35c2c4038f4ab74c8da615434c81d682a4 Author: Javad Date: Tue Oct 25 18:28:34 2022 -0700 Test | Fix Mac OS test failures (#1817) commit 20d4c199923c9b4ea2ffd44d9304fcb306c5efb5 Author: Javad Date: Fri Oct 21 23:41:47 2022 -0700 Add | Adding Net6 support and dropping netcoreapp3.1 (#1704) commit f5eb391e71a9fc559163d38093f71e98dc867c56 Author: David Engel Date: Thu Oct 20 10:21:38 2022 -0700 Add link to connection resiliency article (#1808) commit 02daa6fc0b12ee4099aab3419ea31832f5483d4c Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 19 13:22:41 2022 -0700 Release notes v5.1.0-preview1 (#1788) commit 1e9cd3ab0a60f3fb9496184b948de43a7bd7721c Author: Ken Dale Date: Fri Oct 14 12:20:08 2022 -0400 Documentation Fix | Small spelling fix commit f361a67e6304deb192945e14f29ac64646d3d35b Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 11 09:56:54 2022 -0700 5.0.1 Release notes [main branch] (#1794) Release notes 5.0.1 commit fe8d1c11e4f47886e015b5c1a56adae7ffbac967 Author: Javad Date: Thu Oct 6 07:42:17 2022 -0700 Release | Updating SNI version for 5.1.0-preview1 release (#1787) commit c68dd0ee2233fd839e330fe4d6a2683889d2d991 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 5 12:43:30 2022 -0700 Merge to shared - TdsParserSessionPool (#1595) commit 1cda34531e660b8a16759c88b6c06ab53a07d7c1 Author: Wraith Date: Wed Oct 5 19:56:25 2022 +0100 Convert ExecuteNonQueryAsync to use async context object (#1692) commit eb1b92285152ea36533dc506a0ba82ea6fb7248b Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 5 11:33:45 2022 -0700 Merge to shared - SqlInternalConnection (#1598) commit ac7c1a4a6bc18fdc4892118a2d07211f990c6286 Author: Lawrence Cheung <31262254+lcheunglci@users.noreply.github.com> Date: Tue Oct 4 17:45:22 2022 -0700 Merge to shared - TdsParserSafeHandles (#1604) commit a4974d448c42c29ee56d5295540eb5a81886d006 Author: Wraith Date: Wed Oct 5 01:21:04 2022 +0100 Port lazy initialize hidden column map to netfx (#1443) commit 0eeb135774f90645183e3be5e98a370c260c5925 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Tue Oct 4 14:11:21 2022 -0700 Add missing HostNameInCertificate property in NetFx Ref (#1776) commit 871c0d2d7ce93048dc8b9d325f6c84731117a991 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Tue Oct 4 14:11:02 2022 -0700 Fixes ReadAsync() behavior to register Cancellation token action before streaming results (#1781) commit 81055cf4b48f36a48199c7569e9308fc5be96b7c Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Tue Oct 4 09:44:26 2022 -0700 Fix async deadlock issue when sending attention fails due to network failure (#1766) commit f2517d46cd1b0d98624e87bc6317e4e4f28e3e83 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 4 09:43:28 2022 -0700 Fix | NRE on assigning null to SqlConnectionStringBuilder.Encrypt (#1778) commit f62ac3bcf393d94cbd26aaf335a4611c5df357dc Author: sorensenmatias Date: Tue Sep 27 20:38:46 2022 +0200 For failed connection requests in ConnectionPool in case of PoolBlockingPeriod not enabled, ensure stacktrace of the exception is not swallowed (#1768) commit 50ec923cec1d768ac1e4753ad484edc5c5fe6914 Author: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Tue Sep 27 09:58:04 2022 -0700 Make SqlConnectionEncryptOption string parser public (#1771) * Make SqlConnectionEncryptOption string parser public * Address feedback * Fix non-nullables * Fix docs * Apply suggestions from code review Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit 4dafe91c793436ac43a933b646b3b24dc2477143 Author: David Engel Date: Mon Sep 26 12:42:33 2022 -0700 Doc | Porting guide addition (#1769) commit 7d348eb0c985b34ce5b76a9330c57bc1015c93ff Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Sep 13 15:52:23 2022 -0700 4.1.1 release notes [main branch] (#1759) commit 2c3eb19bd71e8e33ef6ecc39bbee76f5b59fc6e5 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Sep 13 13:13:17 2022 -0700 4.0.2 release notes [main branch] (#1756) commit 4cb2b6728b0895de339d643390c0a01ff84e3d80 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Aug 31 16:01:17 2022 -0700 Fix | Default UTF8 collation conflict (#1739) commit 81231cef246fa2c28a7371d40fd52c6065ea41bd Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Aug 30 16:26:00 2022 -0700 2.1.5 release notes [main branch] (#1730) commit ceaa33d023c9e80c25744dbe7b9e578ce61d5068 Author: David Engel Date: Tue Aug 30 09:32:09 2022 -0700 [Fix] Hang on infinite timeout and managed SNI (#1742) * Fix for issue #1733 - hang on infinite timeout Also fix SSRP when DataSource is an IP address commit 2cd34d66888145b53335e2cf02bf1ccde04ce806 Author: Javad Date: Thu Aug 25 15:27:11 2022 -0700 Documentation | Improve AAD link and consistency. (#1738) commit bd21d762e2362256aab49866e5ad9797b4a037b4 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Aug 18 17:34:43 2022 -0700 Test | Replacing Binary formatter with DataContractSerializer (#1590) commit 6fdc1f31ea817c93cbe7e067728b467e2ed9ed30 Author: Javad Date: Fri Aug 12 14:16:04 2022 -0700 3.1.1 release notes for main branch (#1716) Co-authored-by: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> commit 914caf559fe4569426496d6b73f8e80f0ba69a40 Author: Erik Ejlskov Jensen Date: Fri Aug 12 21:20:01 2022 +0200 Add more SqlConnectionEncryptOption tests (#1705) commit 555975452572dcf606394d058ed8d8b4e0367b02 Author: David Engel Date: Fri Aug 12 12:07:50 2022 -0700 Add breaking change note (#1703) commit a8986114389956347ac522f9bda2bd68405a6ed1 Author: David Engel Date: Tue Aug 9 11:39:52 2022 -0700 Add link to SQL Server TDS 8 doc (#1694) commit 8640bfb7d9610c25a7c40fafca7afe25b70caf50 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Fri Aug 5 13:05:56 2022 -0700 Release notes for v5.0.0 (#1681) commit 73875c9ecb0b9d48262b52da25114cafcc403deb Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Aug 4 12:30:20 2022 -0700 Addressing HostNameInCertificate changes in native SNI (#1680) commit 53b9f0aa38bb6150132f3a71fc85ddcf0a167497 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Aug 4 09:41:20 2022 -0700 Newtonsoft.Json update to 13.0.1 for ManualTesting, XUnitExtensions (#1683) * SNI Update SNI Update * Revert "SNI Update" This reverts commit 7aebf45737714e5fa2b1e8e7d3193b78f0d27da3. * Adding Newtonsoft json to test proj commit 8364c8ae817c1c6fcbef7c95724e630a035e1b54 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Aug 4 09:41:02 2022 -0700 Doc | Address the monikor versions conflict (#1685) * Update * Update doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml Co-authored-by: David Engel * fix * fix * Apply suggestions from code review Co-authored-by: David Engel * fix Co-authored-by: David Engel commit e42e3887e8b9d7797835bf0a489e655110759a5d Author: Wraith Date: Thu Aug 4 02:33:56 2022 +0100 fix null binary rowversion and add test coverage (#1688) commit 7a8a5dea048911de7d6ade80dd30fa8ecf40e7cc Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Aug 3 14:53:41 2022 -0700 Add condition to the Azure_AccessToken_UserManagedIdentityTest and Azure_AccessToken_SystemManagedIdentityTest to require IsAccessTokenSetup (#1691) Add extra access token condition to Azure_AccessToken_UserManagedIdentityTestand Azure_AccessToken_SystemManagedIdentityTest commit cabe7138873fe4c9644110c21f4325071cbfa0d7 Author: SqlClient DevOps Date: Sat Jul 30 02:05:45 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 6bfdb6381bd3bfa1b69bb4c1a17bff39f66dabf3 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Tue Jul 26 11:24:54 2022 -0700 Add check if the FailOverPartner key exists first before retrieving its value from the SqlConnectionString (#1614) commit 13b8c7d5f05a4c251be337ffedbca511a31bade2 Author: Javad Date: Tue Jul 26 18:24:20 2022 +0000 Change | Using default system protocols for TDS8 on Managed code (#1678) commit 620cf46be3ac07eb59cc73fe59bd6df6200bda1c Author: Javad Date: Sat Jul 23 02:13:10 2022 +0000 Adding TDS8 version for TDSLogin (#1657) commit ff013e45e5a7750c57c60dda74ccbf05c5b9b7c8 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jul 21 17:04:00 2022 -0700 Doc | Fix a link (#1677) commit 3a2b5fb17e8c90c4fcc4e3824cc213c813adecf9 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Jul 21 11:58:13 2022 -0700 Changing Encoding UTF7 to ASCII for SSRP Broadcast (#1671) commit 54998bb8e0fc39e831bd6701ec457d3e27267c32 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jul 21 11:08:54 2022 -0700 Doc | Configurable Retry Logic doesn't support CommandBehavior.CloseConnection (#1673) commit 98acbf108903b7539d70a4068cc9bdd0fa5966fa Author: David Engel Date: Wed Jul 20 11:13:51 2022 -0700 Fix inconsistency between netcore and netfx (#1672) commit 4df39297ff0d0c1bb7f1da05b134f42cdf073a78 Author: Dhurata Jahiu <101433552+DhurataJ@users.noreply.github.com> Date: Wed Jul 20 13:39:07 2022 -0400 [BrokenLinksH2] Fix path in link (#1676) commit e9101ca9c4127117e665b6fe18c71e2a010fd2b1 Author: David Engel Date: Tue Jul 19 09:10:37 2022 -0700 Remove union overlay design and use reflection in SqlTypeWorkarounds (#1647) * Remove union overlay design and use reflection in SqlTypeWorkarounds * Leave union overlay method intact for netcore commit 86827411e4964804a56ecb717094b51d38e6de35 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Fri Jul 15 13:56:16 2022 -0700 Chore | Upgrade IdentityModel dependencies (#1646) commit 4e3aa5eaa913ab4bda1b7b15d00d904b752da331 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jun 30 16:21:54 2022 -0700 Doc | Fix typo (#1666) commit 1f2902b6b8823ee11fdcc7d054c9b59d7ef4a330 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jun 28 14:30:55 2022 -0700 Doc | Fix xml doc (#1661) commit 2cf43354994c838a985d87fae0d2d6027fbe528c Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jun 27 17:57:44 2022 -0700 Test | Skip unsupported tests with Azure Synapse (#1658) commit f1172a6ca87013323c41abd8775cdb61e4ec52ae Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jun 22 11:04:44 2022 -0700 Fix Microsoft.SqlServer.Server netcore project package reference (#1654) commit d8fcedebc2c0112eaec43bd35feab5530fd9f1d0 Author: David Engel Date: Fri Jun 17 16:05:38 2022 -0700 Another 5.0 preview 3 note (#1649) commit 88b0f243e1bb4482a7b764014e17315fc868f02f Author: David Engel Date: Fri Jun 17 15:37:39 2022 -0700 5.0 preview 3 release notes adjustments (#1648) * 5.0 preview 3 release notes adjustments * Update CHANGELOG.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit 4fb0bca23392b3a206c5780f44a55106661387cb Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Jun 17 12:40:08 2022 -0700 Release notes v5.0.0-preview3 (#1645) Release Notes for M.D.S 5.0.0-preview3 commit 25126575ccf1b5383bad6a46d599069a2679385c Author: SqlClient DevOps Date: Thu Jun 16 22:16:09 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 04db1a40a95726af8567b7596653e20acdd7f19a Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jun 16 13:27:47 2022 -0700 Feature | Add support server SPN option (#1607) commit 748fd36803ce50cdc6a3b029d6c12ebb1a15d5d4 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Jun 15 15:39:01 2022 -0700 Update SNI Version 5.0.0-Preview3 (#1644) SNI 5.0.0-preview3.22165.1 commit 778f86e54f5b88e7e063b2bc345b75800c874f60 Author: Javad Date: Wed Jun 15 13:44:12 2022 -0700 Feature | Adding TDS 8 support (#1608) commit 10e373a571b67bb9b5a1a8191fb8bdd8f631b273 Author: SqlClient DevOps Date: Wed Jun 15 16:52:28 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit d600f8921e193c72b37d728b8a76cee2cfece9ac Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jun 13 17:10:56 2022 -0700 Feature | Project Microsoft.SqlServer.Server separation phase 2 (MDS consumes MSS using netcore) (#1585) commit 73eba15c548e5b89ad6b5147d8d5c7c8412baa02 Author: David Engel Date: Mon Jun 13 17:08:01 2022 -0700 Strings for localization (#1641) * Strings for localization * Adding initial English strings to be translated commit c9fc8680882586a994b352de26bba650a51123be Author: SqlClient DevOps Date: Sat Jun 11 03:11:19 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 966fc6eab94e193aa893d960dfc8dc0dd2236029 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Jun 9 15:26:07 2022 -0700 Move to Shared - SqlTransaction (#1353) commit 3082ae55013425dc09604a1960fb48ebd8f844fb Author: David Engel Date: Thu Jun 9 13:17:38 2022 -0700 Add support for aliases on netcore+Windows (#1588) * Add support for aliases on netcore+Windows * Add test * Revert spacing * Better partition Windows/Unix code * Add missing files * Fix attempt * Re-work new test * Applying review suggestions * Deduplicate code Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit c45c50776608bf88523d6d378234f050c0cc0058 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jun 9 10:51:40 2022 -0700 Fix | Add StructuredTypeMembers in ref files (#1639) commit 51f46a4eb66d08de0b1442399c05f5914378444e Author: SqlClient DevOps Date: Wed Jun 8 03:09:02 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 155a535609f5d200389a57d2c9e493541070cbd0 Author: Wraith Date: Tue Jun 7 19:52:57 2022 +0100 Rework `TdsParserStateObjectManaged` with nullable annotations (#1555) commit 2b364f478cb544d2367a61e616bae255d85bc60d Author: Wraith Date: Tue Jun 7 19:49:38 2022 +0100 fix naming, order and formatting for diagnostics (#1637) commit 031afe853c6a00b6093254b675954b7eabdbf75e Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jun 7 10:10:46 2022 -0700 Fix | Handle NRE on Azure federated authentication (#1625) commit 9b1996a768afad0f29ae692189ffef8b91770907 Author: David Engel Date: Fri Jun 3 13:45:09 2022 -0700 Fixing transaction doc samples (#1632) BeginTransaction - no parameters BeginTransaction2 - named transaction/savepoint BeginTransaction3 - named transaction/savepoint + isolation level commit d0c5c26accf3266efaf29434129dfc90e2d1ed47 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Jun 3 11:44:42 2022 -0700 Moved to Shared - SqlParameter (#1354) commit 73aa0da943962c31c887f5638816dc68b00f19a4 Author: Wraith Date: Tue May 31 17:19:10 2022 +0100 Combine: Move SqlEnvChange to shared and sync usage (#1525) commit a43348b4044c952cdb65d87a951b90375087cc44 Author: David Engel Date: Mon May 30 14:59:06 2022 -0700 Automatically adjust the default ConnectRetryCount if targeting OnDemand endpoint (#1626) commit 2cfac4d415990e8618b0c3e26d426ce9fe4665dc Author: Javad Date: Mon May 30 13:47:53 2022 -0700 Fix CommandText length for stored procedures (#1484) commit a46f61262a15b9f6998c841318f9851e4e1d2efc Author: Michael Wilson <57151586+tf-micwil@users.noreply.github.com> Date: Fri May 27 20:45:04 2022 -0400 Fix populating of TYPE_SCHEMA column in StructuredTypeMembers metadata (#1500) commit 845902c729b273e2f36337b0affc402e0500ceb7 Author: Javad Date: Thu May 26 18:52:17 2022 -0700 FIX | db_id returns null on Azure SQL Database. (#1294) * db_id() issue. * closed reader. * commit * review comments Co-authored-by: David Engel commit e1fcf5bf029be64062e5a3a50162f3374d1c45b3 Author: Chris B Date: Fri May 27 02:41:42 2022 +0200 Send retained transaction descriptor in MARS TDS header for .NET Core and .NET 5+ (#1623) (#1624) commit b0d0b2af4def7f6fc5caac0131956712fe10eed6 Author: David Engel Date: Thu May 26 09:59:27 2022 -0700 Improve error reporting from SqlDbManager (#1617) commit 2c568306c9ba41bfe2534ff3355c7d2563e4c1e0 Author: Wraith Date: Thu May 26 17:58:57 2022 +0100 Simplify managed SNI receive callback use (#1186) commit caaecea987ea24c41df1adb312e10ffc5b0d02d9 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu May 26 09:58:14 2022 -0700 Chore | upgrade Azure Identity from 1.5.0 to 1.6.0 (#1611) commit c2e7e3e40f8c2c576f4d18a7a64b4e51766997e3 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed May 25 11:32:34 2022 -0700 Test | Improve instance name test (#1618) commit dfa62a1746e4702e57f67380772a2e126088c8fb Author: David Engel Date: Mon May 16 15:50:51 2022 -0700 Parallelize SSRP requests when MSF is specified (#1578) commit 3072fd6093d378c74dcd69d4cdfc3ebe13a95b52 Author: Mohsen Rajabi Date: Sat Apr 30 01:13:10 2022 +0430 improvement regex (#1548) commit 3a41288f2b67307a1f816761deb73785247c85c9 Author: David Engel Date: Fri Apr 29 13:41:08 2022 -0700 Add missing User synonym in connection strings (#1584) commit 11f6ad0eabf263583a151d3904ac1052c173b0d2 Author: Wraith Date: Fri Apr 29 21:40:52 2022 +0100 fix forced on sni log entries (#1580) commit c1edc1a4548ed77e12fce0a38732e6091808ce4a Author: Johnny Pham Date: Fri Apr 29 10:48:35 2022 -0700 Update SqlConnection.xml (#1586) commit f9204415fe80d0a8a599651edd2a2abe6a684b07 Author: Christian Gräfe Date: Thu Apr 28 01:55:18 2022 +0200 Update 5.0.md (#1583) Version number corrected commit a6625b3a94ca2ffaec7e1baac2ef7f2e2402669b Author: SqlClient DevOps Date: Sun Apr 10 03:12:21 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit a9a6e5e003036ee6a0f1b9fea5a72174f7f4d0c7 Author: SqlClient DevOps Date: Sat Apr 9 03:21:42 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit e1ee48eded4d3c2b53b0f289045ecbb61167cc11 Author: SqlClient DevOps Date: Thu Apr 7 03:09:51 2022 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 1e42990ff79de8559bb0a7a1db31c9986b6bdcbc Author: Johnny Pham Date: Wed Apr 6 17:58:19 2022 -0700 Release notes v5.0.0-preview2 (#1577) commit a0af3061b769fb8b7d5da4dfdb6bda6997b1bf64 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Apr 6 14:41:12 2022 -0700 DEV | Drop support for Net461 and add support for Net462 (#1574) commit 9583088b44e513732fe6319de9e502fa259353ea Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Apr 6 14:40:29 2022 -0700 Move to Shared SqlSequentialTextReader (#1343) commit 66ffa40464ede205d7b41600c8b27e4c884178b8 Author: Johnny Pham Date: Wed Apr 6 14:38:37 2022 -0700 Move to Shared for TdsEnums.cs (#1483) commit 02cd5f47b204d321aaab7bfd524fe7f67471ea0a Author: Lawrence <31262254+lcheunglci@users.noreply.github.com> Date: Wed Apr 6 13:59:32 2022 -0700 Move to Shared for SqlDependencyUtils.cs (#1370) * Merge netfx to netcore for SqlDependencyUtils.cs * Move SqlDependencyUtils.cs, SqlDependencyUtils.AppDomain.cs, SqlDependencyUtils.AssemblyLoadContext.cs to shared src and update reference in the csprojs * Update file to conform with coding style cleaning up IDE1006, IDE0090, IDE0044, IDE0008, and IDE0003 commit 1499d4b7f5a5a8b4b2e3b3e5583901c117d2a0f6 Author: Lawrence <31262254+lcheunglci@users.noreply.github.com> Date: Wed Apr 6 13:59:11 2022 -0700 Merge to Shared for DbConnectionPoolGroup (#1371) * Merge netfx to netcore for DbConnectionPoolGroup.cs * Move the netcore version DbConnectionPoolGroup.cs to shared src and update references in the csproj and reorder the DbConnectionPool entries to be alphabetical * Update file to conform with coding style cleaning up IDE0008, IDE0003 and IDE0090 commit 9c752e6b17846c9b86606d53d42849beca1bb868 Author: Johnny Pham Date: Wed Apr 6 13:42:16 2022 -0700 Replace AlwaysEncryptedAttestationException with SqlException (#1515) commit 43562ce57eb809e5dbe1ed778714205949daf4b0 Author: Javad Date: Wed Apr 6 13:11:23 2022 -0700 Upgrade AzureIdentity version (#1462) commit 187c3e29ec38808d55f820bd0471dc7bf60faa02 Author: Wraith Date: Wed Apr 6 01:46:47 2022 +0100 Share SqlBuffer (#1438) commit e597ff4e03c795b5ed6a96b30b00892b0765283d Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Apr 5 15:58:24 2022 -0700 Fix | Skip the CRL check during authenticaiton (#1559) Co-authored-by: Davoud Eshtehari commit 90653f7e2ddc6cb13c9635ff0c5414d5e95d5956 Author: Javad Date: Tue Apr 5 12:33:24 2022 -0700 Improvment | Remove unnecessary netcoreapp2.1 constant from the driver (#1542) commit 77ad58b1e0177ec282ba0e1a4e27a362fc330caf Author: David Engel Date: Wed Mar 30 11:45:14 2022 -0700 3.1 release notes (#1566) commit f2c9ca20884754f553ff5f790fea248aa76c9805 Author: Johnny Pham Date: Tue Mar 29 14:38:16 2022 -0700 Update DataTestUtility.cs (#1567) commit 266569ada36e9f67d547fc0cafc2a562bf6c9bdd Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Mon Mar 28 11:54:50 2022 -0700 Update SNI Version 5.0.0-Preview2 (#1563) commit 38dfaaa8167024e8e00632569f1c2e3db5f47ef1 Author: Johnny Pham Date: Fri Mar 25 15:01:13 2022 -0700 Update CspProviderExt.cs (#1551) commit 76f458ce3f1927bcb44db6e495f7dfafb8802fb3 Author: Johnny Pham Date: Thu Mar 24 14:00:21 2022 -0700 Update Microsoft.Data.SqlClient.ManualTesting.Tests.csproj (#1558) commit d966a81ee04a2283854cc8465871fe8ce76398e0 Author: Erik Ejlskov Jensen Date: Fri Mar 18 19:03:29 2022 +0100 Improve error message when adding wrong type to SqlParameterCollection (#1547) commit 865ac03ea9e0d362b38429348b8694ec960ae3a2 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Mar 10 16:18:53 2022 -0800 Fix | Improved DSEnumerator's test and fixed string format (#1541) commit 5cebfbee1749c649c8352c11554554bc4cde85e1 Author: Javad Date: Thu Mar 10 11:30:17 2022 -0800 5.0.0-preview1 release notes (#1538) commit 0a0c1607160963c2b15e5812bc38a1717279c2f4 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Mar 9 15:44:01 2022 -0800 Chore - Alphabetically sort the compiled files in the netfx and netcore csprojs (#1364) commit 7fba93ba2bd4ed27e46ddc8d5f718230c69ff690 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Mar 9 14:01:05 2022 -0800 Feature | Add SqlDataSourceEnumerator (#1430) commit 517b162aa8e718c2fd0453efbf950c0c98292316 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Mar 9 13:54:04 2022 -0800 Move to shared -SqlInternalTransaction (#1346) Move to shared -SqlInternalTransaction(code merge efforts) commit f2635caf75f69df1256edf3dd18b954672651b3e Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Mar 9 13:23:07 2022 -0800 Move to shared-Sqlstream (#1337) Move to shared-Sqlstream (code merges effort) commit 1a7cbb231f827bfe0d09645f2cedd6ee4b92ed42 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Mar 9 12:33:36 2022 -0800 Move to Shared-MetadataUtilsSmi (#1339) Move to Shared-MetadataUtilsSmi (code merges effort) commit 43296f98a56016f3faab7c5b2836887cde2e951b Author: Mohsen Rajabi Date: Wed Mar 9 19:31:58 2022 +0330 Improvement | Dispose RandomNumberGenerator object (#1478) commit fd1daa64eef003ef4d70876b5616fdca4ae0b3c3 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Tue Mar 8 09:18:15 2022 -0800 Update SNI version (#1537) commit 49d513f9380920852a44a59d72624a921ce75987 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Feb 25 18:25:49 2022 -0800 Add Microsoft.SqlServer.Server documentation (#1503) commit a359a18bbcef01782aa6a628faa74c2b1c57ee63 Author: Wraith Date: Fri Feb 25 22:20:46 2022 +0000 Clean: Modernize style in ValueUtilsSmi (#1351) commit bddbeda176e10a1a915d892fb33947b83bb094e9 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Feb 18 16:41:22 2022 -0800 Fix | Improve code coverage using net fx (#1518) commit 35d9ffe10c80a83649240d09a3a47eb68a906e9c Author: Wraith Date: Fri Feb 11 20:42:20 2022 +0000 Perf: use manual masking on state flags to avoid boxing (#1197) commit 5158ada2132cc70df34125c4a9bdd731812dd3ce Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Feb 10 20:33:58 2022 -0800 Test | Seperate LocalDB and NamedPipe LocalDB Tests (#1499) commit 17ea3d116d83e2cf6cc621d63f9e8e451b517f99 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Feb 10 10:54:06 2022 -0800 Test | Updated Unit Tests for FileStream (#1458) commit f7f02d8a87291678042a0c23f1c7ee702cb5a307 Author: David Engel Date: Wed Feb 9 10:36:51 2022 -0800 Doc | Add detail to Attestation Protocol (#1505) commit c00e10ef22dd05fff262b6df2be95d073747388b Author: David Engel Date: Thu Feb 3 17:40:12 2022 -0800 Doc | Update PersistSecurityInfo Summary (#1492) commit fe1e2a209f572239c41d03a608a78627bb90f762 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Mon Jan 31 16:40:54 2022 -0800 Release Notes 4.1.0 (#1488) * 4.1.0 release notes 4.1.0 release notes * added PR number added PR number * Update CHANGELOG.md Co-authored-by: Johnny Pham * Update release-notes/4.1/4.1.0.md Co-authored-by: Johnny Pham * Added the PR number Added the PR number * added README.md added README.md * added example for None attestation connection string added example for None attestation connection string * added readmore section added readmore section * review comment review comment * Update release-notes/4.1/4.1.0.md Co-authored-by: Johnny Pham * Update CHANGELOG.md * review comments * review comments * Apply suggestions from code review * Update release-notes/4.1/4.1.0.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * Update release-notes/4.1/4.1.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * Update release-notes/4.1/README.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Co-authored-by: Johnny Pham Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit b9dd969d586982252b910df57cf0b2d8cdf6ea9b Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jan 28 13:12:52 2022 -0800 [MSqlServerServer] | Release Note v1.0 (#1491) commit 54ab5aef2e1b74c0971a00711fecb003b624efdf Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Jan 26 14:55:04 2022 -0800 Feature | Project Microsoft.SqlServer.Server separation phase 1 (MDS consumes MSS using netfx) (#1435) commit 8202268230bda8b0898ca9f1ce0ec9ca8393c9f8 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Tue Jan 25 16:21:19 2022 -0800 Use Buffer.BlockCopy with byte[] (#1366) commit 3b945eeeacb349f3a33f13c3c929dbab11f49267 Author: Johnny Pham Date: Mon Jan 24 15:04:10 2022 -0800 Add new Attestation Protocol "None" - phase 2 (#1425) commit c9d59d8426b987e10af245df11853d10bb6a1d0d Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Jan 19 12:04:46 2022 -0800 Move into Shared for SqlError.cs (#1322) * Merge netfx into netcore for SqlError.cs * Move the netcore version of SqlError.cs to shared src and update references in the csprojs * Fix compiler error due to relative path change to the documentation * Add the serializable attribute to the class and change the auto properties back to fields for serializations and included a serialization test for SqlError * Fix compiler error in netfx due to missed merge * Add an ifdef to SqlErrorTest because binary serialization is obsolete in NET5 to suppress a test compiler error * Update src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlErrorTest.cs Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit 6cf9a93fa97f1d682a9308b455e67caae8f74a20 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jan 17 12:56:59 2022 -0800 Edit | 4.0.1 update release note (#1477) commit 35cb3e46a5e0def9b8e37fa53dbdd9477895c06a Author: Javad Date: Fri Jan 14 17:13:07 2022 -0800 4.0.1 Release notes (#1474) commit c805b8f00ce605696a0bf541bdfffb7dc9dcb18e Author: Javad Date: Fri Jan 14 13:45:41 2022 -0800 Fix | SqlLocalDB instance pipename issue with Encryption (#1433) commit 2f502970a6fe1fbc76e2aaaf5b672fc7a2328cde Author: Wraith Date: Fri Jan 14 20:01:57 2022 +0000 find replace windows doc paths to unix (#1442) commit fc2ea583c0eeb3adc6a2788438cf88eea0fa5529 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Jan 14 10:57:24 2022 -0800 Test | Improve MaxPoolWaitForConnectionTest waiting time (#1465) commit d74556b3a809f26deab4188b0bd9450eb7c72d38 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jan 13 18:24:28 2022 -0800 Fix intermittent timed out exception (#1463) commit d9efa74a8934476236e531e12536b56e8e6cc2d1 Author: Johnny Pham Date: Thu Jan 13 16:46:48 2022 -0800 Test | Add lock when using ClearSqlConnectionGlobalProvidersk (#1461) commit 330de7652a41d9610d63ff0a752a37ff80e900f4 Author: Johnny Pham Date: Wed Jan 12 12:07:25 2022 -0800 change to ConcurrentDictionary (#1451) commit 9a4e332bd2f362317d23e5287a85659eb2798c1a Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Tue Jan 11 18:45:03 2022 -0800 Move to Shared - SqlSer.cs (#1313) commit 1ad4af3c5fef0b16ce9355ca77150d142534c9db Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Jan 11 15:22:06 2022 -0800 Suppress TLS security warning with Encrypt=false by new AppContext switch (#1457) commit fe38d260daea80f9412bd984147c96c6746735cf Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jan 10 15:07:24 2022 -0800 fix (#1453) commit 5a53a3615eeda6b5ba3f53a08d853188ca445017 Author: Javad Date: Mon Jan 10 11:17:27 2022 -0800 Shim gss api on Linux to delay loading libgssapi_krb5.so (#1411) commit ee57e926fac2f87c955c3a86328cbbbcf06f508e Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jan 6 16:00:29 2022 -0800 Fix | SqlConnectionStringBuilder doc (#1432) commit 4f27e88c959583ca3af36dd7322ed59ee2f37786 Author: Wraith Date: Wed Jan 5 18:56:52 2022 +0000 Change SQL Server codenames to version names (#1439) commit b84aab93bcf7423e71bc2eb4e65d67a592036921 Author: Johnny Pham Date: Wed Jan 5 09:47:02 2022 -0800 Rename SimulatorEnclaveProvider - "None" attestation protocol, phase 1 (#1419) * rename simulator enclave provider * Update EnclaveDelegate.Crypto.cs * use Array.Empty() * use enum for protocol id fields commit 41b57bb966c225a14d5c086b883d7336735934d8 Author: Wraith Date: Wed Jan 5 02:29:21 2022 +0000 add empty but not null DesignerCategory to prevent subtype element in project file (#1452) commit d4f69fdc1b302a4039a618ae61538a4f98be3b0b Author: Wraith Date: Mon Dec 20 18:56:52 2021 +0000 Style: Suppress new() and using fixers in main library projects (#1330) commit c2e0bd1afc37589c87dc978de75aa85ca624bc7c Author: Wraith Date: Sat Dec 18 01:50:35 2021 +0000 Perf | Port Guid and primitive type data reader optimizations (#1348) commit 10bb7f31bd17b91d7ca212701c0c9844a91778ea Author: David Engel Date: Thu Dec 16 15:27:12 2021 -0800 Adjust language about metadata order (#1431) commit c56baaabb641de6dd595203f78a2e93b65ac2317 Author: Johnny Pham Date: Mon Nov 29 14:52:08 2021 -0800 Update TcpDefaultForAzureTest.cs (#1410) commit 78676d6167bc15b4f9127c12146442a18a70eae7 Author: Johnny Pham Date: Wed Nov 24 14:00:05 2021 -0800 Update DataStreamTest.cs (#1405) commit 43f78803e334cde4030bafd7b9324f6ab308f0fd Author: Johnny Pham Date: Wed Nov 24 13:36:26 2021 -0800 Include derived types of ArgumentException in DataStreamTest when reading past end of stream (#1404) * Update DataStreamTest.cs * Update DataStreamTest.cs * Update src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit 6c6c76ca4f4ead9a2ce4bdd8466aecb6b4003c34 Author: Johnny Pham Date: Mon Nov 22 16:51:02 2021 -0800 Update obsolete api calls in .NET 6 (#1401) * update obsolete api calls * remove RNGCryptoServiceProvider commit 1e763819e98f6dee403404880579bcd8a042cc67 Author: Johnny Pham Date: Mon Nov 22 10:28:08 2021 -0800 Update v4.0.0 release notes (#1399) * Update 4.0.0.md * Update CHANGELOG.md commit 768b58b3d077d4811d6992acd7542fa1aea73b97 Author: Johnny Pham Date: Thu Nov 18 17:51:28 2021 -0800 Release notes v4.0.0 (#1389) * 4.0 release notes * Update 4.0.0.md * Update 4.0.0.md * Update 4.0.0.md * Update README.md * Update 4.0.0.md * Update release-notes/4.0/4.0.0.md Co-authored-by: David Engel * Update release-notes/4.0/4.0.0.md Co-authored-by: David Engel * add changes * Update release-notes/4.0/4.0.0.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * add SqlClientLogger changes * typos Co-authored-by: David Engel Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> commit c1b86b8d253d0a285cafd18a972b889c0e2dbde9 Author: Johnny Pham Date: Thu Nov 18 15:44:11 2021 -0800 update SqlClientLogger in refs (#1392) commit bca1b17b60077844372bc017cdbf4147d27148f1 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Nov 18 14:00:14 2021 -0800 new sni version (#1391) commit fe79b3db43e6c31a8e84d0fff33f38fdcdb1b594 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Nov 18 09:57:00 2021 -0800 Test - Add tests for code coverage part2 (#1384) * Add tests for SqlCommandBuilder * Add missing throw for invalid SqlDbType for a SqlMetaData constructor * Add more ctor tests for SqlMetaData * Add tests to SqlMetaData and increase code coverage to 78% * Add tests to SqlMetaData to increase code coverge to 92.8% * Add tests to SqlDependency to increase code coverage to 75% * Update src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlMetaDataTest.cs Co-authored-by: Cheena Malhotra * remove unnecessary asserts Co-authored-by: Cheena Malhotra Co-authored-by: Johnny Pham commit d1deadd8e1075df8f4be99bd8ed4878f792b97d7 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Nov 17 15:23:04 2021 -0800 Test - Add tests for code coverage part 1 (#1377) commit 397279b74818fe9af1076cb1549031e3331c20c5 Author: Johnny Pham Date: Wed Nov 17 15:22:24 2021 -0800 Avoid throwing exception when receiving invalid SqlNotificationInfo value (#1378) commit d853ac4f924eedfe3ef556ddb25fb114c65aa43c Author: Cheena Malhotra Date: Tue Nov 16 16:20:53 2021 -0800 Build script changes for enhanced testing experience (#1382) commit ab8ca769b94b436b9bc566f0487e4d06c6ca600a Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Nov 12 13:55:22 2021 -0800 fix API docs(#1386) commit a5b357f5c76d59d72ed81504777b668d3ed25398 Author: Javad Date: Mon Nov 8 11:26:38 2021 -0800 Test | Code syntax improvements for TVP test (#1374) commit 78e8ebcf806adc4cdc3ba0a40da9dafdbb584d84 Author: Johnny Pham Date: Wed Oct 27 10:29:01 2021 -0700 Tests | Split up manual tests into sets (#1373) commit 27c56af560cd8049cf894a3ae6a4686c5b7f6481 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 25 10:11:02 2021 -0700 Tests | Add test to SqlNotificationRequest to address code coverage (#1367) commit 5bf73f1beff2b300eb008c57aa5b7749bb85aed9 Author: SqlClient DevOps Date: Sat Oct 23 03:10:42 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit fc10bbc45191cc87efcc50f50241cfce149a7486 Author: SqlClient DevOps Date: Fri Oct 22 03:08:25 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 4a79cf5af1abd42a3e21410f961bbb10a5904fe5 Author: SqlClient DevOps Date: Thu Oct 21 03:11:05 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 2d445376fb47b4ff3612d631c244e6afbdfa68fd Author: Johnny Pham Date: Wed Oct 20 15:42:42 2021 -0700 Release notes for v4.0.0-preview3 (#1363) * add 4.0.0-preview3 release notes * Update CHANGELOG.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * Update CHANGELOG.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * address feedback * typos * Apply suggestions from code review Co-authored-by: Cheena Malhotra * Update release-notes/4.0/4.0.0-preview3.md Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> * update version number Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Co-authored-by: Cheena Malhotra commit 3c8ef33f2a54be00af201c00859b78dad28a278d Author: Cheena Malhotra Date: Wed Oct 20 12:54:39 2021 -0700 Active Directory Default authentication improvements (#1360) * Active Directory Default improvements * Disable test on Linux * Feedback applied * Update src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs Co-authored-by: Javad * Add configureawaits Co-authored-by: Javad commit aa952236b75d7083a362adb728a3c67e8d00264a Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 20 10:18:40 2021 -0700 Refactor SqlConnectionString.cs (#1359) commit 884c67c2ce0a73fcb51d7a3defcb5055d44b1f9f Author: Cheena Malhotra Date: Tue Oct 19 15:02:38 2021 -0700 Revert mars state machine changes (#1357) commit 2be398002f975930b787e3f91c12869af64cd7b0 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 19 14:13:18 2021 -0700 Tests | Fix event counter test intermittent failure (#1358) commit 6cb4ca20eeaa6b1f05901c1901ab2141d9897cd6 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Tue Oct 19 10:42:40 2021 -0700 Move to Shared SqlSequentialStream (#1345) commit e84845043553d44c1a5585d2d60328303afbfe02 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 18 18:02:26 2021 -0700 Move into Shared for SqlConnectionString.cs (#1329) commit 9fd88b1c320fdcec5d3b6e979a831681af18d595 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Mon Oct 18 17:42:39 2021 -0700 Moved SmiXetterAccessMap to shared src folder (#1310) commit 6c1d000cb1ed1e0fd08ebefa7133f7c5d3d16504 Author: Cheena Malhotra Date: Mon Oct 18 14:22:06 2021 -0700 Revert "Fix Async Cancel (#956)" (#1352) commit 85fbc168cb5e23206932ab9c28ff0f48c7bbe6eb Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 18 13:23:24 2021 -0700 Move into Shared SqlDependencyListener.cs (#1308) commit c3e22e2b3482370cabbfdb173407f3d8b10eb544 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 18 13:10:29 2021 -0700 Move into Shared SqlMetaDataFactory.cs (#1315) commit 87a568b1447b58849b682aaf0f391aa2c52223e6 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Oct 18 12:51:23 2021 -0700 Fix AKV provider package reference condition (#1356) commit c10207ae54574512821f8f2ebf160ebb3d0b0ddb Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 18 12:45:23 2021 -0700 Move into Shared for SqlInfoMessageEvent.cs (#1311) commit 542056a0a615bdc6052fc6c3369e8802a5fb2455 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 18 12:44:42 2021 -0700 Move to Shared for SqlConnectionPoolKey.cs (#1292) commit 99425238c690c84760e498fd43df6357287b0324 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Oct 18 12:44:15 2021 -0700 Merging SqlConnectionStringBuilder code bases (#1349) commit 71aefa589221265e8484aea7739d817f58685a4a Author: Cheena Malhotra Date: Mon Oct 18 12:16:30 2021 -0700 Tests | Address random error on AADPasswordWithWrongPassword test case (#1355) commit c0fd7d26a8aa8ff313942f62fa5f38e39ae8c29b Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Fri Oct 15 15:58:31 2021 -0700 Move to shared - SmiMetaDataProperty (#1320) commit 47ff52789c4b9a683ae54ae9d56626b3ebd7e1c7 Author: Cheena Malhotra Date: Fri Oct 15 12:52:36 2021 -0700 Fix get_ConnectionTimeout property API in SqlAuthenticationParameters (#1336) commit 12fafc20d98726f4161034f7153f222bb094b028 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Fri Oct 15 09:05:52 2021 -0700 Move to Shared for SqlEnums.cs (#1317) Co-authored-by: Erik Ejlskov Jensen Co-authored-by: smichtch commit da1f9ab0764512bd8c233a8776dc85099991197e Author: Wraith Date: Fri Oct 15 07:38:55 2021 +0100 Simplify diagnostic tracing (#1193) commit bc4edc6f5f0dd0e1e3ac0894e7f2de43f8114731 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 14 23:32:26 2021 -0700 Move into Shared for SqlBulkCopyColumnMappingCollection.cs (#1285) commit bc4046fe1dc14151a182684293c34f5964fa7691 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 14 23:07:55 2021 -0700 Move to Shared for SqlDependency.cs (#1299) commit 1dc9647be02081eb866da421fe976c46353bb0a8 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 14 22:51:19 2021 -0700 Move the netcore version of SqlReferenceCollection.cs into share src and updated references in the csprojs and fix compiler error removing internal method with no references (#1303) commit 04cdeff6d26d6180a8464bf25d169d09f62f909b Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 14 21:41:23 2021 -0700 Move to Shared for SqlException.cs (#1300) commit 3a10d55f44531afe54bad6090c021ef4ff0d0393 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Oct 14 15:55:41 2021 -0700 Move to shared - ValueUtilsSmi (#1326) commit 73919cadf0babb2bf24644cd42a78a1cc4a08088 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 14 10:03:00 2021 -0700 Move into Shared SqlNotificationEventArgs.cs (#1314) commit b659f88d867b6e9877d47253a3455be040096473 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Oct 13 16:40:54 2021 -0700 Move to Shared SmiEventSink and SmiEventSinkDefault (#1324) commit d4c8ea08233a9d720d2b45f116c5e0977a1af584 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 13 16:32:02 2021 -0700 Move into Shared SqlErrorCollection.cs (#1305) commit b75dfb51fd1674617ae84e6fea2d39b84f7757a5 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 13 16:31:27 2021 -0700 Move to Shared for SqlConnectionPoolGroupProviderInfo.cs (#1323) commit d8b59b6d895e73e0968de46f260261174a23bba1 Author: smichtch Date: Wed Oct 13 16:30:30 2021 -0700 Fixed ActiveDirectoryAuthenticationProvider constructors. (#1328) commit 7583486f87605ff82dc54eac0355b64e27e62cf3 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 13 13:37:29 2021 -0700 Move into Shared for SqlCommandBuilder.cs (#1284) commit 7305c1cadef433823f30446c50415779c80af229 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Wed Oct 13 12:38:01 2021 -0700 Move to Shared -SqlDataRecord (#1309) commit f88b7e4dcd81b4fccbae565cbcb2e094c7fdf2bd Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Oct 13 10:25:43 2021 -0700 Skip reliability tests on enclave server (#1340) commit 8a7a5f563d5487ef2cc4623429e1da4175552e41 Author: Erik Ejlskov Jensen Date: Wed Oct 13 19:24:15 2021 +0200 Fix broken links (#1341) commit 6c46392d7ae3b06daf9f87eada1b7d9f4494a1d4 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 12 14:01:42 2021 -0700 Merging common code bases DbConnectionStringCommon (#1265) commit 31f566a8aad900a04694cb2a212344c2f356346a Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Oct 12 12:05:20 2021 -0700 Merging common code bases AdapterUtil (#1306) commit d9c2e7c2e8422c334bd08db345c9036c82ac3d79 Author: Parminder Kaur <88398605+Kaur-Parminder@users.noreply.github.com> Date: Thu Oct 7 17:03:40 2021 -0700 Move to shared SmiTypedGetterSetter (#1321) commit 9a7d53ea1651b94783c07f37eaa39cd8f728c02e Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 7 17:02:57 2021 -0700 Move into shared for SqlCachedBuffer.cs (#1280) commit 8476c8eee65324f1b19d08087bbf26e746e9b084 Author: Cheena Malhotra Date: Thu Oct 7 17:02:11 2021 -0700 Attempt to fix test intermittent issues by Including source linking for release build only. (#1325) commit 1493972cd94574303fe118e12548f1f504050d14 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 7 16:15:22 2021 -0700 Move to Shared for SqlDataAdapter.cs (#1295) commit 64befd5f8e6b0a78ee4b6eefa0fc09fa3ec9cb2e Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Thu Oct 7 11:04:24 2021 -0700 Move into shared for DbMetaDataFactory.cs (#1278) commit 08059dd52c74b0cb64323e73bf1446156b51c917 Author: Cheena Malhotra Date: Wed Oct 6 13:46:01 2021 -0700 Fix | Disable encryption when connecting to SQL Local DB (#1312) commit 6af83fcaa849bd25ccc96cc5ba59948cddb456dd Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 6 13:22:23 2021 -0700 Move into Shared for SqlCommandSet.cs (#1286) commit dcad18a5529f0c453c9e3b2ff14a48b9f8404f5a Author: Wraith Date: Wed Oct 6 21:18:51 2021 +0100 Move SqlCollation to shared, make readonly and cache last used (#1202) commit 3d7370989e096bd958ee97100a48bd13c037da9b Author: Wraith Date: Wed Oct 6 21:12:35 2021 +0100 Add GetFieldValue(Async) support for XmlReader, TextReader, Stream (#1019) commit 6ac1e49d6ef9b5c9cf6c88d3f32e6d2c4e820b0c Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Oct 6 13:12:19 2021 -0700 Merging common code bases DBConnectionOptions (#1279) commit a77f2ae9e898738e183eab2e77028566917189ba Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Oct 6 10:14:13 2021 -0700 Move into shared for TimeoutTimer.cs (#1273) commit a226a74c2acd38e31edf71ceb85bdeaa5ebc99a4 Author: Javad Date: Tue Oct 5 13:59:22 2021 -0700 Tests | Adding Kerberos Testing with Integrated Authentication (#1185) commit 2f0a801e1b5c346b47c3d1116ae548e19324ce08 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Tue Oct 5 13:58:29 2021 -0700 Move to Shared for SqlQueryMetadataCache.cs (#1316) commit 84df6f46cc2e85e36fb5ff96559b7cbfe6fdb7cb Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Oct 4 10:44:37 2021 -0700 Move into shared for SQLResource.cs (#1276) commit 0df363dbfc9eface34c0ce96bef4620d849c1deb Author: Wraith Date: Fri Oct 1 23:59:31 2021 +0100 Merge: Generalize pool and move to shared (#1199) commit 647006e7dfc5bdf472d1306b03ca3f4d6b25135a Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Wed Sep 29 15:47:11 2021 -0700 Move to shared SqlClientMetaDataCollectionNames.cs (#1287) commit 57dd66d08f0bcc6177009492f327b159b22549ea Author: David Engel Date: Wed Sep 29 15:37:55 2021 -0700 Incorrect doc default value for Column Encryption Setting (#1302) commit f59d1c7004c864756d990a4bd0b1e12229a2a3c3 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Sep 29 11:12:18 2021 -0700 Merging common code bases StringsHelper (#1288) commit 75fb627818c23458fabd69dadaf578f4e0dd4594 Author: Nadeem Afana Date: Wed Sep 29 13:33:38 2021 -0400 Fixes FormatException when Tracing is enabled (#1291) commit c8c8fe4dde0e28b43e0d1870ca0f5bead869e71f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed Sep 29 10:32:13 2021 -0700 Fix | Remove Visual Studio designer attributes (#1296) commit e66e1b92782423929bd91eb4bfc9affe23ea30ad Author: Cheena Malhotra Date: Tue Sep 28 16:41:25 2021 -0700 Drop .NET Core 2.1 (Out of support) (#1272) commit 5755d56b00ab095a4c49ed3addf841599833ac96 Author: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Mon Sep 27 15:24:22 2021 -0700 Tests | Change the NETFX predefined constants variable in the functional tests to NETFRAMEWORK to keep it consistent with the netfx csproj (#1293) commit c3e72d65518a33035f1ca09115093279ca0c2218 Author: Erik Ejlskov Jensen Date: Tue Sep 28 00:23:04 2021 +0200 Fix typo (#1289) commit 1ca304f5d6fb5a18a4d6f2080a27efd48fefee42 Author: Johnny Pham Date: Mon Sep 27 14:52:13 2021 -0700 Read makecert.exe path from config.json + AdapterTest improvements (#1271) * use makecert path from config.json if provided * use better random names in adapter test * Update Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj * akv nuspec * Update Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec * Update DataTestUtility.cs * add makecert property to update config.default.json and buildguide.md * typo * use DataTestUtility methods to drop database objects * Update BUILDGUIDE.md commit 9daae2401fd18a7cd7e0d5f96ceba36fe7f89751 Author: Javad Date: Fri Sep 24 14:35:46 2021 -0700 Release notes for v3.0.1 (#1281) commit b71b62a139a3fe6e12493133abfc7223c5ee806f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Sep 23 11:40:15 2021 -0700 Test | Fix Event counter test failure using Azure DB (#1277) commit 249b4ea1c7a431010e389eb00f87584f6c5aefeb Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Sep 21 15:01:42 2021 -0700 Release notes v4.0.0-preview2 (#1269) commit 478519bc6dffe11100f8d9fdf30085f35268be1c Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Sep 21 11:15:45 2021 -0700 Include new packages in nuspec file (#1266) commit e653bfea57176431a8af7d9dc2da1c451324bd25 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Sep 20 17:23:03 2021 -0700 Release notes for v2.1.4 (#1268) commit 186188d9f2f64736984edf1a820daedf641cd096 Author: Cheena Malhotra Date: Mon Sep 20 15:57:08 2021 -0700 Fix unknown transaction state issues when promoting delegated transaction (#1216) commit 5cd0f7d47840c62a54e9982f3ccfaccea889c658 Author: Javad Date: Mon Sep 20 15:52:23 2021 -0700 FIX | Adding support for sharedInstances to managed SNI (#1237) commit 96a8b0508eff834b611cbeaec21d2326918e9a5e Author: Johnny Pham Date: Mon Sep 20 12:44:27 2021 -0700 Port connection pool tests from devdiv (#1155) commit a93f86aab3c39d00e8c15ac5be530d25dc8ca068 Author: Javad Date: Fri Sep 17 15:57:59 2021 -0700 Fix | Revert Event source changes on TryBeginExecuteEvent and WriteEndExecuteEvent to address the failure on other MS products. (#1258) commit 831287f7ba016d184703f54e0ccfe40dfa00dca8 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Sep 17 15:53:19 2021 -0700 Remove Configurable Retry Logic safety switch (#1254) commit 576fadb12b45b6703a221379c9173a6736be4374 Author: Wraith Date: Fri Sep 17 23:52:56 2021 +0100 Fix Async Cancel (#956) commit f25e96dc7f3f68e18af4b08d2fc89e5c9f31af69 Author: Cheena Malhotra Date: Fri Sep 17 14:59:25 2021 -0700 Fix | Fix deadlock in transaction (.NET Framework) (#1242) commit 601d9f8d3ee58c4cd70ff4a89347a072e33d21db Author: Cheena Malhotra Date: Fri Sep 17 12:16:04 2021 -0700 Feature | Support for SqlFileStream for .NET Standard 2.0+ on Windows (#1240) commit c9147a63fa22aee43fb7ef6281f70a8308083868 Author: Cheena Malhotra Date: Fri Sep 17 12:15:32 2021 -0700 Cleanup StringsHelper (#1236) commit 2d8207e680c2debc18f451dfc8bbd25b5b54dbe8 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Sep 16 10:36:26 2021 -0700 Fix | Improve decimal conversion from SqlDecimal to .Net Decimal (#1179) commit aea4bbeb95467fa941db6cb270d797dfb229c0ca Author: Johnny Pham Date: Tue Sep 7 21:12:57 2021 -0700 Update ConversionTests.cs (#1251) commit fbfd5d7bbf5bbd929f9d15403156d09d7553514f Author: SqlClient DevOps Date: Fri Aug 27 03:04:01 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 2c5fbdde41f6d2adc9b694e822ec319eb88b3552 Author: SqlClient DevOps Date: Thu Aug 26 03:04:12 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit d484db8c09a5304715386f65bff00c8fc6e48a24 Author: Cheena Malhotra Date: Wed Aug 25 12:38:38 2021 -0700 Update 4.0.0-preview1.md commit 593fe726a956ccebb6c458d9dd5e39c1f57d30fe Author: Javad Date: Wed Aug 25 12:30:48 2021 -0700 Release notes 4.0.0 preview1 (#1222) commit 2b74ca1779116b5875c4df960753049c46f23849 Author: Cheena Malhotra Date: Wed Aug 25 10:00:47 2021 -0700 Fix regression in CancelAsyncConnections test using Native SNI - reproduced locally (#1226) commit 6dde935c5a1887e4ae8d42b8f0b692268b9657e5 Author: SqlClient DevOps Date: Wed Aug 25 03:03:45 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 74ffd8ba1d39b237d1f7c7d89c0b52f35c4c3a79 Author: Cheena Malhotra Date: Tue Aug 24 12:47:08 2021 -0700 Reduce size of AnyOS binaries with required String extracted (#1225) commit 369314da526b7b4e377b801a00a9a2aa7276326d Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Tue Aug 24 12:33:36 2021 -0700 add Cng (#1224) .NET Core 3.1.2 known issue: It should be added manually for ReferenceType = Package. Co-authored-by: Davoud Eshtehari commit 58ec32c1400571665aeaef84077fa45174869955 Author: Cheena Malhotra Date: Tue Aug 24 11:16:11 2021 -0700 File included in wrong location causes heavier "AnyOS" binaries. (#1223) commit 00df61d41a7fc2d18b34ba2762307f7356fdcd8b Author: SqlClient DevOps Date: Tue Aug 24 03:03:51 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 241631a2f0ea0208703b4248ae5ababa687bd2c2 Author: Cheena Malhotra Date: Mon Aug 23 15:21:06 2021 -0700 Perf | Port PR #328 to improve performance in .NET Framework (#1084) commit 5f6478aef9419025bbeb86c02b5883a806c321a1 Author: Cheena Malhotra Date: Mon Aug 23 12:47:07 2021 -0700 Fix Async thread blocking on SqlConnection open for AAD modes (#1213) commit 896c4fc6b63ed9e0c526ff127c8dfaa9faa4fd45 Author: Cheena Malhotra Date: Mon Aug 23 10:41:47 2021 -0700 Include 42108 and 42109 to retriable transient errors list (#1215) * Include 42108 and 42109 to retriable transient errors list * Update tests commit 8b77c4943ba8e76317afd9ef5dc766a85ef87e6e Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Aug 23 10:16:07 2021 -0700 Fix | Exclude unsupported protocols (#1168) commit dab5ca0d034e0318333e7d5b69e0563dfb4d5574 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Aug 23 10:14:53 2021 -0700 Update SNI version (#1221) Co-authored-by: Davoud Eshtehari commit d1ff708949999bd8c02991beec19f3ac6c9540fe Author: Javad Date: Fri Aug 20 15:19:08 2021 -0700 FIX | Add Component Model annotations to SqlConnectionStringBuilder class in netcore's src folder (#1152) commit 8412c78091733785d5430fadd14496ce072cce4e Author: Cheena Malhotra Date: Fri Aug 20 15:17:38 2021 -0700 Fix multiple retry issue on ExecuteScalarAsync + add missing ConfigureAwait calls (#1220) commit e5863e95a2308c493fc28c8914466911b4268e9e Author: Javad Date: Fri Aug 20 15:17:17 2021 -0700 Tests | Improve ConnectivityTest (#1203) commit 16fd7430ec575b98253509a748c538c55b6df56a Author: Javad Date: Fri Aug 20 14:48:20 2021 -0700 Update test error (#1218) commit 131e90751625bf2f199e07f665d6fde414299617 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Aug 20 13:11:27 2021 -0700 Update `Encrypt` property default value to true (#1210) commit 554fe16fe8876bb1f733a5b21f8bd3173751c39a Author: Cheena Malhotra Date: Fri Aug 20 10:35:55 2021 -0700 Activity tracking + Event Source support for AKV Provider (#1174) commit ce5a1f7f98fe66da71a50e62f09985383740c11c Author: Cheena Malhotra Date: Thu Aug 19 09:30:57 2021 -0700 Fix bug with LegacyRowVersionNullBehavior (#1182) commit ffce6d365d60be069883a1584136fa9d82ac56df Author: Cheena Malhotra Date: Wed Aug 18 13:44:44 2021 -0700 Enable PoolBlockingPeriod for .NET Standard + expose GetColumnSchema (#1181) commit 104e9a698cee44c5467bdf2cca457cba88c18a1d Author: Johnny Pham Date: Wed Aug 11 11:40:10 2021 -0700 Tests | Port async MARS tests from devdiv (#1190) commit 83b8421bcbfd8be8d46396fe1c9b4541f4e0700b Author: Wraith Date: Wed Aug 4 21:25:43 2021 +0100 Convert try-finally log scopes to using blocks (#1188) commit df9990c632d49dece2d10900b61d9ebc142e8db9 Author: Johnny Pham Date: Wed Aug 4 13:25:18 2021 -0700 Port bulk copy tests from devdiv (#1177) commit ba2dbfed0e3a080caf9db9ca154ed4479a41cc53 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jul 30 15:02:43 2021 -0700 Reset cached async state on disposing a command (#1128) commit 4e72e437a918d60c1d52e77a4a7a363326573f01 Author: Wraith Date: Thu Jul 29 00:49:59 2021 +0100 Tracing improvements in Managed SNI (#1187) commit 0288d90bf14b2d8d9424ae33bb0449ad3f3959e4 Author: SqlClient DevOps Date: Sat Jul 24 03:03:21 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit ad31bb8cfdbf42b9a191da5a0dd50284e2da493a Author: Wraith Date: Fri Jul 23 19:14:15 2021 +0100 Rework MARSConnection state machine (#933) commit 6a5a670842fe958e7d5f89de194d7604735d2d4f Author: Nate Hitze Date: Fri Jul 23 13:53:24 2021 -0400 Document difference in DateTime vs TimeSpan value for DbType.Time parameter (#1173) commit 9765a4ec95367ca8f06c6bc8fd7557187ae67f9d Author: SqlClient DevOps Date: Fri Jul 23 03:03:55 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 0b235a4e86abbe22465fe49559348a20531944e7 Author: SqlClient DevOps Date: Thu Jul 22 03:04:30 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 7f0e3bb7223302383987c281039b727b3e797369 Author: GitHubPang <61439577+GitHubPang@users.noreply.github.com> Date: Thu Jul 22 01:37:43 2021 +0800 Fix typo in string resources (#1178) commit 68fc25945deed7bf1e2fa45cad8cfe37fee192ce Author: Javad Date: Wed Jul 14 09:55:56 2021 -0700 commit (#1166) commit 23fcd008ef1c227c13f91788d5e8a9df8035baea Author: Johnny Pham Date: Tue Jul 13 14:53:52 2021 -0700 Improve SqlConnectionTest and SqlCommandTest with Assert.Throws (#1159) * update sqlconnectiontest and sqlcommandtest * remove redundant assert commit c9aa89fc7a5df326855f2ea5bbe6425daf378db5 Author: Johnny Pham Date: Tue Jul 13 12:34:36 2021 -0700 Update error code when certificate validation fails in managed SNI (#1130) commit 2325ddd9bb96e170c813999e5032e1df47f923d4 Author: Wraith Date: Tue Jul 13 20:32:28 2021 +0100 Add ValueTask stream overloads on SNI streams and Waits (#902) commit f666c0e4243b1a8899072f2c275c7301df4cd628 Author: Johnny Pham Date: Tue Jul 13 11:50:43 2021 -0700 fix keyword and synonym counts (#1165) commit 05815edefd203560b0fcf3e53ce256edd5150caa Author: SqlClient DevOps Date: Tue Jul 13 03:03:53 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 423eb2a889fed77b02241437bd94125b0f595f08 Author: Cheena Malhotra Date: Mon Jul 12 16:47:59 2021 -0700 Tests | Performance Tests Initial base (#1059) commit ac43fa454813bae45d4caea6b4091b65cd3a7c06 Author: Cheena Malhotra Date: Mon Jul 12 15:23:10 2021 -0700 Tests | Enhance Visual Studio testing experience (#1161) commit ad1e481ac680bf4ade1bbbb5deea6a4c679ade4b Author: SqlClient DevOps Date: Sat Jul 10 03:03:43 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit ae693c38de3bbe76f7fcd4c479b828ecb8a814a2 Author: Johnny Pham Date: Fri Jul 9 18:19:19 2021 -0700 Do not add parameters for sp_describe_parameter_encryption when not provided (#1115) * Update SqlCommand.cs * only execute sp_describe_parameter_encryption if parameters not empty * add test * improve test coverage * only go through parameters if not null * revert previous attempt * Update ApiShould.cs * Update ApiShould.cs commit 4fdd40bdd1ff6000ea1d91e9555b4e5c633a5968 Author: SqlClient DevOps Date: Fri Jul 9 03:03:30 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 34ed3f7496727fb98906d4e793bea9ff0d7c6d86 Author: SqlClient DevOps Date: Thu Jul 8 03:03:51 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit f4d9cdb64dc9e8b3e08a825e33c48d55a22fb5b7 Author: Johnny Pham Date: Wed Jul 7 16:55:36 2021 -0700 Drop Asynchronous Processing connection property + Improve connection string docs (#1148) commit 145b5f54f76a7e7d471eb4ea4959aaffd87ee329 Author: Wraith Date: Thu Jul 8 00:55:15 2021 +0100 Add SqlCommand.DisableOutputParameters Feature (#1041) commit 00cbff1cbe7b711bdde1646f0b158199bec58312 Author: Cédric Luthi Date: Mon Jul 5 23:54:23 2021 +0200 Fix EntryPointNotFoundException in InOutOfProcHelper constructor (#1120) commit 98ea349b0d37d2c5b80f0ebc70e3fe1d66832f31 Author: Wraith Date: Mon Jul 5 22:38:07 2021 +0100 Replace WeakReference with WeakReference (#1141) commit d1bac502ed01175b14bb84844b96d1e2671d3bb9 Author: SqlClient DevOps Date: Wed Jun 30 03:04:08 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 57ee5df2c9d2ecc8a23a76c5c9d63ef44e84b7b3 Author: Johnny Pham Date: Tue Jun 29 10:45:32 2021 -0700 Remove designer attribute from SqlCommand and SqlDataAdapter (#1132) * remove designer attribute * remove designer and toolboxitem attribute from sqldataadapter * remove from refs * remove from netcore refs * add TODOs in netfx refs commit 2999808b50da4d4898bf263fbcdc821df58daf15 Author: SqlClient DevOps Date: Sat Jun 26 03:03:40 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 5f5ca2115e7076dbe25e2aaae018f07985ef8eee Author: Cheena Malhotra Date: Fri Jun 25 13:30:43 2021 -0700 Cleanup S.D.S references (#1139) commit e0fdd53fceca58b2482643ddc1f58f71ad0a25be Author: SqlClient DevOps Date: Fri Jun 25 03:04:06 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit a0a66a7546076f93f6dcfab825516dfcf6076ce8 Author: Wraith Date: Fri Jun 25 01:16:47 2021 +0100 Cleanup SqlDataRecord (#1133) commit 1bbafb9416856c1f3e18de628eda5dcbd47c5f6a Author: Javad Date: Thu Jun 24 16:35:00 2021 -0700 Fix strings.resx (#1136) commit 5c236a20198a229f390372a9e7c82fb17dace294 Author: SqlClient DevOps Date: Thu Jun 24 03:04:05 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 1b79752c142da439290b6be2f4a07f28ed2393d9 Author: Johnny Pham Date: Wed Jun 23 12:49:12 2021 -0700 Add sample on how to register and reuse SqlColumnEncryptionAzureKeyVaultProvider across multiple SqlCommand objects (#1135) * Create RegisterCustomKeyStoreProvider_Example.cs * add using statements commit 95d23bb39ca74ffd0177e50c9613d4e90505758f Author: Wraith Date: Wed Jun 23 18:42:33 2021 +0100 Update CannotCreateNormalize resource name in resource files (#1134) commit 2891166cc6ee7843729a57a2fb0c036ef9ce1891 Author: Cheena Malhotra Date: Mon Jun 21 10:51:13 2021 -0700 4.0 update (#1129) commit ddb7fc787b25639cab1fdccbb2f00dad5fe48d43 Author: Wraith Date: Mon Jun 21 18:50:41 2021 +0100 Change WeakReference to WeakReference (#1122) commit 355e1959bde167d70ecd3a1de9b963e76144746f Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Fri Jun 18 18:24:45 2021 -0700 update error list (#1125) Co-authored-by: Davoud Eshtehari commit 0256b69452ecbcd200872589382bbf11087734f7 Author: cmeyertons Date: Wed Jun 16 17:54:32 2021 -0500 SqlMetadataPrivFlags remove Enum.HasFlag in favor of bitwise operations (#1054) commit 7e86e4e8d26eb1b95be3d5f14019c3ad366adfaf Author: Wraith Date: Wed Jun 16 23:50:43 2021 +0100 Sync SqlDataRecord (#1024) commit d28fe2120df341b89bfe9c6cb48d2c988af5bba5 Author: Wraith Date: Wed Jun 16 23:50:18 2021 +0100 Clean up AAsyncCallContext and SqlDataReader uses of it (#925) commit 94f401938ae2f5db20259d7037ca39aace57c02b Author: Cédric Luthi Date: Wed Jun 16 09:22:30 2021 +0200 Fix the version 3.0.0 release date in the release notes (#1119) commit 0a844fa0fcfaea8264c9c8a5951bad6c497f5d74 Author: SqlClient DevOps Date: Tue Jun 15 03:03:51 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit c832bd0ad14288bf0278cd52e827a5284547d711 Author: Wraith Date: Mon Jun 14 23:58:30 2021 +0100 Share SqlNormalizer (#1057) commit 4c3dcb998df8162fa2a6ac8cc9f75746e1aa81e4 Author: Wraith Date: Mon Jun 14 23:08:42 2021 +0100 Perf: Change SqlParameter bool fields to flags (#1064) commit 218e34f6aafdd3025528b68250d8c9fcdee9dbef Author: Wraith Date: Mon Jun 14 23:05:00 2021 +0100 Simplify SNIProxy (#934) commit c99ce8d23f359860914bc537a85a215be81c8bab Author: Cheena Malhotra Date: Mon Jun 14 14:59:54 2021 -0700 AKV provider v3.0.0 release notes (#1113) commit 2dec1e95c24a4d5ceaae51605cb426d5000db53d Author: Javad Date: Mon Jun 14 14:57:36 2021 -0700 buildGuide (#1114) commit f188cef29608fb54330d5a45cd636090d7b89f48 Author: Cheena Malhotra Date: Mon Jun 14 11:42:03 2021 -0700 Update nuspec for AKV Provider (#1111) commit f17bba2f5cfdff0e64e7cb94a5a7f2eb28194a6b Author: Wraith Date: Fri Jun 11 22:03:26 2021 +0100 Perf: Static delegates (#1060) * netcore static lambda rework * minor netcore api cleanup * netfx static lambda rework * netcore add strongbox to avoid boxing * fixup 2 anonymous typed lambdas to be explicit commit 1e8ce9766c79b12f7835a8679058d9bce41f7dbc Author: Cheena Malhotra Date: Wed Jun 9 23:41:01 2021 -0700 Minor update commit 8908b9259f81ce20e25eb2c900be12e66eb59832 Author: Johnny Pham Date: Wed Jun 9 10:57:56 2021 -0700 3.0 GA release notes (#1107) commit 3df7de613aecee3a8b5229333c84142e6e83ae9d Author: Johnny Pham Date: Mon Jun 7 19:04:50 2021 -0700 Give system key store providers precedence over instance-level providers (#1101) commit a51a67453c27c81816d90e15b6100c308108840c Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon Jun 7 16:01:28 2021 -0700 Add support ConfigurationManager in Net Standard for configurable retry logic (#1090) commit b672ea74c7e52c2fee215ee14f4a54acbdb719a1 Author: Cheena Malhotra Date: Mon Jun 7 15:56:17 2021 -0700 Update SNI version to stable v3.0.0. (#1102) commit e9f2734b11b076e25e088d1cb142bc045f2f768b Author: Cheena Malhotra Date: Fri Jun 4 13:40:17 2021 -0700 Fix Vulnerability (#1100) commit 6ba4694bb6e4cdd7d7c0a6554df0de295ed2f954 Author: Cheena Malhotra Date: Thu Jun 3 17:31:48 2021 -0700 Tests | Fix issues with Azure Synapse (#1099) commit 89e15c4b2132858f073f98bd01e96fb6e796aa16 Author: Johnny Pham Date: Thu Jun 3 16:08:56 2021 -0700 Extend SqlQueryMetadataCache to include enclave-required keys (#1062) commit 688b931870304114a1bb362280fe62ebb8e97f04 Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu Jun 3 15:16:30 2021 -0700 Update cross reference errors in configurable retry logic documents (#1095) commit d3f91308d80b7c39797af45dcc8efd7d9c19e31b Author: Johnny Pham Date: Thu Jun 3 15:16:19 2021 -0700 Update cross reference errors in key store provider registration docs (#1092) commit fbf8e0cebb96488b02a2b0a5b436d21f63cb2a36 Author: Cheena Malhotra Date: Thu Jun 3 09:59:23 2021 -0700 Fix doc issues for SqlDependency (#1096) Tested on docs build. commit 21475c8ed5d935e4a010d0a3d83cfd265cb7b01d Author: Cheena Malhotra Date: Wed Jun 2 15:12:07 2021 -0700 Tests | Add Local DB App Name config property (#1088) commit cc9f3b5df7878477b02a655d334ec6e46d4da242 Author: Johnny Pham Date: Wed Jun 2 13:01:08 2021 -0700 Add multiuser key store provider samples (#1093) commit ae2d7313f77f38d03ed1dbffe3a71ce2f3d45891 Author: David Engel Date: Tue Jun 1 15:27:16 2021 -0700 Tweak event counter display info (#1091) commit 0578fbf5772296cde19c8a9a2b21f876b1facc8d Author: Cheena Malhotra Date: Mon May 31 14:21:52 2021 -0700 Add ConfigurationManager dependency to nuspec (#1087) commit f3515917c053c3ee6783beaff3901df5c0f0dfe6 Author: Johnny Pham Date: Thu May 27 16:40:38 2021 -0700 Update API docs (#1085) commit 5c5a15d5ac842b48c4e99bff951b026f07f1a5d3 Author: Johnny Pham Date: Tue May 25 15:42:52 2021 -0700 Update LanguageString.cs (#1081) commit 4d1194b4d409f87e1fd917202cd1947043954714 Author: Cheena Malhotra Date: Tue May 25 15:42:37 2021 -0700 Include missing refs (#1083) commit f58464be1bb8ffb15f979d34ecfcd24a7807a476 Author: Cheena Malhotra Date: Fri May 21 11:15:23 2021 -0700 Release notes for v2.1.3 (#1080) commit b1c9067ec4a4b6b89a724d4e0aaf1403d8cff71b Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Thu May 20 16:22:39 2021 -0700 Control building tools separately (#1077) commit 294c452069f21464473842f757734b62c9ed6b4d Author: Cheena Malhotra Date: Thu May 20 16:15:39 2021 -0700 Release notes for v3.0.0-preview3 (#1079) commit 3c140f8c9559c1d74950e44e21be35f68d38e0c8 Author: SqlClient DevOps Date: Thu May 20 19:59:28 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit e105137f04a0c6311ed4786ce5a0114318bfc628 Author: SqlClient DevOps Date: Thu May 20 03:04:19 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 9268dcd35993514a18c67da433f33504d76cb86b Author: Johnny Pham Date: Wed May 19 19:03:54 2021 -0700 Set ColumnEncryptionKeyCacheTtl to zero when key store provider is registered and used globally (#1078) commit 926ed8b93594253236aa9fe9c0666604c27ed753 Author: Cheena Malhotra Date: Wed May 19 19:03:34 2021 -0700 Docs | Switch to new docs for Microsoft.Data.SqlClient (#1075) commit 6b8a9b745c2251f31b191cce5146501f12de682c Author: SqlClient DevOps Date: Wed May 19 03:03:54 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 9543d17d96da3aa7773f5dcf28e70b069333ace4 Author: Cheena Malhotra Date: Tue May 18 10:23:58 2021 -0700 Vulnerability fix | System.Text.Encodings.Web Version override (#1070) commit c6d854a65e1f2fa8c32e3d8cfc0881160ad292bc Author: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Mon May 17 20:42:43 2021 -0700 fix debug assert (#1073) commit b479938c9a1c82ea32ae8ea20583a0d6bd47354e Author: SqlClient DevOps Date: Tue May 18 03:03:42 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 00d45e87ab45b5d7fab334baf65631a64ae20aaf Author: Cheena Malhotra Date: Mon May 17 16:59:40 2021 -0700 Fixes corrupted connection issue when an exception occurs during RPC execution with TVP types (#1068) commit ca4957c49e853aca8f3a6a890fe042673128b03d Author: Cheena Malhotra Date: Mon May 17 16:59:16 2021 -0700 Update error messages for Enclave with forward links (#994) commit 4316474cdb6f3e09d0a9f10d70042215fa1fa74c Author: Cheena Malhotra Date: Mon May 17 16:58:44 2021 -0700 Feature | Introduce "Active Directory Default" authentication mode (#1043) commit 5e067c40ae6f87f54dcdfd44d3de6a7488241c62 Author: Johnny Pham Date: Mon May 17 16:58:30 2021 -0700 Add multi-user key store provider registration support (#1056) commit 561b53556434b2bf2cf9742529e0794582fb2871 Author: Karina Zhou Date: Mon May 17 10:36:15 2021 -0700 Add IP address preference support for TCP connection (#1015) commit fee499fdb42c43d57f8daa0ab4e7179af76e7bb9 Author: Cheena Malhotra Date: Thu May 13 16:37:38 2021 -0700 Add sample back for old driver version docs (#1067) commit 96e7f21e57a2d2889499c4983711a4098633a8b9 Author: Johnny Pham Date: Tue May 11 17:29:44 2021 -0700 Update doc for SqlCommand.ColumnEncryptionSetting (#1066) * Update SqlCommand.xml * Update SqlCommand.xml commit adaa55c7787b7392c3cfad1a92d7222e1ee2a173 Author: Wraith Date: Tue May 11 18:19:53 2021 +0100 Share SqlConnectionTimeoutErrorInternal (#1039) commit 4208104875fbf40c1862252e4cbf089d417ebb70 Author: SqlClient DevOps Date: Mon May 10 03:04:02 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 624a5d6b1735080012e2f5de13a506eaceba4fdc Author: SqlClient DevOps Date: Sun May 9 03:03:37 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit 461af074621f69ae109329a8904d3c3ffa664b82 Author: SqlClient DevOps Date: Sat May 8 03:03:42 2021 +0000 [Scheduled Run] Localized resource files from OneLocBuild commit efc6c4642085ee6aec6c3f04c0c2d65fb0dfc7f5 Author: Johnny Pham Date: Fri May 7 11:26:38 2021 -0700 Update enclave sim to use new crypto apis (#1061) * update enclave sim to use new crypto apis * update using statement commit 91c5844231c4732936d80005a4605613158f3917 Author: Wraith Date: Fri May 7 05:44:48 2021 +0100 Share SqlStatistics (#1028) commit 1eabe061ddc231f33abeaa3210ad6bf5a7d52ee6 Author: Wraith Date: Fri May 7 05:44:24 2021 +0100 Shrink SqlParameter XmlSchema (#1033) --- .config/CredScanSuppressions.json | 25 + .config/PolicheckExclusions.xml | 5 + .config/tsaoptions.json | 11 +- .editorconfig | 4 + .gitignore | 3 + BUILDGUIDE.md | 24 +- CHANGELOG.md | 341 +- NuGet.config | 7 + README.md | 23 +- RunPackageReferenceTests.cmd | 90 +- RunProjectReferenceTests.cmd | 4 +- build.proj | 50 +- ...DAuthenticationCustomDeviceFlowCallback.cs | 2 +- doc/samples/AzureKeyVaultProviderExample.cs | 6 +- ...VaultProviderWithEnclaveProviderExample.cs | 6 +- ...viceCodeFlowAzureAuthenticationProvider.cs | 56 +- doc/samples/SqlBatch_ExecuteReader.cs | 43 + doc/samples/SqlBulkCopy_ColumnMapping.cs | 4 +- .../SqlBulkCopy_ColumnMappingRemoveAt.cs | 2 +- .../SqlConnection_AccessTokenCallback.cs | 48 +- .../SqlDataSourceEnumerator.xml | 244 +- .../SqlNotificationRequest.xml | 216 +- .../ColumnSensitivity.xml | 39 +- .../InformationType.xml | 55 +- .../Label.xml | 55 +- .../SensitivityClassification.xml | 140 +- .../SensitivityProperty.xml | 124 +- .../SensitivityRank.xml | 35 +- .../SqlDataRecord.xml | 2295 +++-- .../SqlMetaData.xml | 2620 ++++-- .../TriggerAction.xml | 631 +- .../ActiveDirectoryAuthenticationProvider.xml | 209 +- .../ApplicationIntent.xml | 41 +- .../OnChangeEventHandler.xml | 31 +- .../PoolBlockingPeriod.xml | 36 +- .../Microsoft.Data.SqlClient/SQLDebugging.xml | 28 +- .../Microsoft.Data.SqlClient/SortOrder.xml | 45 +- .../SqlAuthenticationInitializer.xml | 31 +- .../SqlAuthenticationMethod.xml | 96 +- .../SqlAuthenticationParameters.xml | 112 +- .../SqlAuthenticationProvider.xml | 121 +- .../SqlAuthenticationToken.xml | 44 +- .../Microsoft.Data.SqlClient/SqlBatch.xml | 429 + .../SqlBatchCommand.xml | 142 + .../SqlBatchCommandCollection.xml | 183 + .../Microsoft.Data.SqlClient/SqlBulkCopy.xml | 3534 +++++--- .../SqlBulkCopyColumnMapping.xml | 1434 +++- .../SqlBulkCopyColumnMappingCollection.xml | 1615 +++- .../SqlBulkCopyColumnOrderHint.xml | 576 +- .../SqlBulkCopyColumnOrderHintCollection.xml | 1250 ++- .../SqlBulkCopyOptions.xml | 219 +- .../SqlClientDiagnostic.xml | 525 ++ .../SqlClientFactory.xml | 540 +- .../SqlClientLogger.xml | 127 +- .../SqlClientMetaDataCollectionNames.xml | 148 +- .../SqlClientPermission.xml | 315 +- .../SqlClientPermissionAttribute.xml | 39 +- ...lumnEncryptionCertificateStoreProvider.xml | 143 +- .../SqlColumnEncryptionCngProvider.xml | 153 +- .../SqlColumnEncryptionCspProvider.xml | 151 +- .../SqlColumnEncryptionEnclaveProvider.xml | 150 +- .../SqlColumnEncryptionKeyStoreProvider.xml | 173 +- .../Microsoft.Data.SqlClient/SqlCommand.xml | 7419 ++++++++++------- .../SqlCommandBuilder.xml | 967 ++- .../SqlCommandColumnEncryptionSetting.xml | 66 +- .../SqlConfigurableRetryFactory.xml | 364 +- .../SqlConnection.xml | 4625 +++++++--- .../SqlConnectionAttestationProtocol.xml | 64 +- .../SqlConnectionColumnEncryptionSetting.xml | 32 +- .../SqlConnectionEncryptOption.xml | 66 +- .../SqlConnectionIPAddressPreference.xml | 76 +- .../SqlConnectionOverrides.xml | 40 +- .../SqlConnectionStringBuilder.xml | 3036 ++++--- .../SqlCredential.xml | 176 +- .../SqlDataAdapter.xml | 1871 +++-- .../SqlDataReader.xml | 3163 ++++--- .../SqlDependency.xml | 560 +- .../SqlEnclaveAttestationParameters.xml | 79 +- .../SqlEnclaveSession.xml | 65 +- .../Microsoft.Data.SqlClient/SqlError.xml | 863 +- .../SqlErrorCollection.xml | 402 +- .../Microsoft.Data.SqlClient/SqlException.xml | 1267 ++- .../SqlInfoMessageEventArgs.xml | 110 +- .../SqlInfoMessageEventHandler.xml | 34 +- .../SqlNotificationEventArgs.xml | 89 +- .../SqlNotificationInfo.xml | 178 +- .../SqlNotificationSource.xml | 120 +- .../SqlNotificationType.xml | 50 +- .../Microsoft.Data.SqlClient/SqlParameter.xml | 1663 ++-- .../SqlParameterCollection.xml | 1138 ++- .../SqlRetryIntervalBaseEnumerator.xml | 155 +- .../SqlRetryLogicBase.xml | 142 +- .../SqlRetryLogicBaseProvider.xml | 224 +- .../SqlRetryLogicOption.xml | 133 +- .../SqlRetryingEventArgs.xml | 82 +- .../SqlRowUpdatedEventArgs.xml | 204 +- .../SqlRowUpdatedEventHandler.xml | 41 +- .../SqlRowUpdatingEventArgs.xml | 218 +- .../SqlRowUpdatingEventHandler.xml | 46 +- .../SqlRowsCopiedEventArgs.xml | 97 +- .../SqlRowsCopiedEventHandler.xml | 24 +- .../SqlTransaction.xml | 688 +- .../Microsoft.Data.SqlTypes/SqlFileStream.xml | 905 +- .../Microsoft.Data.SqlTypes/SqlJson.xml | 33 + .../OperationAbortedException.xml | 27 +- .../Microsoft.Data/SqlDbTypeExtensions.xml | 24 + .../DataAccessKind.xml | 54 +- .../Microsoft.SqlServer.Server/Format.xml | 367 +- .../IBinarySerialize.xml | 238 +- .../InvalidUdtException.xml | 82 +- .../SqlFacetAttribute.xml | 419 +- .../SqlFunctionAttribute.xml | 354 +- .../SqlMethodAttribute.xml | 161 +- .../SqlUserDefinedAggregateAttribute.xml | 341 +- .../SqlUserDefinedTypeAttribute.xml | 307 +- .../SystemDataAccessKind.xml | 54 +- .../jobs/build-signed-akv-package-job.yml | 70 + .../jobs/build-signed-package-job.yml | 63 + .../templates/jobs/ci-build-nugets-job.yml | 77 + .../templates/jobs/ci-code-coverage-job.yml | 122 + .../templates/jobs/ci-run-tests-job.yml | 248 + .../jobs/run-tests-package-reference-job.yml | 68 + .../jobs/validate-signed-package-job.yml | 349 + .../templates/stages/ci-run-tests-stage.yml | 102 + ...ld-all-configurations-signed-dlls-step.yml | 54 + .../templates/steps/build-all-tests-step.yml | 75 + .../build-and-run-tests-netcore-step.yml | 80 + .../steps/build-and-run-tests-netfx-step.yml | 79 + .../templates/steps/ci-prebuild-step.yml | 43 + .../templates/steps/ci-project-build-step.yml | 91 + .../templates/steps/code-analyze-step.yml | 51 + .../steps/configure-sql-server-linux-step.yml | 64 + .../steps/configure-sql-server-step.yml | 111 + .../steps/configure-sql-server-win-step.yml | 250 + .../steps/copy-dlls-for-test-step.yml | 106 + .../steps/esrp-code-signing-step.yml | 135 + .../steps/generate-nuget-package-step.yml | 60 + .../common/templates/steps/pre-build-step.yml | 20 + .../templates/steps/prepare-test-db-step.yml | 26 + .../templates/steps/publish-symbols-step.yml | 150 + .../steps/publish-test-results-step.yml | 59 + .../templates/steps/run-all-tests-step.yml | 107 + .../steps/update-config-file-step.yml | 199 + .../update-nuget-config-local-feed-step.yml | 89 + eng/pipelines/dotnet-sqlclient-ci-core.yml | 388 + ...qlclient-ci-package-reference-pipeline.yml | 94 + ...qlclient-ci-project-reference-pipeline.yml | 86 + .../dotnet-sqlclient-signing-pipeline.yml | 174 + eng/pipelines/libraries/akv-variables.yml | 15 + eng/pipelines/libraries/build-variables.yml | 10 + .../libraries/ci-build-variables.yml | 25 + eng/pipelines/libraries/common-variables.yml | 23 + .../libraries/mds-validation-variables.yml | 36 + eng/pipelines/libraries/mds-variables.yml | 17 + eng/pipelines/libraries/variables.yml | 17 + porting-cheat-sheet.md | 6 + release-notes/2.0/2.0.0-preview1.md | 2 +- release-notes/2.0/2.0.0.md | 2 +- release-notes/2.1/2.1.7.md | 81 + release-notes/2.1/2.1.md | 1 + release-notes/2.1/README.md | 1 + release-notes/3.1/3.1.4.md | 78 + release-notes/3.1/3.1.5.md | 75 + release-notes/3.1/3.1.7.md | 81 + release-notes/3.1/3.1.md | 3 + release-notes/3.1/README.md | 3 + release-notes/4.0/4.0.4.md | 73 + release-notes/4.0/4.0.5.md | 71 + release-notes/4.0/4.0.6.md | 75 + release-notes/4.0/4.0.md | 3 + release-notes/4.0/README.md | 3 + release-notes/5.0/5.0.0-preview1.md | 5 + release-notes/5.0/5.0.0-preview2.md | 5 + release-notes/5.0/5.0.0-preview3.md | 7 + release-notes/5.0/5.0.0.md | 8 + release-notes/5.0/5.0.1.md | 3 + release-notes/5.0/5.0.2.md | 4 + release-notes/5.1/5.1.0-preview1.md | 5 + release-notes/5.1/5.1.0-preview2.md | 6 + release-notes/5.1/5.1.0.md | 13 +- release-notes/5.1/5.1.1.md | 7 +- release-notes/5.1/5.1.2.md | 78 + release-notes/5.1/5.1.3.md | 67 + release-notes/5.1/5.1.4.md | 70 + release-notes/5.1/5.1.5.md | 72 + release-notes/5.1/5.1.6.md | 75 + release-notes/5.1/5.1.md | 5 + release-notes/5.1/README.md | 5 + release-notes/5.2/5.2.0-preview1.md | 11 +- release-notes/5.2/5.2.0-preview2.md | 10 +- release-notes/5.2/5.2.0-preview3.md | 9 +- release-notes/5.2/5.2.0-preview4.md | 145 + release-notes/5.2/5.2.0-preview5.md | 107 + release-notes/5.2/5.2.0.md | 282 +- release-notes/5.2/5.2.1.md | 99 + release-notes/5.2/5.2.2.md | 100 + release-notes/5.2/5.2.md | 20 + release-notes/5.2/README.md | 12 +- release-notes/6.0/6.0.0-preview1.md | 100 + release-notes/6.0/6.0.md | 7 + release-notes/6.0/README.md | 7 + release-notes/README.md | 5 +- .../AzureKeyVaultProvider/5.1/5.1.0.md | 72 + .../AzureKeyVaultProvider/5.1/README.md | 7 + src/Directory.Build.props | 27 +- src/Microsoft.Data.SqlClient.sln | 106 +- ...waysEncrypted.AzureKeyVaultProvider.csproj | 16 +- ...qlColumnEncryptionAzureKeyVaultProvider.cs | 2 +- .../add-ons/AzureKeyVaultProvider/Utils.cs | 7 +- .../add-ons/Directory.Build.props | 10 +- .../Microsoft.Data.SqlClient.NetStandard.cs | 16 - .../netcore/ref/Microsoft.Data.SqlClient.cs | 445 +- .../ref/Microsoft.Data.SqlClient.csproj | 24 +- .../Interop/Unix/Interop.Libraries.cs | 4 + .../Interop.GssApiException.cs | 6 +- .../Interop.GssBuffer.cs | 6 +- .../Interop.NetSecurityNative.cs | 5 +- .../Windows/Crypt32/Interop.certificates.cs | 4 + .../Crypt32/Interop.certificates_types.cs | 4 + .../SChannel/Interop.SECURITY_STATUS.cs | 4 + ...terop.SecPkgContext_ApplicationProtocol.cs | 0 .../SChannel/SecPkgContext_ConnectionInfo.cs | 5 +- .../Windows/kernel32}/Interop.CloseHandle.cs | 4 + .../Windows/kernel32/Interop.FreeLibrary.cs | 0 .../kernel32/Interop.GetProcAddress.cs | 0 .../Windows/kernel32/Interop.LoadLibraryEx.cs | 0 .../Interop/Windows/sspicli/GlobalSSPI.cs | 4 + .../Interop/Windows/sspicli/Interop.SSPI.cs | 4 + .../Windows/sspicli/NegotiationInfoClass.cs | 4 + .../Interop/Windows/sspicli/SSPIAuthType.cs | 4 + .../Interop/Windows/sspicli/SSPIInterface.cs | 4 + .../Windows/sspicli/SSPISecureChannelType.cs | 4 + .../Interop/Windows/sspicli/SSPIWrapper.cs | 7 +- .../Windows/sspicli/SafeDeleteContext.cs | 6 +- .../Windows/sspicli/SecPkgContext_Bindings.cs | 4 + .../sspicli/SecPkgContext_NegotiationInfoW.cs | 4 + .../Windows/sspicli/SecPkgContext_Sizes.cs | 5 +- .../sspicli/SecPkgContext_StreamSizes.cs | 5 +- .../Windows/sspicli/SecurityPackageInfo.cs | 4 + .../sspicli/SecurityPackageInfoClass.cs | 4 + .../Windows/sspicli/SecuritySafeHandles.cs | 21 +- .../Data/ProviderBase/DbConnectionInternal.cs | 18 +- .../Win32/SafeHandles/GssSafeHandles.cs | 4 + .../Win32/SafeHandles/SafeLibraryHandle.cs | 0 .../Generic/BidirectionalDictionary.cs | 4 + .../System/IO/PathInternal.Windows.cs | 0 .../System/Net/ContextFlagsAdapterPal.Unix.cs | 4 +- .../Net/ContextFlagsAdapterPal.Windows.cs | 4 +- .../{src => }/System/Net/ContextFlagsPal.cs | 4 +- .../DebugCriticalHandleMinusOneIsInvalid.cs | 6 +- ...ugCriticalHandleZeroOrMinusOneIsInvalid.cs | 6 +- .../{src => }/System/Net/DebugSafeHandle.cs | 7 +- .../{src => }/System/Net/InternalException.cs | 0 .../System/Net/Logging/DebugThreadTracking.cs | 4 + .../Net/Logging/NetEventSource.Common.cs | 4 +- .../System/Net/NegotiationInfoClass.cs | 4 + .../Net/Security/NegotiateStreamPal.Unix.cs | 4 + .../Security/NegotiateStreamPal.Windows.cs | 4 + .../NetEventSource.Security.Windows.cs | 4 + .../Net/Security/NetEventSource.Security.cs | 8 +- .../System/Net/Security/SecurityBuffer.cs | 5 +- .../System/Net/Security/SecurityBufferType.cs | 4 + .../Security/SecurityContextTokenHandle.cs | 5 +- .../Net/Security/Unix/SafeDeleteContext.cs | 4 + .../Security/Unix/SafeDeleteNegoContext.cs | 4 + .../Net/Security/Unix/SafeFreeCredentials.cs | 4 + .../Security/Unix/SafeFreeNegoCredentials.cs | 4 + .../Net/SecurityStatusAdapterPal.Windows.cs | 4 + .../{src => }/System/Net/SecurityStatusPal.cs | 4 + .../Common/{src => }/System/NotImplemented.cs | 0 .../System/Threading/Tasks/TaskToApm.cs | 0 .../CoreLib/Interop/Windows/Interop.BOOL.cs | 21 - .../Interop.Initialization.cs | 41 - .../Interop.GetCurrentProcess_IntPtr.cs | 15 - .../Data/ProviderBase/DbConnectionFactory.cs | 477 -- .../Interop/SNINativeMethodWrapper.Windows.cs | 16 +- .../src/Microsoft.Data.SqlClient.csproj | 1012 +-- .../Data/Common/DbConnectionOptions.cs | 6 +- .../Data/ProviderBase/DbConnectionClosed.cs | 16 - .../Data/ProviderBase/DbConnectionFactory.cs | 220 - .../Data/ProviderBase/DbConnectionInternal.cs | 40 +- .../DbConnectionPool.NetCoreApp.cs | 46 - .../Data/SqlClient/LocalDBAPI.uap.cs | 14 - .../Data/SqlClient/SNI/LocalDB.uap.cs | 14 - .../Microsoft/Data/SqlClient/SNI/SNICommon.cs | 276 +- .../Microsoft/Data/SqlClient/SNI/SNIHandle.cs | 6 - .../Data/SqlClient/SNI/SNIMarsHandle.cs | 4 +- .../Data/SqlClient/SNI/SNINpHandle.cs | 18 +- .../Microsoft/Data/SqlClient/SNI/SNIPacket.cs | 4 +- .../Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 119 +- .../Data/SqlClient/SNI/SNITcpHandle.cs | 63 +- .../src/Microsoft/Data/SqlClient/SNI/SSRP.cs | 12 +- .../SNI/SslOverTdsStream.NetStandard.cs | 223 - .../Data/SqlClient/SNI/SslOverTdsStream.cs | 2 +- .../SqlClient/SNI/SspiClientContextStatus.cs | 4 + ...uthenticationProviderManager.NetCoreApp.cs | 195 - ...thenticationProviderManager.NetStandard.cs | 15 - .../SqlAuthenticationProviderManager.cs | 125 - .../Microsoft/Data/SqlClient/SqlBulkCopy.cs | 55 +- .../Data/SqlClient/SqlClientDiagnostic.cs | 970 +++ .../SqlClientDiagnosticListenerExtensions.cs | 380 +- .../Data/SqlClient/SqlClientFactory.cs | 55 - ...umnEncryptionEnclaveProvider.NetCoreApp.cs | 25 - .../SqlColumnEncryptionEnclaveProvider.cs | 19 - .../Microsoft/Data/SqlClient/SqlCommand.cs | 569 +- .../Microsoft/Data/SqlClient/SqlConnection.cs | 86 +- ...qlConnectionFactory.AssemblyLoadContext.cs | 6 +- .../Data/SqlClient/SqlConnectionFactory.cs | 25 +- .../Data/SqlClient/SqlConnectionHelper.cs | 28 +- .../Microsoft/Data/SqlClient/SqlDataReader.cs | 741 +- .../SqlDelegatedTransaction.NetCoreApp.cs | 2 +- .../SqlDelegatedTransaction.NetStandard.cs | 22 - .../Data/SqlClient/SqlDelegatedTransaction.cs | 115 +- .../SqlClient/SqlInternalConnectionTds.cs | 209 +- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 2218 ----- .../Data/SqlClient/TdsParser.NetCoreApp.cs | 5 +- .../Data/SqlClient/TdsParser.NetStandard.cs | 41 - .../Data/SqlClient/TdsParser.Windows.cs | 34 +- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 2820 ++++--- .../SqlClient/TdsParserStateObject.netcore.cs | 1814 +--- .../SqlClient/TdsParserStateObjectManaged.cs | 39 +- .../SqlClient/TdsParserStateObjectNative.cs | 18 +- .../Data/SqlClient/TdsParserStaticMethods.cs | 185 - .../Data/SqlTypes/SqlFileStream.Windows.cs | 8 +- ...yzerExceptionList.analyzerdata.netstandard | 44 - .../netfx/ref/Microsoft.Data.SqlClient.cs | 48 +- .../netfx/ref/Microsoft.Data.SqlClient.csproj | 13 +- .../Data/Common/NameValuePermission.cs | 56 +- .../Data/Common/DBDataPermissionAttribute.cs | 98 - .../netfx/src/Microsoft.Data.SqlClient.csproj | 484 +- .../Microsoft/Data/Common/AdapterSwitches.cs | 2 +- .../Data/Common/DBConnectionString.cs | 40 +- .../Data/Common/DbConnectionOptions.cs | 16 +- .../src/Microsoft/Data/Common/GreenMethods.cs | 6 +- .../Interop/SNINativeManagedWrapperARM64.cs | 8 +- .../Interop/SNINativeManagedWrapperX64.cs | 8 +- .../Interop/SNINativeManagedWrapperX86.cs | 8 +- .../Data/Interop/SNINativeMethodWrapper.cs | 130 +- .../Microsoft/Data/ProviderBase/DbBuffer.cs | 807 -- .../Data/ProviderBase/DbConnectionClosed.cs | 180 - .../Data/ProviderBase/DbConnectionInternal.cs | 109 +- .../Data/ProviderBase/DbConnectionPool.cs | 2020 ----- .../ProviderBase/DbConnectionPoolCounters.cs | 14 +- .../ProviderBase/DbConnectionPoolIdentity.cs | 240 - .../ProviderBase/DbReferenceCollection.cs | 265 - .../src/Microsoft/Data/Sql/SqlGenericUtil.cs | 35 - .../AlwaysEncryptedKeyConverter.Cng.cs | 71 - .../SqlClient/Server/SmiContextFactory.cs | 10 +- .../Microsoft/Data/SqlClient/SqlBulkCopy.cs | 57 +- .../SqlClient/SqlBulkCopyColumnMapping.cs | 138 - .../Data/SqlClient/SqlCertificateCallbacks.cs | 31 - .../Data/SqlClient/SqlClientFactory.cs | 98 - .../SqlClient/SqlClientOriginalAddressInfo.cs | 73 - .../Data/SqlClient/SqlClientPermission.cs | 52 +- .../SqlClient/SqlClientWrapperSmiStream.cs | 4 +- .../SqlClientWrapperSmiStreamChars.cs | 6 +- ...olumnEncryptionCertificateStoreProvider.cs | 581 -- .../SqlColumnEncryptionCngProvider.cs | 392 - .../SqlColumnEncryptionCspProvider.cs | 436 - .../Microsoft/Data/SqlClient/SqlCommand.cs | 628 +- .../Microsoft/Data/SqlClient/SqlConnection.cs | 176 +- .../Data/SqlClient/SqlConnectionFactory.cs | 35 +- .../Data/SqlClient/SqlConnectionHelper.cs | 41 +- .../Microsoft/Data/SqlClient/SqlDataReader.cs | 1775 ++-- .../Data/SqlClient/SqlDataReaderSmi.cs | 2 +- .../Data/SqlClient/SqlDelegatedTransaction.cs | 80 +- .../Data/SqlClient/SqlDependencyUtils.cs | 709 -- .../SqlClient/SqlInternalConnectionSmi.cs | 81 +- .../SqlClient/SqlInternalConnectionTds.cs | 238 +- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 2677 ------ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 3053 +++---- .../Data/SqlClient/TdsParserHelperClasses.cs | 1390 --- .../SqlClient/TdsParserStateObject.netfx.cs | 1867 +---- .../Microsoft/Data/SqlTypes/SqlFileStream.cs | 4 +- ...crosoft.Data.SqlClient.Batch.NetCoreApp.cs | 29 + .../ref/Microsoft.Data.SqlClient.Batch.cs | 131 + .../src/Interop/Windows/Interop.Errors.cs | 0 .../src/Interop/Windows/Interop.Libraries.cs | 2 +- .../Interop/Windows/Interop.UNICODE_STRING.cs | 0 .../Windows/Kernel32}/Interop.CTL_CODE.cs | 0 .../Kernel32}/Interop.DeviceIoControl.cs | 0 .../Windows/Kernel32/Interop.FileTypes.cs | 0 .../Interop.GetFileType_SafeHandle.cs | 0 .../Kernel32}/Interop.IoControlCodeAccess.cs | 0 .../Interop.IoControlTransferType.cs | 0 .../Kernel32/Interop.SetThreadErrorMode.cs | 0 .../NtDll/Interop.FILE_FULL_EA_INFORMATION.cs | 0 .../Windows/NtDll/Interop.IO_STATUS_BLOCK.cs | 0 .../Windows/NtDll/Interop.NtCreateFile.cs | 0 .../NtDll/Interop.RtlNtStatusToDosError.cs | 0 .../src/Microsoft.Data.SqlClient.csproj | 8 + .../Data/Common/AdapterUtil.Windows.cs | 4 +- .../src/Microsoft/Data/Common/AdapterUtil.cs | 63 +- .../Data/Common/BitConverterCompatible.cs | 18 + .../Data/Common/DbConnectionOptions.Common.cs | 29 +- .../Data/Common/DbConnectionStringCommon.cs | 97 +- .../Data/Common/MultipartIdentifier.cs | 2 +- .../Microsoft/Data/Common/NameValuePair.cs | 2 +- .../src/Microsoft/Data/DataException.cs | 4 +- .../Data/OperationAbortedException.cs | 3 + .../Data/ProviderBase/DbConnectionClosed.cs | 23 +- .../Data/ProviderBase/DbConnectionFactory.cs | 335 +- .../Data/ProviderBase/DbConnectionPool.cs | 338 +- .../DbConnectionPoolAuthenticationContext.cs | 2 +- .../ProviderBase/DbConnectionPoolGroup.cs | 12 +- .../DbConnectionPoolIdentity.Unix.cs | 0 .../DbConnectionPoolIdentity.Windows.cs | 17 +- .../ProviderBase/DbConnectionPoolIdentity.cs | 20 +- .../Data/ProviderBase/DbMetaDataFactory.cs | 6 +- .../ProviderBase/DbReferenceCollection.cs | 114 +- .../Sql/SqlDataSourceEnumerator.Windows.cs | 2 +- .../Data/Sql/SqlDataSourceEnumerator.cs | 6 +- .../SqlDataSourceEnumeratorManagedHelper.cs | 2 +- .../SqlDataSourceEnumeratorNativeHelper.cs | 8 +- .../Data/Sql/SqlNotificationRequest.cs | 4 +- .../Data/SqlClient/AAsyncCallContext.cs | 0 .../ActiveDirectoryAuthenticationProvider.cs | 321 +- .../SqlClient/AlwaysEncryptedHelperClasses.cs | 22 +- .../SqlClient/AlwaysEncryptedKeyConverter.cs} | 57 +- .../AzureAttestationBasedEnclaveProvider.cs | 15 +- .../Data/SqlClient/ColumnEncryptionKeyInfo.cs | 12 +- .../SqlClient/EnclaveDelegate.NotSupported.cs | 56 - .../Data/SqlClient/EnclaveProviderBase.cs | 12 +- .../Data/SqlClient/EnclaveSessionCache.cs | 25 +- .../Data/SqlClient/LocalAppContextSwitches.cs | 117 +- .../SqlConfigurableRetryLogicLoader.cs | 4 +- .../Data/SqlClient/SQLFallbackDNSCache.cs | 7 +- .../SSPI/ManagedSSPIContextProvider.cs | 24 + .../SSPI/NativeSSPIContextProvider.cs | 68 + .../SSPI/NegotiateSSPIContextProvider.cs | 41 + .../SqlClient/SSPI/SSPIContextProvider.cs | 59 + .../SqlClient/Server/ExtendedClrTypeCode.cs | 4 + .../SqlClient/Server/MemoryRecordBuffer.cs | 2 +- .../Data/SqlClient/Server/MetadataUtilsSmi.cs | 47 +- .../SqlClient/Server/SmiEventSink_Default.cs | 16 +- .../Server/SmiEventSink_Default.netfx.cs | 36 +- .../Data/SqlClient/Server/SmiGettersStream.cs | 6 +- .../Data/SqlClient/Server/SmiMetaData.cs | 6 +- .../Data/SqlClient/Server/SmiSettersStream.cs | 6 +- .../Data/SqlClient/Server/SqlDataRecord.cs | 2 +- .../Data/SqlClient/Server/SqlMetaData.cs | 30 +- .../Data/SqlClient/Server/SqlRecordBuffer.cs | 6 +- .../Data/SqlClient/Server/ValueUtilsSmi.cs | 24 +- .../SqlClient/Server/ValueUtilsSmi.netfx.cs | 4 +- .../SqlClient/SignatureVerificationCache.cs | 27 +- .../SqlAeadAes256CbcHmac256Algorithm.cs | 4 +- .../SqlAuthenticationProviderManager.cs | 75 +- .../src/Microsoft/Data/SqlClient/SqlBatch.cs | 239 + .../SqlBatchCommand.Net8OrGreater.cs | 21 + .../Data/SqlClient/SqlBatchCommand.cs | 149 + .../SqlClient/SqlBatchCommandCollection.cs | 79 + .../src/Microsoft/Data/SqlClient/SqlBuffer.cs | 33 +- .../SqlClient/SqlBulkCopyColumnMapping.cs | 2 +- .../Data/SqlClient/SqlCachedBuffer.cs | 23 +- ...SqlClientEncryptionAlgorithmFactoryList.cs | 2 +- .../Data/SqlClient/SqlClientEventSource.cs | 9 + .../Data/SqlClient/SqlClientFactory.cs | 108 + ...ryptionCertificateStoreProvider.Windows.cs | 88 +- .../SqlColumnEncryptionCngProvider.Windows.cs | 20 +- .../SqlColumnEncryptionCspProvider.Windows.cs | 20 +- .../SqlColumnEncryptionEnclaveProvider.cs | 11 +- .../Data/SqlClient/SqlCommandBuilder.cs | 4 +- .../Microsoft/Data/SqlClient/SqlCommandSet.cs | 76 +- .../SqlConnectionPoolGroupProviderInfo.cs | 6 +- .../Data/SqlClient/SqlConnectionPoolKey.cs | 59 +- .../Data/SqlClient/SqlConnectionString.cs | 58 +- .../SqlClient/SqlConnectionStringBuilder.cs | 60 +- .../Data/SqlClient/SqlDataAdapter.cs | 20 +- .../Microsoft/Data/SqlClient/SqlDependency.cs | 38 +- .../Data/SqlClient/SqlDependencyListener.cs | 26 +- .../SqlDependencyUtils.AssemblyLoadContext.cs | 4 + .../Data/SqlClient/SqlDependencyUtils.cs | 10 +- ...claveAttestationParameters.NotSupported.cs | 19 - .../Data/SqlClient/SqlEnclaveSession.cs | 2 +- .../src/Microsoft/Data/SqlClient/SqlEnums.cs | 13 +- .../src/Microsoft/Data/SqlClient/SqlError.cs | 25 +- .../Microsoft/Data/SqlClient/SqlException.cs | 71 +- .../Data/SqlClient/SqlInfoMessageEvent.cs | 2 +- .../Data/SqlClient/SqlInternalConnection.cs | 45 +- .../Data/SqlClient/SqlInternalTransaction.cs | 6 +- .../Data/SqlClient/SqlMetadataFactory.cs | 11 +- .../Microsoft/Data/SqlClient/SqlParameter.cs | 44 +- .../Data/SqlClient/SqlParameterCollection.cs | 5 + .../Data/SqlClient/SqlQueryMetadataCache.cs | 20 +- .../Data/SqlClient/SqlReferenceCollection.cs | 2 +- .../Data/SqlClient/SqlSecurityUtility.cs | 14 +- .../Data/SqlClient/SqlSequentialTextReader.cs | 55 +- .../Microsoft/Data/SqlClient/SqlStatistics.cs | 4 +- .../src/Microsoft/Data/SqlClient/SqlStream.cs | 12 +- .../Data/SqlClient/SqlSymmetricKeyCache.cs | 14 +- .../Data/SqlClient/SqlTransaction.Common.cs | 4 +- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 2801 ++++++- .../src/Microsoft/Data/SqlClient/TdsEnums.cs | 68 +- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 216 + .../Data/SqlClient/TdsParserHelperClasses.cs | 73 +- .../SqlClient/TdsParserSafeHandles.Windows.cs | 6 +- .../Data/SqlClient/TdsParserSessionPool.cs | 11 +- .../Data/SqlClient/TdsParserStateObject.cs | 2031 ++++- .../Data/SqlClient/TdsParserStaticMethods.cs | 4 +- .../Data/SqlClient/TdsValueSetter.cs | 62 +- .../VirtualSecureModeEnclaveProviderBase.cs | 56 +- .../src/Microsoft/Data/SqlDbTypeExtensions.cs | 19 + .../src/Microsoft/Data/SqlTypes/SqlJson.cs | 103 + .../src/Resources/Strings.Designer.cs | 32 +- .../src/Resources/Strings.de.resx | 69 +- .../src/Resources/Strings.es.resx | 67 +- .../src/Resources/Strings.fr.resx | 75 +- .../src/Resources/Strings.it.resx | 67 +- .../src/Resources/Strings.ja.resx | 73 +- .../src/Resources/Strings.ko.resx | 73 +- .../src/Resources/Strings.pt-BR.resx | 73 +- .../src/Resources/Strings.resx | 53 +- .../src/Resources/Strings.ru.resx | 69 +- .../src/Resources/Strings.zh-Hans.resx | 75 +- .../src/Resources/Strings.zh-Hant.resx | 75 +- .../src/Resources/StringsHelper.cs | 2 +- .../src/System/Diagnostics/CodeAnalysis.cs | 56 +- .../CustomRetryLogicProvider.csproj | 1 - .../tests/Directory.Build.props | 2 +- .../tests/Docker/DockerLinuxTest/Dockerfile | 6 +- ...soft.Data.SqlClient.DockerLinuxTest.csproj | 6 +- .../tests/Docker/DockerLinuxTest/Program.cs | 1 - ...ncryptionCertificateStoreProviderShould.cs | 13 +- .../AlwaysEncryptedTests/Utility.cs | 6 +- .../AmbientTransactionFailureTest.cs | 5 +- .../AssertExtensions.cs | 34 +- .../BaseProviderAsyncTest.cs | 2 +- .../BaseProviderAsyncTest/MockCommand.cs | 2 +- .../BaseProviderAsyncTest/MockConnection.cs | 2 +- .../BaseProviderAsyncTest/MockDataReader.cs | 2 +- .../tests/FunctionalTests/CloneTests.cs | 10 + .../FunctionalTests/DataCommon/TestUtility.cs | 16 + .../Microsoft.Data.SqlClient.Tests.csproj | 54 +- .../SqlAuthenticationProviderTest.cs | 26 + .../tests/FunctionalTests/SqlBufferTests.cs | 253 + .../SqlBulkCopyColumnMappingCollectionTest.cs | 13 +- ...qlBulkCopyColumnOrderHintCollectionTest.cs | 12 +- .../FunctionalTests/SqlClientFactoryTest.cs | 36 +- .../tests/FunctionalTests/SqlCommandTest.cs | 12 +- .../SqlConfigurableRetryLogicTest.cs | 6 +- .../SqlConnectionBasicTests.cs | 59 +- .../SqlConnectionReadOnlyRoutingTests.cs | 140 + .../SqlConnectionStringBuilderTest.cs | 195 +- .../SqlConnectionTest.RetrieveStatistics.cs | 6 +- .../FunctionalTests/SqlDataRecordTest.cs | 37 +- .../tests/FunctionalTests/SqlErrorTest.cs | 6 +- .../tests/FunctionalTests/SqlExceptionTest.cs | 4 +- .../tests/FunctionalTests/SqlHelperTest.cs | 2 +- .../tests/FunctionalTests/SqlMetaDataTest.cs | 6 +- .../FunctionalTests/TestRoutingTdsServer.cs | 64 + .../tests/FunctionalTests/TestTdsServer.cs | 17 +- .../AlwaysEncrypted/AKVUnitTests.cs | 15 +- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 6 +- .../ColumnDecryptErrorTests.cs | 169 + .../AlwaysEncrypted/ConversionTests.cs | 5 +- .../AlwaysEncrypted/DateOnlyReadTests.cs | 93 + .../AlwaysEncrypted/End2EndSmokeTests.cs | 2 +- .../TestFixtures/DatabaseHelper.cs | 31 +- .../TestFixtures/SQLSetupStrategy.cs | 11 +- .../TestFixtures/Setup/CertificateUtility.cs | 39 +- .../Setup/ColumnDecryptErrorTestTable.cs | 40 + .../TestFixtures/Setup/DateOnlyTestTable.cs | 42 + .../ManualTests/DataCommon/AADUtility.cs | 14 - .../DataCommon/ConnectionTestParameters.cs | 40 + .../ConnectionTestParametersData.cs | 85 + .../ManualTests/DataCommon/DataTestUtility.cs | 195 +- .../SqlClientCustomTokenCredential.cs | 64 +- .../tests/ManualTests/Json/SqlJsonTest.cs | 151 + ....Data.SqlClient.ManualTesting.Tests.csproj | 80 +- .../MultipleResultsTest.cs | 10 +- .../AADFedAuthTokenRefreshTest.cs | 74 + .../SQL/AdapterTest/AdapterTest.cs | 29 +- .../ManualTests/SQL/AsyncTest/AsyncTest.cs | 2 +- .../SQL/AsyncTest/AsyncTimeoutTest.cs | 2 +- .../SQL/AsyncTest/XmlReaderAsyncTest.cs | 2 +- .../tests/ManualTests/SQL/Batch/BatchTests.cs | 644 ++ .../SystemDataInternals/FedAuthTokenHelper.cs | 108 + .../ConnectionPoolTest/ConnectionPoolTest.cs | 1 + .../CertificateTest.cs | 68 +- .../CertificateTestWithTdsServer.cs | 269 + .../GenerateSelfSignedCertificate.ps1 | 14 +- .../ConnectivityTests/AADConnectionTest.cs | 52 +- .../SQL/ConnectivityTests/ConnectivityTest.cs | 117 +- .../ConnectionSchemaTest.cs | 36 +- .../DataClassificationTest.cs | 2 +- .../DataReaderTest/DataReaderStreamsTest.cs | 2 +- .../SQL/DataReaderTest/DataReaderTest.cs | 36 +- .../DataSourceParserTest.cs | 75 + .../SQL/DataStreamTest/DataStreamTest.cs | 8 +- .../ExceptionTest/ConnectionExceptionTest.cs | 19 - .../SQL/ExceptionTest/ExceptionTest.cs | 19 +- .../SQL/InstanceNameTest/InstanceNameTest.cs | 201 +- .../IntegratedAuthenticationTest.cs | 2 +- .../SQL/JsonTest/JsonStreamTest.cs | 193 + .../ManualTests/SQL/JsonTest/JsonTest.cs | 340 + .../SQL/LocalDBTest/LocalDBTest.cs | 126 +- .../MARSSessionPoolingTest.cs | 4 +- .../ManualTests/SQL/MARSTest/MARSTest.cs | 2 +- .../SQL/ParameterTest/ParametersTest.cs | 144 +- .../SQL/ParameterTest/SteTypeBoundaries.cs | 2 +- .../ManualTests/SQL/ParameterTest/TvpTest.cs | 29 +- .../SQL/RandomStressTest/Randomizer.cs | 6 +- .../SQL/RetryLogic/RetryLogicConfigHelper.cs | 31 +- .../SQL/RetryLogic/RetryLogicCounterTest.cs | 4 +- .../SQL/RetryLogic/RetryLogicTestHelper.cs | 5 +- .../RetryLogic/SqlCommandReliabilityTest.cs | 239 +- .../SqlConfigurationManagerReliabilityTest.cs | 30 +- .../SqlConnectionReliabilityTest.cs | 10 +- .../SQL/SplitPacketTest/SplitPacketTest.cs | 2 +- .../SqlBulkCopyTest/InvalidAccessFromEvent.cs | 4 +- .../SQL/SqlBulkCopyTest/SqlBulkCopyTest.cs | 2 +- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 138 + .../SQL/SqlCommand/SqlCommandCancelTest.cs | 8 +- .../SqlCredentialTest/SqlCredentialTest.cs | 1 - .../SqlDependencyTest/SqlDependencyTest.cs | 4 +- .../SqlNotificationTest.cs | 2 +- .../SqlSchemaInfoTest/SqlSchemaInfoTest.cs | 20 +- .../DistributedTransactionTest.cs | 5 +- .../TransactionEnlistmentTest.cs | 12 +- .../SQL/UdtTest/SqlServerTypesTest.cs | 2 +- .../SQL/UdtTest/UDTs/Address/Address.csproj | 1 - .../SQL/UdtTest/UDTs/Circle/Circle.csproj | 1 - .../SQL/UdtTest/UDTs/Shapes/Shapes.csproj | 1 - .../UdtTest/UDTs/Utf8String/Utf8String.csproj | 1 - .../SQL/UdtTest/UdtBulkCopyTest.cs | 2 +- .../SQL/UdtTest/UdtDateTimeOffsetTest.cs | 143 + .../tests/ManualTests/SQL/UdtTest/UdtTest2.cs | 2 +- .../SQL/WeakRefTest/WeakRefTest.cs | 4 + .../WeakRefTestYukonSpecific.cs | 6 +- .../TracingTests/DiagnosticTest.cs | 243 +- .../ManualTests/TracingTests/TestTdsServer.cs | 52 +- .../tests/ManualTests/makepfxcert.ps1 | 158 + .../tests/ManualTests/mismatchedcert.cer | Bin 0 -> 919 bytes .../tests/ManualTests/removecert.ps1 | 21 + .../Microsoft.Data.SqlClient.NSLibrary.csproj | 13 - ...oft.Data.SqlClient.PerformanceTests.csproj | 3 +- ...crosoft.Data.SqlClient.ExtUtilities.csproj | 2 +- .../SqlDbManager.cs | 8 - .../Config.cs | 4 +- .../config.default.json | 3 - .../xunit.runner.json | 6 + .../Attributes/ActiveIssueAttribute.cs | 24 - .../Attributes/ConditionalClassAttribute.cs | 23 - .../Attributes/ConditionalFactAttribute.cs | 28 - .../Attributes/ConditionalTheoryAttribute.cs | 28 - .../Attributes/OuterLoopAttribute.cs | 20 - .../Attributes/PlatformSpecificAttribute.cs | 19 - .../Attributes/SkipOnCoreClrAttribute.cs | 21 - .../Attributes/SkipOnMonoAttribute.cs | 18 - .../SkipOnTargetFrameworkAttribute.cs | 19 - .../Attributes/TestCategoryAttribute.cs | 19 - .../ConditionalDiscovererException.cs | 13 - .../DesktopTraceListener.cs | 32 - .../DiscovererHelpers.cs | 26 - .../Discoverers/ActiveIssueDiscoverer.cs | 63 - .../Discoverers/ConditionalClassDiscoverer.cs | 70 - .../Discoverers/ConditionalFactDiscoverer.cs | 27 - .../Discoverers/ConditionalTestDiscoverer.cs | 180 - .../ConditionalTheoryDiscoverer.cs | 59 - .../Discoverers/OuterLoopTestsDiscoverer.cs | 27 - .../Discoverers/PlatformSpecificDiscoverer.cs | 39 - .../Discoverers/SkipOnCoreClrDiscoverer.cs | 103 - .../Discoverers/SkipOnMonoDiscoverer.cs | 39 - .../SkipOnTargetFrameworkDiscoverer.cs | 37 - .../Discoverers/TestCategoryDiscoverer.cs | 31 - .../Extensions/PlatformDetection.cs | 16 - .../Extensions/TheoryExtensions.cs | 38 - .../Microsoft.DotNet.XUnitExtensions.csproj | 56 - .../RuntimeStressTestModes.cs | 39 - .../SkippedFactTestCase.cs | 39 - .../SkippedTestCase.cs | 48 - .../SkippedTestMessageBus.cs | 50 - .../SkippedTheoryTestCase.cs | 39 - .../TargetFrameworkMonikers.cs | 17 - .../TestPlatforms.cs | 20 - .../XunitConstants.cs | 28 - .../tools/TDS/TDS.EndPoint/ITDSServer.cs | 10 +- .../TDS/TDS.EndPoint/ITDSServerSession.cs | 5 + .../TDS/TDS.EndPoint/TDS.EndPoint.csproj | 4 +- .../tools/TDS/TDS.EndPoint/TDSClientParser.cs | 2 +- .../tools/TDS/TDS.EndPoint/TDSServerParser.cs | 12 + .../tools/TDS/TDS.Servers/GenericTDSServer.cs | 34 +- .../TDS.Servers/GenericTDSServerSession.cs | 5 + .../tools/TDS/TDS.Servers/RoutingTDSServer.cs | 2 +- .../TDS/TDS/PreLogin/TDSPreLoginToken.cs | 5 +- .../TDSPreLoginTokenEncryptionType.cs | 3 +- .../tests/tools/TDS/TDS/TDSEncryptionType.cs | 7 +- .../tests/tools/TDS/TDS/TDSFeatureID.cs | 5 + .../tests/tools/TDS/TDS/TDSStream.cs | 4 + .../tests/tools/TDS/TDS/TDSUtilities.cs | 12 + .../Microsoft.SqlServer.Server.csproj | 3 - src/NuGet.config | 7 - src/docker-compose.dcproj | 3 - src/docker-compose.override.yml | 3 - src/docker-compose.yml | 2 +- .../Microsoft.DotNet.GenAPI.csproj | 2 +- tools/props/Versions.props | 61 +- tools/props/VersionsNet8OrLater.props | 10 + tools/specs/Microsoft.Data.SqlClient.nuspec | 231 +- tools/specs/Microsoft.SqlServer.Server.nuspec | 2 +- ...waysEncrypted.AzureKeyVaultProvider.nuspec | 85 +- tools/targets/GenerateNugetPackage.targets | 21 +- tools/targets/RepositoryInfo.targets | 40 + .../GenerateAKVProviderNugetPackage.targets | 2 +- tools/testsql/createUdtTestDb.sql | Bin 200366 -> 200788 bytes 705 files changed, 64741 insertions(+), 46828 deletions(-) create mode 100644 .config/CredScanSuppressions.json create mode 100644 .config/PolicheckExclusions.xml create mode 100644 NuGet.config create mode 100644 doc/samples/SqlBatch_ExecuteReader.cs create mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlBatch.xml create mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommand.xml create mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommandCollection.xml create mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml create mode 100644 doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml create mode 100644 doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml create mode 100644 eng/pipelines/common/templates/jobs/build-signed-akv-package-job.yml create mode 100644 eng/pipelines/common/templates/jobs/build-signed-package-job.yml create mode 100644 eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml create mode 100644 eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml create mode 100644 eng/pipelines/common/templates/jobs/ci-run-tests-job.yml create mode 100644 eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml create mode 100644 eng/pipelines/common/templates/jobs/validate-signed-package-job.yml create mode 100644 eng/pipelines/common/templates/stages/ci-run-tests-stage.yml create mode 100644 eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml create mode 100644 eng/pipelines/common/templates/steps/build-all-tests-step.yml create mode 100644 eng/pipelines/common/templates/steps/build-and-run-tests-netcore-step.yml create mode 100644 eng/pipelines/common/templates/steps/build-and-run-tests-netfx-step.yml create mode 100644 eng/pipelines/common/templates/steps/ci-prebuild-step.yml create mode 100644 eng/pipelines/common/templates/steps/ci-project-build-step.yml create mode 100644 eng/pipelines/common/templates/steps/code-analyze-step.yml create mode 100644 eng/pipelines/common/templates/steps/configure-sql-server-linux-step.yml create mode 100644 eng/pipelines/common/templates/steps/configure-sql-server-step.yml create mode 100644 eng/pipelines/common/templates/steps/configure-sql-server-win-step.yml create mode 100644 eng/pipelines/common/templates/steps/copy-dlls-for-test-step.yml create mode 100644 eng/pipelines/common/templates/steps/esrp-code-signing-step.yml create mode 100644 eng/pipelines/common/templates/steps/generate-nuget-package-step.yml create mode 100644 eng/pipelines/common/templates/steps/pre-build-step.yml create mode 100644 eng/pipelines/common/templates/steps/prepare-test-db-step.yml create mode 100644 eng/pipelines/common/templates/steps/publish-symbols-step.yml create mode 100644 eng/pipelines/common/templates/steps/publish-test-results-step.yml create mode 100644 eng/pipelines/common/templates/steps/run-all-tests-step.yml create mode 100644 eng/pipelines/common/templates/steps/update-config-file-step.yml create mode 100644 eng/pipelines/common/templates/steps/update-nuget-config-local-feed-step.yml create mode 100644 eng/pipelines/dotnet-sqlclient-ci-core.yml create mode 100644 eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml create mode 100644 eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml create mode 100644 eng/pipelines/dotnet-sqlclient-signing-pipeline.yml create mode 100644 eng/pipelines/libraries/akv-variables.yml create mode 100644 eng/pipelines/libraries/build-variables.yml create mode 100644 eng/pipelines/libraries/ci-build-variables.yml create mode 100644 eng/pipelines/libraries/common-variables.yml create mode 100644 eng/pipelines/libraries/mds-validation-variables.yml create mode 100644 eng/pipelines/libraries/mds-variables.yml create mode 100644 eng/pipelines/libraries/variables.yml create mode 100644 release-notes/2.1/2.1.7.md create mode 100644 release-notes/3.1/3.1.4.md create mode 100644 release-notes/3.1/3.1.5.md create mode 100644 release-notes/3.1/3.1.7.md create mode 100644 release-notes/4.0/4.0.4.md create mode 100644 release-notes/4.0/4.0.5.md create mode 100644 release-notes/4.0/4.0.6.md create mode 100644 release-notes/5.1/5.1.2.md create mode 100644 release-notes/5.1/5.1.3.md create mode 100644 release-notes/5.1/5.1.4.md create mode 100644 release-notes/5.1/5.1.5.md create mode 100644 release-notes/5.1/5.1.6.md create mode 100644 release-notes/5.2/5.2.0-preview4.md create mode 100644 release-notes/5.2/5.2.0-preview5.md create mode 100644 release-notes/5.2/5.2.1.md create mode 100644 release-notes/5.2/5.2.2.md create mode 100644 release-notes/5.2/5.2.md create mode 100644 release-notes/6.0/6.0.0-preview1.md create mode 100644 release-notes/6.0/6.0.md create mode 100644 release-notes/6.0/README.md create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/5.1/5.1.0.md create mode 100644 release-notes/add-ons/AzureKeyVaultProvider/5.1/README.md delete mode 100644 src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.NetStandard.cs rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Unix/Interop.Libraries.cs (92%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/Crypt32/Interop.certificates.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/Crypt32/Interop.certificates_types.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/SChannel/Interop.SecPkgContext_ApplicationProtocol.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src/CoreLib/Interop/Windows/Kernel32 => Interop/Windows/kernel32}/Interop.CloseHandle.cs (93%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/kernel32/Interop.FreeLibrary.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/kernel32/Interop.GetProcAddress.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/kernel32/Interop.LoadLibraryEx.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/GlobalSSPI.cs (93%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/Interop.SSPI.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/NegotiationInfoClass.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SSPIAuthType.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SSPIInterface.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SSPISecureChannelType.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SSPIWrapper.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SafeDeleteContext.cs (92%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecPkgContext_Bindings.cs (93%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs (93%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecPkgContext_Sizes.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecurityPackageInfo.cs (94%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecurityPackageInfoClass.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Interop/Windows/sspicli/SecuritySafeHandles.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Microsoft/Data/ProviderBase/DbConnectionInternal.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/Microsoft/Win32/SafeHandles/GssSafeHandles.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src/CoreLib => }/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Collections/Generic/BidirectionalDictionary.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src/CoreLib => }/System/IO/PathInternal.Windows.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/ContextFlagsAdapterPal.Unix.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/ContextFlagsAdapterPal.Windows.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/ContextFlagsPal.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs (96%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs (95%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/DebugSafeHandle.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/InternalException.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Logging/DebugThreadTracking.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Logging/NetEventSource.Common.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/NegotiationInfoClass.cs (94%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/NegotiateStreamPal.Unix.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/NegotiateStreamPal.Windows.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/NetEventSource.Security.Windows.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/NetEventSource.Security.cs (88%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/SecurityBuffer.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/SecurityBufferType.cs (96%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/SecurityContextTokenHandle.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/Unix/SafeDeleteContext.cs (97%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/Unix/SafeDeleteNegoContext.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/Unix/SafeFreeCredentials.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/Security/Unix/SafeFreeNegoCredentials.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/SecurityStatusAdapterPal.Windows.cs (99%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/Net/SecurityStatusPal.cs (98%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src => }/System/NotImplemented.cs (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Common/{src/CoreLib => }/System/Threading/Tasks/TaskToApm.cs (100%) delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Interop.BOOL.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetCurrentProcess_IntPtr.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.uap.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/LocalDB.uap.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.NetStandard.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs create mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnostic.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientFactory.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetStandard.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetStandard.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStaticMethods.cs delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/PinvokeAnalyzerExceptionList.analyzerdata.netstandard rename src/Microsoft.Data.SqlClient/netfx/src/Common/{src => }/Microsoft/Data/Common/NameValuePermission.cs (87%) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Common/src/Microsoft/Data/Common/DBDataPermissionAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbReferenceCollection.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Sql/SqlGenericUtil.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.Cng.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopyColumnMapping.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCertificateCallbacks.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlClientFactory.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlClientOriginalAddressInfo.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlUtil.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserHelperClasses.cs create mode 100644 src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.Batch.NetCoreApp.cs create mode 100644 src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.Batch.cs rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/Interop.Errors.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/Interop.Libraries.cs (95%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/Interop.UNICODE_STRING.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/Interop/Windows/kernel32 => src/Interop/Windows/Kernel32}/Interop.CTL_CODE.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/Interop/Windows/kernel32 => src/Interop/Windows/Kernel32}/Interop.DeviceIoControl.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/CoreLib => src}/Interop/Windows/Kernel32/Interop.FileTypes.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/CoreLib => src}/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/Interop/Windows/kernel32 => src/Interop/Windows/Kernel32}/Interop.IoControlCodeAccess.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/Interop/Windows/kernel32 => src/Interop/Windows/Kernel32}/Interop.IoControlTransferType.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common/src/CoreLib => src}/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/NtDll/Interop.FILE_FULL_EA_INFORMATION.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/NtDll/Interop.IO_STATUS_BLOCK.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/NtDll/Interop.NtCreateFile.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Interop/Windows/NtDll/Interop.RtlNtStatusToDosError.cs (100%) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/BitConverterCompatible.cs rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs (88%) rename src/Microsoft.Data.SqlClient/{netfx => }/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs (75%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs (87%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs (73%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs (71%) rename src/Microsoft.Data.SqlClient/{netcore/src/Common => }/src/Microsoft/Data/ProviderBase/DbReferenceCollection.cs (66%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/AAsyncCallContext.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/AlwaysEncryptedHelperClasses.cs (96%) rename src/Microsoft.Data.SqlClient/{netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.CrossPlatform.cs => src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.cs} (75%) delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveDelegate.NotSupported.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SSPI/ManagedSSPIContextProvider.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SSPI/NativeSSPIContextProvider.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SSPI/NegotiateSSPIContextProvider.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SSPI/SSPIContextProvider.cs rename src/Microsoft.Data.SqlClient/{netfx => }/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs (73%) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBatch.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBatchCommand.Net8OrGreater.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBatchCommand.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBatchCommandCollection.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientFactory.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs (84%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.Windows.cs (92%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.Windows.cs (92%) rename src/Microsoft.Data.SqlClient/{netfx => }/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.cs (52%) delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnclaveAttestationParameters.NotSupported.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/TdsParserHelperClasses.cs (93%) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlDbTypeExtensions.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlJson.cs rename src/Microsoft.Data.SqlClient/tests/{tools/Microsoft.DotNet.XUnitExtensions/Extensions => FunctionalTests}/AssertExtensions.cs (87%) create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/DataCommon/TestUtility.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlAuthenticationProviderTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlBufferTests.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionReadOnlyRoutingTests.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/TestRoutingTdsServer.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ColumnDecryptErrorTests.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/DateOnlyReadTests.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnDecryptErrorTestTable.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/DateOnlyTestTable.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ConnectionTestParameters.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ConnectionTestParametersData.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/Json/SqlJsonTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AADFedAuthTokenRefreshTest/AADFedAuthTokenRefreshTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Batch/BatchTests.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/SystemDataInternals/FedAuthTokenHelper.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionTestWithSSLCert/CertificateTestWithTdsServer.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataSourceParserTest/DataSourceParserTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/JsonTest/JsonStreamTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/JsonTest/JsonTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtDateTimeOffsetTest.cs create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/makepfxcert.ps1 create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/mismatchedcert.cer create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/removecert.ps1 delete mode 100644 src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/xunit.runner.json delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/ActiveIssueAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/ConditionalClassAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/ConditionalFactAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/ConditionalTheoryAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/OuterLoopAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/PlatformSpecificAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/SkipOnCoreClrAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/SkipOnMonoAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/SkipOnTargetFrameworkAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Attributes/TestCategoryAttribute.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/ConditionalDiscovererException.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/DesktopTraceListener.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/DiscovererHelpers.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/ActiveIssueDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/ConditionalClassDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/ConditionalFactDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/ConditionalTestDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/ConditionalTheoryDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/OuterLoopTestsDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/PlatformSpecificDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/SkipOnCoreClrDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/SkipOnMonoDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/SkipOnTargetFrameworkDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Discoverers/TestCategoryDiscoverer.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Extensions/PlatformDetection.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Extensions/TheoryExtensions.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/Microsoft.DotNet.XUnitExtensions.csproj delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/RuntimeStressTestModes.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/SkippedFactTestCase.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/SkippedTestCase.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/SkippedTestMessageBus.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/SkippedTheoryTestCase.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/TargetFrameworkMonikers.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/TestPlatforms.cs delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.DotNet.XUnitExtensions/XunitConstants.cs delete mode 100644 src/NuGet.config delete mode 100644 src/docker-compose.override.yml create mode 100644 tools/props/VersionsNet8OrLater.props create mode 100644 tools/targets/RepositoryInfo.targets diff --git a/.config/CredScanSuppressions.json b/.config/CredScanSuppressions.json new file mode 100644 index 0000000000..ffc7e87789 --- /dev/null +++ b/.config/CredScanSuppressions.json @@ -0,0 +1,25 @@ +{ + "tool": "Credential Scanner", + "suppressions": [ + { + "file": "src/Microsoft.Data.SqlClient/tests/Docker/DockerLinuxTest/Program.cs", + "justification": "Test projects should be skipped" + }, + { + "file": "src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs", + "justification": "Test projects should be skipped" + }, + { + "file": "src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TdsServerCertificate.pfx", + "justification": "Test projects should be skipped" + }, + { + "file": "src/docker-compose.yml", + "justification": "Docker test project should be excluded" + }, + { + "file": "doc/samples/SqlConnectionStringBuilder.cs", + "justification": "Documentation could include sample data and can be ignored" + } + ] +} diff --git a/.config/PolicheckExclusions.xml b/.config/PolicheckExclusions.xml new file mode 100644 index 0000000000..a4269513d1 --- /dev/null +++ b/.config/PolicheckExclusions.xml @@ -0,0 +1,5 @@ + + SRC/MICROSOFT.DATA.SQLCLIENT/TESTS + .YML|.MD|.SQL + NOTICE.TXT|SQLDATAADAPTER.CS + \ No newline at end of file diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json index a9be6f5aae..c9e3a2cfb6 100644 --- a/.config/tsaoptions.json +++ b/.config/tsaoptions.json @@ -1,11 +1,14 @@ { "instanceUrl": "https://sqlclientdrivers.visualstudio.com/", - "projectName": "ADO.NET", - "areaPath": "ADO.NET", - "iterationPath": "ADO.NET", + "projectName": "ADO.Net", + "areaPath": "ADO.Net", + "iterationPath": "ADO.Net\\TSA\\SqlClient", "notificationAliases": [ "SqlClient@microsoft.com" ], "repositoryName": "SqlClient", "codebaseName": "SqlClient", "allTools": true, - "template": "MSDATA_RevolutionR" + "template": "MSDATA_RevolutionR", + "language": "csharp", + "includePathPatterns": "src/Microsoft.Data.SqlClient/*, src/Microsoft.SqlServer.Server/*, tools/*", + "excludePathPatterns": "src/Microsoft.Data.SqlClient/tests/*" } diff --git a/.editorconfig b/.editorconfig index db85dde7fd..b2014e3974 100644 --- a/.editorconfig +++ b/.editorconfig @@ -169,3 +169,7 @@ dotnet_code_quality.ca1802.api_surface = private, internal [*.cs] dotnet_code_quality.CA2100.excluded_type_names_with_derived_types = Microsoft.Data.SqlClient.ManualTesting.Tests.* +dotnet_diagnostic.xUnit1031.severity=none +dotnet_diagnostic.xUnit1030.severity=none + + diff --git a/.gitignore b/.gitignore index daeaf68c7a..bb6f58f9bd 100644 --- a/.gitignore +++ b/.gitignore @@ -353,6 +353,9 @@ healthchecksdb # Backup folder for Package Reference Convert tool in Visual Studio 2017 MigrationBackup/ +# JetBrains Rider (cross platform .NET IDE) working folder +.idea/ + # Ionide (cross platform F# VS Code tools) working folder .ionide/ diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 47cacc9fb7..09143c84cf 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -8,6 +8,8 @@ This project should be built with Visual Studio 2019+ for the best compatibility - **Visual Studio 2019** with imported components: [VS19Components](/tools/vsconfig/VS19Components.vsconfig) +- **Powershell**: To build SqlClient on Linux, powershell is needed as well. Follow the distro specific instructions at [Install Powershell on Linux](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux?view=powershell-7.4) + Once the environment is setup properly, execute the desired set of commands below from the _root_ folder to perform the respective operations: ## Building the driver @@ -102,7 +104,7 @@ msbuild -t:RunTests -p:configuration=Release -p:DotnetPath=C:\net6-win-x86\ To specify custom target framework, use `TF` property: ```bash -msbuild -t:RunTests -p:configuration=Release -p:TF=net7.0 +msbuild -t:RunTests -p:configuration=Release -p:TF=net8.0 msbuild -t:RunTests -p:configuration=Release -p:TF=net48 # Runs tests for specified target framework. # TargetNetCoreVersion and TargetNetFxVersion are not to be used with TF property, they will take precedence over TF if provided. @@ -165,7 +167,6 @@ Manual Tests require the below setup to run: |TCPConnectionString | Connection String for a TCP enabled SQL Server instance. | `Server={servername};Database={Database_Name};Trusted_Connection=True;`
OR `Data Source={servername};Initial Catalog={Database_Name};Integrated Security=True;`| |NPConnectionString | Connection String for a Named Pipes enabled SQL Server instance.| `Server=\\{servername}\pipe\sql\query;Database={Database_Name};Trusted_Connection=True;`
OR
`Data Source=np:{servername};Initial Catalog={Database_Name};Integrated Security=True;`| |TCPConnectionStringHGSVBS | (Optional) Connection String for a TCP enabled SQL Server with Host Guardian Service (HGS) attestation protocol configuration. | `Server=tcp:{servername}; Database={Database_Name}; UID={UID}; PWD={PWD}; Attestation Protocol = HGS; Enclave Attestation Url = {AttestationURL};`| - |TCPConnectionStringAASVBS | (Optional) Connection String for a TCP enabled SQL Server with a VBS Enclave and using Microsoft Azure Attestation (AAS) attestation protocol configuration. | `Server=tcp:{servername}; Database={Database_Name}; UID={UID}; PWD={PWD}; Attestation Protocol = AAS; Enclave Attestation Url = {AttestationURL};`| |TCPConnectionStringNoneVBS | (Optional) Connection String for a TCP enabled SQL Server with a VBS Enclave and using None Attestation protocol configuration. | `Server=tcp:{servername}; Database={Database_Name}; UID={UID}; PWD={PWD}; Attestation Protocol = NONE;`| |TCPConnectionStringAASSGX | (Optional) Connection String for a TCP enabled SQL Server with a SGX Enclave and using Microsoft Azure Attestation (AAS) attestation protocol configuration. | `Server=tcp:{servername}; Database={Database_Name}; UID={UID}; PWD={PWD}; Attestation Protocol = AAS; Enclave Attestation Url = {AttestationURL};`| |EnclaveEnabled | Enables tests requiring an enclave-configured server.| @@ -176,15 +177,12 @@ Manual Tests require the below setup to run: |AADSecurePrincipalSecret | (Optional) A Secret defined for a registered application which has been granted permission to the database defined in the AADPasswordConnectionString. | {Secret} | |AzureKeyVaultURL | (Optional) Azure Key Vault Identifier URL | `https://{keyvaultname}.vault.azure.net/` | |AzureKeyVaultTenantId | (Optional) The Azure Active Directory tenant (directory) Id of the service principal. | _{Tenant ID of Active Directory}_ | - |AzureKeyVaultClientId | (Optional) "Application (client) ID" of an Active Directory registered application, granted access to the Azure Key Vault specified in `AZURE_KEY_VAULT_URL`. Requires the key permissions Get, List, Import, Decrypt, Encrypt, Unwrap, Wrap, Verify, and Sign. | _{Client Application ID}_ | - |AzureKeyVaultClientSecret | (Optional) "Client Secret" of the Active Directory registered application, granted access to the Azure Key Vault specified in `AZURE_KEY_VAULT_URL` | _{Client Application Secret}_ | |SupportsIntegratedSecurity | (Optional) Whether or not the USER running tests has integrated security access to the target SQL Server.| `true` OR `false`| |LocalDbAppName | (Optional) If Local Db Testing is supported, this property configures the name of Local DB App instance available in client environment. Empty string value disables Local Db testing. | Name of Local Db App to connect to.| |LocalDbSharedInstanceName | (Optional) If LocalDB testing is supported and the instance is shared, this property configures the name of the shared instance of LocalDB to connect to. | Name of shared instance of LocalDB. | |FileStreamDirectory | (Optional) If File Stream is enabled on SQL Server, pass local directory path to be used for setting up File Stream enabled database. | `D:\\escaped\\absolute\\path\\to\\directory\\` | |UseManagedSNIOnWindows | (Optional) Enables testing with Managed SNI on Windows| `true` OR `false`| |DNSCachingConnString | Connection string for a server that supports DNS Caching| - |IsAzureSynpase | (Optional) When set to 'true', test suite runs compatible tests for Azure Synapse/Parallel Data Warehouse. | `true` OR `false`| |EnclaveAzureDatabaseConnString | (Optional) Connection string for Azure database with enclaves | |ManagedIdentitySupported | (Optional) When set to `false` **Managed Identity** related tests won't run. The default value is `true`. | |IsManagedInstance | (Optional) When set to `true` **TVP** related tests will use on non-Azure bs files to compare test results. this is needed when testing against Managed Instances or TVP Tests will fail on Test set 3. The default value is `false`. | @@ -234,17 +232,15 @@ Tests can be built and run with custom "Reference Type" property that enables di - "Project" => Build and run tests with Microsoft.Data.SqlClient as Project Reference - "Package" => Build and run tests with Microsoft.Data.SqlClient as Package Reference with configured "TestMicrosoftDataSqlClientVersion" in "Versions.props" file. -- "NetStandard" => Build and run tests with Microsoft.Data.SqlClient as Project Reference via .NET Standard Library -- "NetStandardPackage" => Build and run tests with Microsoft.Data.SqlClient as Package Reference via .NET Standard Library -> ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" AND "NETSTANDARDPACKAGE" REFERENCE TYPES *************** +> ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" REFERENCE TYPE *************** > CREATE A NUGET PACKAGE WITH BELOW COMMAND AND ADD TO LOCAL FOLDER + UPDATE NUGET CONFIG FILE TO READ FROM THAT LOCATION > > ```bash > msbuild -p:configuration=Release > ``` -A non-AnyCPU platform reference can only be used with package and NetStandardPackage reference types. Otherwise, the specified platform will be replaced with AnyCPU in the build process. +A non-AnyCPU platform reference can only be used with package reference type. Otherwise, the specified platform will be replaced with AnyCPU in the build process. ### Building Tests with Reference Type @@ -255,10 +251,6 @@ msbuild -t:BuildTestsNetCore -p:ReferenceType=Project # Default setting uses Project Reference. msbuild -t:BuildTestsNetCore -p:ReferenceType=Package - -msbuild -t:BuildTestsNetCore -p:ReferenceType=NetStandard - -msbuild -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage ``` For .NET Framework, below reference types are supported: @@ -293,7 +285,7 @@ msbuild -t:BuildTestsNetFx -p:TargetNetFxVersion=net462 ```bash msbuild -t:BuildTestsNetCore -p:TargetNetCoreVersion=net6.0 # Build the tests for custom TargetFramework (.NET) -# Applicable values: net6.0 | net7.0 +# Applicable values: net6.0 | net8.0 ``` ### Running Tests with custom target framework (traditional) @@ -305,7 +297,7 @@ dotnet test -p:TargetNetFxVersion=net462 ... dotnet test -p:TargetNetCoreVersion=net6.0 ... # Use above property to run Functional Tests with custom TargetFramework (.NET) -# Applicable values: net6.0 | net7.0 +# Applicable values: net6.0 | net8.0 ``` ## Using Managed SNI on Windows @@ -389,7 +381,7 @@ Configure `runnerconfig.json` file with connection string and preferred settings ```bash cd src\Microsoft.Data.SqlClient\tests\PerformanceTests -dotnet run -c Release -f net6.0|net7.0 +dotnet run -c Release -f net6.0|net8.0 ``` _Only "**Release** Configuration" applies to Performance Tests_ diff --git a/CHANGELOG.md b/CHANGELOG.md index 09b07617a8..0d8052f809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,213 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +## [Preview Release 6.0.0-preview1.24240.8] - 2024-08-27 + +This update brings the below changes over the previous release: + +### Breaking Changes + +- Removed support for .NET Standard. [#2386](https://github.com/dotnet/SqlClient/pull/2386) +- Removed UWP (uap) references. [#2483](https://github.com/dotnet/SqlClient/pull/2483) + +### Added + +- Added `TokenCredential` object to take advantage of token caching in `ActiveDirectoryAuthenticationProvider`. [#2380](https://github.com/dotnet/SqlClient/pull/2380) +- Added `DateOnly` and `TimeOnly` support to `DataTable` as a structured parameter. [#2258](https://github.com/dotnet/SqlClient/pull/2258) +- Added `Microsoft.Data.SqlClient.Diagnostics.SqlClientDiagnostic` type in .NET. [#2226](https://github.com/dotnet/SqlClient/pull/2226) +- Added scope trace for `GenerateSspiClientContext`. [#2497](https://github.com/dotnet/SqlClient/pull/2497), [#2725](https://github.com/dotnet/SqlClient/pull/2725) + +### Fixed + +- Fixed `Socket.Connect` timeout issue caused by thread starvation. [#2777](https://github.com/dotnet/SqlClient/pull/2777) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2618](https://github.com/dotnet/SqlClient/pull/2618) +- Fixed Entra authentication when using infinite connection timeout in `ActiveDirectoryAuthenticationProvider`. [#2651](https://github.com/dotnet/SqlClient/pull/2651) +- Fixed `GetSchema` by excluding unsupported engines due to lack of support for `ASSEMBLYPROPERTY` function. [#2593](https://github.com/dotnet/SqlClient/pull/2593) +- Fixed SSPI retry negotiation with default port in .NET. [#2559](https://github.com/dotnet/SqlClient/pull/2559) +- Fixed assembly path in .NET 8.0 and `.AssemblyAttributes`. [#2550](https://github.com/dotnet/SqlClient/pull/2550) +- Fixed certificate chain validation. [#2487](https://github.com/dotnet/SqlClient/pull/2487) +- Fixed clone of `SqlConnection` to include `AccessTokenCallback`. [#2525](https://github.com/dotnet/SqlClient/pull/2525) +- Fixed issue with `DateTimeOffset` in table-valued parameters, which was introduced in 5.2. [#2453](https://github.com/dotnet/SqlClient/pull/2453) +- Fixed `ArgumentNullException` on `SqlDataRecord.GetValue` when using user-defined data type on .NET. [#2448](https://github.com/dotnet/SqlClient/pull/2448) +- Fixed `SqlBuffer` and `SqlGuild` when it's null. [#2310](https://github.com/dotnet/SqlClient/pull/2310) +- Fixed `SqlBulkCopy.WriteToServer` state in a consecutive calls. [#2375](https://github.com/dotnet/SqlClient/pull/2375) +- Fixed null reference exception with `SqlConnection.FireInfoMessageEventOnUserErrors` after introducing the batch command. [#2399](https://github.com/dotnet/SqlClient/pull/2399) + +### Changed + +- Updated Microsoft.Data.SqlClient.SNI version to `6.0.0-preview1.24226.4`. [#2772](https://github.com/dotnet/SqlClient/pull/2772) +- Improved access to `SqlAuthenticationProviderManager.Instance` and avoid early object initiation. [#2636](https://github.com/dotnet/SqlClient/pull/2636) +- Removed undocumented properties of `Azure.Identity` in `ActiveDirectoryAuthenticationProvider`. [#2562](https://github.com/dotnet/SqlClient/pull/2562) +- Replaced `System.Runtime.Caching` with `Microsoft.Extensions.Caching.Memory`. [#2493](https://github.com/dotnet/SqlClient/pull/2493) +- Updated `EnableOptimizedParameterBinding` to only accept text mode commands. [#2417](https://github.com/dotnet/SqlClient/pull/2417) +- Updated `Azure.Identity` version from `1.10.3` to `1.11.4`. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Updated `Azure.Core` version from `1.35.0` to `1.38.0`. [#2462](https://github.com/dotnet/SqlClient/pull/2462) +- Updated `Azure.Security.KeyVault.Keys` version from `4.4.0` to `4.5.0`. [#2462](https://github.com/dotnet/SqlClient/pull/2462) +- Updated `Microsoft.IdentityModel.JsonWebTokens` and `Microsoft.IdentityModel.Protocols.OpenIdConnect` from `6.35.0` to `7.5.0`. [#2429](https://github.com/dotnet/SqlClient/pull/2429) +- Removed direct dependency to `Microsoft.Identity.Client` to take the transient dependecy through `Azure.Identity`. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Removed unnecessary references `Microsoft.Extensions.Caching.Memory` and `System.Security.Cryptography.Cng` after removing .NET Standard. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Improved memory allocation when reader opened by `CommandBehavior.SequentialAccess` over the big string columns. [#2356](https://github.com/dotnet/SqlClient/pull/2356) +- Improved SSPI by consolidating the context generation to single abstraction and using memory/span for SSPI generation. [#2255](https://github.com/dotnet/SqlClient/pull/2255), [#2447](https://github.com/dotnet/SqlClient/pull/2447) +- Reverted the [#2281](https://github.com/dotnet/SqlClient/pull/2281) code changes on ManagedSNI. [#2395](https://github.com/dotnet/SqlClient/pull/2395) +- Updated assembly version to 6.0.0.0. [#2382](https://github.com/dotnet/SqlClient/pull/2382) +- Code health improvements: [#2366](https://github.com/dotnet/SqlClient/pull/2366), [#2369](https://github.com/dotnet/SqlClient/pull/2369), [#2381](https://github.com/dotnet/SqlClient/pull/2381), [#2390](https://github.com/dotnet/SqlClient/pull/2390), [#2392](https://github.com/dotnet/SqlClient/pull/2392), [#2403](https://github.com/dotnet/SqlClient/pull/2403), [#2410](https://github.com/dotnet/SqlClient/pull/2410), [#2413](https://github.com/dotnet/SqlClient/pull/2413), [#2425](https://github.com/dotnet/SqlClient/pull/2425), [#2428](https://github.com/dotnet/SqlClient/pull/2428), [#2440](https://github.com/dotnet/SqlClient/pull/2440), [#2443](https://github.com/dotnet/SqlClient/pull/2443), [#2450](https://github.com/dotnet/SqlClient/pull/2450), [#2466](https://github.com/dotnet/SqlClient/pull/2466), [#2486](https://github.com/dotnet/SqlClient/pull/2486), [#2521](https://github.com/dotnet/SqlClient/pull/2521), [#2522](https://github.com/dotnet/SqlClient/pull/2522), [#2533](https://github.com/dotnet/SqlClient/pull/2533), [#2552](https://github.com/dotnet/SqlClient/pull/2552), [#2560](https://github.com/dotnet/SqlClient/pull/2560), [#2726](https://github.com/dotnet/SqlClient/pull/2726), [#2751](https://github.com/dotnet/SqlClient/pull/2751), [#2811](https://github.com/dotnet/SqlClient/pull/2811) + +## [Stable release 5.2.2] - 2024-08-27 + +### Fixed + +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2650](https://github.com/dotnet/SqlClient/pull/2650) +- Fixed issue with `Socket.Connect` in managed SNI. [#2779](https://github.com/dotnet/SqlClient/pull/2779) +- Fixed path for `AssemblyAttributes` in obj folder causing NET 8.0 assembly to appear in NET 6.0 dll. [#2789](https://github.com/dotnet/SqlClient/pull/2789) +- Fixed SSPI retry negotiation with default port in .NET. [#2815](https://github.com/dotnet/SqlClient/pull/2815) +- Fixed `ArgumentNullException` on `SqlDataRecord.GetValue` when using user-defined data type on .NET. [#2816](https://github.com/dotnet/SqlClient/pull/2816) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2817](https://github.com/dotnet/SqlClient/pull/2817) + +### Changed + +- Upgraded `Azure.Identity` version from 1.11.3 to 1.11.4 [#2648](https://github.com/dotnet/SqlClient/pull/2648) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Upgraded `Microsoft.Identity.Client` version from 4.60.0 to 4.61.3 [#2648](https://github.com/dotnet/SqlClient/pull/2648) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Added caching to `TokenCredential` objects to take advantage of token caching. [#2775](https://github.com/dotnet/SqlClient/pull/2775) + +## [Stable release 5.2.1] - 2024-05-31 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed connection errors on Linux when Data Source property contains both named instance and port [#2436](https://github.com/dotnet/SqlClient/pull/2436) +- Fixed `SqlConnection.FireInfoMessageEventOnUserErrors` when set to true throws an exception [#2505](https://github.com/dotnet/SqlClient/pull/2505) +- Fixed exception when using `DATETIMEOFFSET(n)` in a TVP if `n` is 1, 2, 3, or 4 [#2506](https://github.com/dotnet/SqlClient/pull/2506) +- Reverted PR [#1983](https://github.com/dotnet/SqlClient/pull/1938) which caused connection failure delays when using `OpenAsync` [#2507](https://github.com/dotnet/SqlClient/pull/2507) +- Fixed `SqlConnection.Clone()` to include `AccessTokenCallback` [#2527](https://github.com/dotnet/SqlClient/pull/2527) + +### Changed + +- Upgraded `Azure.Identity` version from 1.10.3 to 1.11.3 [#2492](https://github.com/dotnet/SqlClient/pull/2492), [#2528](https://github.com/dotnet/SqlClient/pull/2528) +- Upgraded `Microsoft.Identity.Client` version from 4.56.0 to 4.60.3 [#2492](https://github.com/dotnet/SqlClient/pull/2492) +- Code Health improvements: [#2467](https://github.com/dotnet/SqlClient/pull/2467) + +## [Stable release 5.2.0] - 2024-02-28 + +### Added + +- Added a new `AccessTokenCallBack` API to `SqlConnection`. [#1260](https://github.com/dotnet/SqlClient/pull/1260) +- Added `SqlBatch` support on .NET 6+ [#1825](https://github.com/dotnet/SqlClient/pull/1825), [#2223](https://github.com/dotnet/SqlClient/pull/2223),[#2371](https://github.com/dotnet/SqlClient/pull/2371), [#2373](https://github.com/dotnet/SqlClient/pull/2373) +- Added support of `SqlDiagnosticListener` on **.NET Standard**. [#1931](https://github.com/dotnet/SqlClient/pull/1931) +- Added new property `RowsCopied64` to `SqlBulkCopy`. [#2004](https://github.com/dotnet/SqlClient/pull/2004) +- Added support for the `SuperSocketNetLib` registry option for Encrypt on .NET on Windows. [#2047](https://github.com/dotnet/SqlClient/pull/2047) +- Added the ability to generate debugging symbols in a separate package file [#2137](https://github.com/dotnet/SqlClient/pull/2137) +- Added Workload Identity authentication support [#2159](https://github.com/dotnet/SqlClient/pull/2159), [#2264](https://github.com/dotnet/SqlClient/pull/2264) +- Added support for Big Endian systems [#2170](https://github.com/dotnet/SqlClient/pull/2170) +- Added support for Georgian collation [#2194](https://github.com/dotnet/SqlClient/pull/2194) +- Added Localization support on .NET [#2210](https://github.com/dotnet/SqlClient/pull/2110) +- Added .NET 8 support [#2230](https://github.com/dotnet/SqlClient/pull/2230) +- Added explicit version for major .NET version dependencies on System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0, and System.Diagnostics. +- DiagnosticSource 8.0.0 [#2303](https://github.com/dotnet/SqlClient/pull/2303) + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) +- Fixed behavior when error class is greater than 20 on connection retry. [#1953](https://github.com/dotnet/SqlClient/pull/1953) +- Fixed error message when symmetric key decryption failed using Always Encrypted. [#1948](https://github.com/dotnet/SqlClient/pull/1948) +- Fixed TransactionScope connection issue when Enlist is enable, Pooling is disabled and network connection type is Redirect. [#1960](https://github.com/dotnet/SqlClient/pull/1960) +- Fixed TDS RPC error on large queries in SqlCommand.ExecuteReaderAsync. [#1936](https://github.com/dotnet/SqlClient/pull/1936) +- Fixed throttling of token requests by calling AcquireTokenSilent. [#1925](https://github.com/dotnet/SqlClient/pull/1925) +- Fixed Linux code coverage result in Build proj. [#1950](https://github.com/dotnet/SqlClient/pull/1950) +- Fixed NullReferenceException in GetBytesAsync. [#1906](https://github.com/dotnet/SqlClient/pull/1906) +- Fixed Transient fault handling issue with OpenAsync. [#1983](https://github.com/dotnet/SqlClient/pull/1983) +- Fixed invariant mode checks. [#1917](https://github.com/dotnet/SqlClient/pull/1917) +- Fixed GC behavior in TdsParser by adding array rental capability in TryReadPlpUnicodeChars. [#1866](https://github.com/dotnet/SqlClient/pull/1866) +- Fixed socket synchronization issue during connect in managed SNI. [#1029](https://github.com/dotnet/SqlClient/pull/1029) +- Fixed issue with `SqlConnectionStringBuilder` property indexer not supporting non-string values. [#2018](https://github.com/dotnet/SqlClient/pull/2018) +- Fixed `SqlDataAdapter.Fill` and configurable retry logic issue on .NET Framework. [#2084](https://github.com/dotnet/SqlClient/pull/2084) +- Fixed `SqlConnectionEncryptOption` type conversion by introducing the `SqlConnectionEncryptOptionConverter` attribute when using **appsettings.json** files. [#2057](https://github.com/dotnet/SqlClient/pull/2057) +- Fixed th-TH culture info issue on Managed SNI. [#2066](https://github.com/dotnet/SqlClient/pull/2066) +- Fixed an issue when using the Authentication option, but not encrypting on .NET Framework where the server certificate was being incorrectly validated [#2224](https://github.com/dotnet/SqlClient/pull/2224) +- Fixed a deadlock problem for distributed transactions when on .NET [#2161](https://github.com/dotnet/SqlClient/pull/2161) +- Fixed an issue with connecting to named instances on named pipes in managed SNI (Linux/macOS) [#2142](https://github.com/dotnet/SqlClient/pull/2142) +- Fixed LocalDb connection issue with an invalid source when using managed SNI [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed an `AccessViolationException` when using a SQL Express user instance [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed a metadata query issue when connecting to Azure SQL Edge [#2099](https://github.com/dotnet/SqlClient/pull/2099) +- Fixed file version information for .NET and .NET Standard binaries [#2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed the SPN sent for a named instance when using Kerberos authentication on Linux/macOS [#2240](https://github.com/dotnet/SqlClient/pull/2240) +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2275](https://github.com/dotnet/SqlClient/pull/2275) +- Fixed token caching to prevent expired access tokens from being reused in a connection pool [#2273](https://github.com/dotnet/SqlClient/pull/2273) + +### Changed + +- Improved parsing buffered characters in `TdsParser`. [#1544](https://github.com/dotnet/SqlClient/pull/1544) +- Added Microsoft.SqlServer.Types to verify support for SqlHierarchyId and Spatial for .NET Core. [#1848](https://github.com/dotnet/SqlClient/pull/1848) +- Moved to new System.Data.SqlTypes APIs on **.NET 7** and up. [#1934](https://github.com/dotnet/SqlClient/pull/1934) and [#1981](https://github.com/dotnet/SqlClient/pull/1981) +- Removed reference to Microsoft.Win32.Registry since it's shipped starting with .NET 6.0. [#1974](https://github.com/dotnet/SqlClient/pull/1974) +- Changed **[UseOneSecFloorInTimeoutCalculationDuringLogin](https://learn.microsoft.com/sql/connect/ado-net/appcontext-switches#enable-a-minimum-timeout-during-login)** App Context switch default to **true** and extended its effect to .NET and .NET Standard. [#2012](https://github.com/dotnet/SqlClient/pull/2012) +- Updated `Microsoft.Identity.Client` version from 4.47.2 to 4.53.0. [#2031](https://github.com/dotnet/SqlClient/pull/2031), [#2055](https://github.com/dotnet/SqlClient/pull/2055) +- Switched to the new .NET [NegotiateAuthentication](https://learn.microsoft.com/en-us/dotnet/api/system.net.security.negotiateauthentication?view=net-7.0) API on .NET 7.0 and above for SSPI token negotiation using Managed SNI. [#2063](https://github.com/dotnet/SqlClient/pull/2063) +- Removed `ignoreSniOpenTimeout` in open connection process on Windows. [#2067](https://github.com/dotnet/SqlClient/pull/2067) +- Enforce explicit ordinal for internal `StringComparison` operations. [#2068](https://github.com/dotnet/SqlClient/pull/2068) +- Improved error messages when validating server certificates in managed SNI (Linux/macOS) [#2060](https://github.com/dotnet/SqlClient/pull/2060) +- Improved CPU usage when `AppContext` switches are in use [#2227](https://github.com/dotnet/SqlClient/pull/2227) +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27), [#2189](https://github.com/dotnet/SqlClient/pull/2189) +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2290](https://github.com/dotnet/SqlClient/pull/2290) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET/.NET Standard dependency) version to `v5.2.0`. [#2363](https://github.com/dotnet/SqlClient/pull/2363), which includes removing dead code and addressing static analysis warnings +- Code health improvements: [#1198](https://github.com/dotnet/SqlClient/pull/1198), [#1829](https://github.com/dotnet/SqlClient/pull/1829), [#1943](https://github.com/dotnet/SqlClient/pull/1943), [#1949](https://github.com/dotnet/SqlClient/pull/1949), [#1959](https://github.com/dotnet/SqlClient/pull/1959), [#1985](https://github.com/dotnet/SqlClient/pull/1985), [#2071](https://github.com/dotnet/SqlClient/pull/2071), [#2073](https://github.com/dotnet/SqlClient/pull/2073), [#2088](https://github.com/dotnet/SqlClient/pull/2088), [#2091](https://github.com/dotnet/SqlClient/pull/2091), [#2098](https://github.com/dotnet/SqlClient/pull/2098), [#2121](https://github.com/dotnet/SqlClient/pull/2121), [#2122](https://github.com/dotnet/SqlClient/pull/2122), [#2132](https://github.com/dotnet/SqlClient/pull/2132), [#2136](https://github.com/dotnet/SqlClient/pull/2136), [#2144](https://github.com/dotnet/SqlClient/pull/2144), [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2157](https://github.com/dotnet/SqlClient/pull/2157), [#2164](https://github.com/dotnet/SqlClient/pull/2164), [#2166](https://github.com/dotnet/SqlClient/pull/2166), [#2168](https://github.com/dotnet/SqlClient/pull/2168), [#2186](https://github.com/dotnet/SqlClient/pull/2186), [#2254](https://github.com/dotnet/SqlClient/pull/2254), [#2288](https://github.com/dotnet/SqlClient/pull/2288), [#2305](https://github.com/dotnet/SqlClient/pull/2305), [#2317](https://github.com/dotnet/SqlClient/pull/2317) + +## [Preview Release 5.2.0-preview5.24024.3] - 2024-01-24 + +This update brings the below changes over the previous release: + +### Added + +- Added .NET 8 support [#2230](https://github.com/dotnet/SqlClient/pull/2230) +- Added explicit version for major .NET version dependencies on System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0, and System.Diagnostics.DiagnosticSource 8.0.0 [#2303](https://github.com/dotnet/SqlClient/pull/2303) +- Added the ability to generate debugging symbols in a separate package file [#2137](https://github.com/dotnet/SqlClient/pull/2137) + +### Changed + +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2290](https://github.com/dotnet/SqlClient/pull/2290) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2275](https://github.com/dotnet/SqlClient/pull/2275) +- Fixed token caching to prevent expired access tokens from being reused in a connection pool [#2273](https://github.com/dotnet/SqlClient/pull/2273) +- Code health improvements: [#2288](https://github.com/dotnet/SqlClient/pull/2288), [#2305](https://github.com/dotnet/SqlClient/pull/2305), [#2254](https://github.com/dotnet/SqlClient/pull/2254), [#2317](https://github.com/dotnet/SqlClient/pull/2317) + +## [Preview Release 5.2.0-preview4.23342.2] - 2023-12-08 + +This update brings the below changes over the previous release: + +### Added + +- Added `SqlBatch` support on .NET 6+ [#1825](https://github.com/dotnet/SqlClient/pull/1825), [#2223](https://github.com/dotnet/SqlClient/pull/2223) +- Added Workload Identity authentication support [#2159](https://github.com/dotnet/SqlClient/pull/2159), [#2264](https://github.com/dotnet/SqlClient/pull/2264) +- Added Localization support on .NET [#2210](https://github.com/dotnet/SqlClient/pull/2110) +- Added support for Georgian collation [#2194](https://github.com/dotnet/SqlClient/pull/2194) +- Added support for Big Endian systems [#2170](https://github.com/dotnet/SqlClient/pull/2170) + +### Changed + +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET/.NET Standard dependency) version to `v5.2.0-preview1.23340.1`. [#2257](https://github.com/dotnet/SqlClient/pull/2257), which includes removing dead code and addressing static analysis warnings +- Improved CPU usage when `AppContext` switches are in use [#2227](https://github.com/dotnet/SqlClient/pull/2227) +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27), [#2188](https://github.com/dotnet/SqlClient/pull/2188) +- Improved error messages when validating server certificates in managed SNI (Linux/macOS) [#2060](https://github.com/dotnet/SqlClient/pull/2060) + +### Fixed + +- Fixed an issue when using the Authentication option, but not encrypting on .NET Framework where the server certificate was being incorrectly validated [#2224](https://github.com/dotnet/SqlClient/pull/2224) +- Fixed a deadlock problem for distributed transactions when on .NET [#2161](https://github.com/dotnet/SqlClient/pull/2161) +- Fixed an issue with connecting to named instances on named pipes in managed SNI (Linux/macOS)[#2142](https://github.com/dotnet/SqlClient/pull/2142) +- Fixed LocalDb connection issue with an invalid source when using managed SNI [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed an `AccessViolationException` when using a SQL Express user instance [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed a metadata query issue when connecting to Azure SQL Edge [#2099](https://github.com/dotnet/SqlClient/pull/2099) +- Fixed file version information for .NET and .NET Standard binaries[#2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed the SPN sent for a named instance when using Kerberos authentication on Linux/macOS [#2240](https://github.com/dotnet/SqlClient/pull/2240) +- Various code improvements [#2091](https://github.com/dotnet/SqlClient/pull/2091), [#2098](https://github.com/dotnet/SqlClient/pull/2098), [#2121](https://github.com/dotnet/SqlClient/pull/2121), [#2122](https://github.com/dotnet/SqlClient/pull/2122), [#2132](https://github.com/dotnet/SqlClient/pull/2132), [#2136](https://github.com/dotnet/SqlClient/pull/2136), [#2144](https://github.com/dotnet/SqlClient/pull/2144), [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2157](https://github.com/dotnet/SqlClient/pull/2157), [#2164](https://github.com/dotnet/SqlClient/pull/2164), [#2166](https://github.com/dotnet/SqlClient/pull/2166), [#2168](https://github.com/dotnet/SqlClient/pull/2168), [#2186](https://github.com/dotnet/SqlClient/pull/2186) + +This update brings the below changes over the previous release: + ## [Preview Release 5.2.0-preview3.23201.1] - 2023-07-20 This update brings the below changes over the previous release: @@ -77,6 +284,74 @@ This update brings the below changes over the previous release: - Added Microsoft.SqlServer.Types to verify support for SqlHierarchyId and Spatial for .NET Core. [#1848](https://github.com/dotnet/SqlClient/pull/1848) - Code health improvements:[#1943](https://github.com/dotnet/SqlClient/pull/1943)[#1949](https://github.com/dotnet/SqlClient/pull/1949)[#1198](https://github.com/dotnet/SqlClient/pull/1198)[#1829](https://github.com/dotnet/SqlClient/pull/1829) +## [Stable release 5.1.6] - 2024-08-27 + +### Fixed + +- Fixed Transient fault handling issue with `OpenAsync`. [#1983](https://github.com/dotnet/SqlClient/pull/1983) [#2508](https://github.com/dotnet/SqlClient/pull/2508) +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2706](https://github.com/dotnet/SqlClient/pull/2706) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2618](https://github.com/dotnet/SqlClient/pull/2618) [#2818](https://github.com/dotnet/SqlClient/pull/2818) + +### Changed + +- Upgraded `Azure.Identity` version from 1.11.3 to 1.11.4 [#2649] (https://github.com/dotnet/SqlClient/pull/2649) [#2529] (https://github.com/dotnet/SqlClient/pull/2529) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Upgraded `Microsoft.Identity.Client` version from 4.60.0 to 4.61.3 [#2649] (https://github.com/dotnet/SqlClient/pull/2649) [#2529] (https://github.com/dotnet/SqlClient/pull/2529) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Added caching to `TokenCredential` objects to take advantage of token caching. [#2776](https://github.com/dotnet/SqlClient/pull/2776) +- Code health improvements: [#2490] (https://github.com/dotnet/SqlClient/pull/2490) + +## [Stable release 5.1.5] - 2024-01-29 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2321](https://github.com/dotnet/SqlClient/pull/2321) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2324](https://github.com/dotnet/SqlClient/pull/2324) + +### Changed + +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2320](https://github.com/dotnet/SqlClient/pull/2320) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) + +## [Stable release 5.1.4] - 2024-01-09 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed a deadlock problem for distributed transactions when on .NET. + +### Changed + +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27). + +## [Stable release 5.1.3] - 2024-01-09 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## [Stable release 5.1.2] - 2023-10-26 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed access violation when using SQL Express user instance. [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed non-string values and `SqlConnectionStringBuilder` property indexer issue. [#2018](https://github.com/dotnet/SqlClient/pull/2018) +- Fixed `SqlConnectionEncryptOption` type conversion by introducing the `SqlConnectionEncryptOptionConverter` attribute when using **appsettings.json** files. [#2057](https://github.com/dotnet/SqlClient/pull/2057) +- Fixed Transient fault handling issue with `OpenAsync`. [#1983](https://github.com/dotnet/SqlClient/pull/1983) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) + +### Changed + +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET Core/Standard dependency) version to `5.1.1`. [#2123](https://github.com/dotnet/SqlClient/pull/2123) + ## [Stable release 5.1.1] - 2023-03-28 This update brings the below changes over the previous release: @@ -312,6 +587,33 @@ This update brings the below changes over the previous release: - Added new Attestation Protocol `None` for `VBS` enclave types. This protocol will allow users to forgo enclave attestation for VBS enclaves. [#1419](https://github.com/dotnet/SqlClient/pull/1419) [#1425](https://github.com/dotnet/SqlClient/pull/1425) +## [Stable release 4.0.6] - 2024-08-21 + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) [#2435](https://github.com/dotnet/SqlClient/pull/2435) +- Fixed AcquireTokenAsync timeout handling for edge cases in ActiveDirectoryAuthenticationProvider [#2707](https://github.com/dotnet/SqlClient/pull/2707) + +### Changed + +- Code health improvements: [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2513](https://github.com/dotnet/SqlClient/pull/2513), [#2519](https://github.com/dotnet/SqlClient/pull/2519) + +## [Stable release 4.0.5] - 2024-01-09 + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## [Stable release 4.0.4] - 2023-10-30 + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) + ## [Stable release 4.0.3] - 2023-04-20 ### Fixed @@ -452,6 +754,36 @@ This update brings the below changes over the previous release: - Optimized async method allocations in .NET Framework by porting changes from .NET Core. [#1084](https://github.com/dotnet/SqlClient/pull/1084) - Various code improvements [#902](https://github.com/dotnet/SqlClient/pull/902) [#925](https://github.com/dotnet/SqlClient/pull/925) [#933](https://github.com/dotnet/SqlClient/pull/933) [#934](https://github.com/dotnet/SqlClient/pull/934) [#1024](https://github.com/dotnet/SqlClient/pull/1024) [#1057](https://github.com/dotnet/SqlClient/pull/1057) [#1122](https://github.com/dotnet/SqlClient/pull/1122) [#1133](https://github.com/dotnet/SqlClient/pull/1133) [#1134](https://github.com/dotnet/SqlClient/pull/1134) [#1141](https://github.com/dotnet/SqlClient/pull/1141) [#1187](https://github.com/dotnet/SqlClient/pull/1187) [#1188](https://github.com/dotnet/SqlClient/pull/1188) [#1223](https://github.com/dotnet/SqlClient/pull/1223) [#1225](https://github.com/dotnet/SqlClient/pull/1225) [#1226](https://github.com/dotnet/SqlClient/pull/1226) +## [Stable release 3.1.7] - 2024-08-20 + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool. [#2301](https://github.com/dotnet/SqlClient/pull/2301) [#2434](https://github.com/dotnet/SqlClient/pull/2434) +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2709](https://github.com/dotnet/SqlClient/pull/2709) +- Fixed the signing issue with `Microsoft.Data.SqlClient` assembly. [#2789](https://github.com/dotnet/SqlClient/pull/2789) + +### Changed + +- Updated Microsoft.Data.SqlClient.SNI version 3.0.1 to 3.0.2 [#2676](https://github.com/dotnet/SqlClient/pull/2676) which includes the fix for AppDomain crashing in issue [#1418](https://github.com/dotnet/SqlClient/issues/1418) and various code refactors. +- Code health improvements: [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2515](https://github.com/dotnet/SqlClient/pull/2515), [#2517](https://github.com/dotnet/SqlClient/pull/2517) addresses [CVE-2019-0545](https://github.com/advisories/GHSA-2xjx-v99w-gqf3), [#2539](https://github.com/dotnet/SqlClient/pull/2539) + +## [Stable release 3.1.5] - 2024-01-09 + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## [Stable release 3.1.4] - 2023-10-31 + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) +- Fixed FormatException when event source tracing is enabled. [#1291](https://github.com/dotnet/SqlClient/pull/1291) + ## [Stable release 3.1.3] - 2023-03-10 ### Fixed @@ -521,6 +853,13 @@ This update brings the below changes over the previous release: - Modified column encryption key store provider registrations to give built-in system providers precedence over providers registered on connection and command instances. [#1101](https://github.com/dotnet/SqlClient/pull/1101) +## [Stable Release 2.1.7] - 2024-01-09 + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + ## [Stable Release 2.1.6] - 2023-04-27 ### Fixed @@ -915,7 +1254,7 @@ This update brings the below changes over the previous release: - Improved performance of Managed SNI by enhancing utilization of resources [#173](https://github.com/dotnet/SqlClient/pull/173) - Ported [dotnet/corefx#35363](https://github.com/dotnet/corefx/pull/35363) and [dotnet/corefx#40732](https://github.com/dotnet/corefx/pull/40732) - Improved performance of Managed SNI RPC Parameter Usage [#209](https://github.com/dotnet/SqlClient/pull/209) - Ported [dotnet/corefx#34049](https://github.com/dotnet/corefx/pull/34049) - Changed enclave key map to be lazy initialized [#372](https://github.com/dotnet/SqlClient/pull/372) -- Changed `Recieve()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) +- Changed `Receive()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) - Changed `EnclaveProviderBase` caching implementation to support Async Scenarios _(Introduces breaking changes)_ [#346](https://github.com/dotnet/SqlClient/pull/346) ## [Stable Release 1.1.0] - 2019-11-20 diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..3233e60161 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/README.md b/README.md index 29f8950a49..e19c9fb88b 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,17 @@ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/dotnet/sqlclient/master/LICENSE) [![Nuget](https://img.shields.io/nuget/dt/Microsoft.Data.SqlClient?label=Nuget.org%20Downloads&style=flat-square&color=blue)](https://www.nuget.org/packages/Microsoft.Data.SqlClient) -[![Gitter](https://img.shields.io/gitter/room/badges/shields.svg?style=flat-square&color=blue)](https://gitter.im/Microsoft/mssql-developers) -[![Build status](https://sqlclientdrivers.visualstudio.com/public/_apis/build/status/ADO/CI-SqlClient)](https://sqlclientdrivers.visualstudio.com/public/_build/latest?definitionId=1139) +[![Build status](https://sqlclientdrivers.visualstudio.com/public/_apis/build/status/ADO/CI-SqlClient)](https://sqlclientdrivers.visualstudio.com/public/_build/latest?definitionId=1879) # Microsoft SqlClient Data Provider for SQL Server -Welcome to the home of the Microsoft ADO.NET driver for SQL Server aka the Microsoft.Data.SqlClient GitHub repository. - -Microsoft.Data.SqlClient is a data provider for Microsoft SQL Server and Azure SQL Database. Now in General Availability, it is a union of the two System.Data.SqlClient components which live independently in .NET Framework and .NET Core. Going forward, support for new SQL Server features will be implemented in Microsoft.Data.SqlClient. +Microsoft.Data.SqlClient is a .NET data provider for [Microsoft SQL Server]([url](https://aka.ms/sql)) and the [Azure SQL]([url](https://aka.ms/azure_sql)) family of databases. It grew from a union of the two System.Data.SqlClient components which live independently in .NET Framework and .NET Core. Going forward, support for new SQL Server and Azure SQL features will only be implemented in Microsoft.Data.SqlClient. ## Supportability -The Microsoft.Data.SqlClient package supports the below environments: +The Microsoft.Data.SqlClient package supports the following environments: - .NET Framework 4.6.2+ -- .NET Core 3.1+ -- .NET Standard 2.0+ - -The source code of this library is now available under the MIT license. +- .NET 6.0+ ## Download @@ -25,9 +19,9 @@ The Microsoft.Data.SqlClient NuGet package is available on [NuGet.org](https://w ## SNI Package References -For the .NET Framework driver on Windows, a package reference to [Microsoft.Data.SqlClient.SNI](https://www.nuget.org/packages/Microsoft.Data.SqlClient.SNI/) loads native `Microsoft.Data.SqlClient.SNI.x64.dll` and `Microsoft.Data.SqlClient.SNI.x86.dll` libraries into the client's build directories. +When targeting .NET Framework on Windows, a package reference to [Microsoft.Data.SqlClient.SNI](https://www.nuget.org/packages/Microsoft.Data.SqlClient.SNI/) loads native `Microsoft.Data.SqlClient.SNI..dll` libraries into the client's build directories. -For the .NET Core driver on Windows, a package reference to [Microsoft.Data.SqlClient.SNI.runtime](https://www.nuget.org/packages/Microsoft.Data.SqlClient.SNI.runtime/) loads `arm`, `arm64`, `x64` and `x86` native `Microsoft.Data.SqlClient.SNI.dll` libraries into the client's build directories. +When targeting .NET on Windows, a package reference to [Microsoft.Data.SqlClient.SNI.runtime](https://www.nuget.org/packages/Microsoft.Data.SqlClient.SNI.runtime/) loads `arm64`, `x64` and `x86` native `Microsoft.Data.SqlClient.SNI.dll` libraries into subdirectories in the client's build directory. ## Helpful Links @@ -40,7 +34,6 @@ For the .NET Core driver on Windows, a package reference to [Microsoft.Data.SqlC | Support Policy | [SUPPORT.md](SUPPORT.md) | | Code of Conduct | [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | | Copyright Information | [COPYRIGHT.md](COPYRIGHT.md) | -| | | ## Our Featured Contributors @@ -65,7 +58,7 @@ All preview and stable driver release notes are available under [release-notes]( ## Porting from System.Data.SqlClient -Refer to [porting-cheat-sheet.md](porting-cheat-sheet.md) for a safe porting experience from System.Data.SqlClient to Microsoft.Data.SqlClient and share your experience with us by advancing this guide for future developers. +Refer to [porting-cheat-sheet.md](porting-cheat-sheet.md) for a safe porting experience from System.Data.SqlClient to Microsoft.Data.SqlClient and share your experience with us by enhancing this guide for future developers. ## Still have questions? @@ -85,7 +78,7 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). diff --git a/RunPackageReferenceTests.cmd b/RunPackageReferenceTests.cmd index fd37b9c7ba..fa503f905e 100644 --- a/RunPackageReferenceTests.cmd +++ b/RunPackageReferenceTests.cmd @@ -1,10 +1,10 @@ @echo off -:: .NET CORE + .NET STANDARD LIBRARY TEST CASES +:: .NET CORE TEST CASES echo Building .NET Core Tests call :pauseOnError msbuild -t:Clean -:: ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" AND "NETSTANDARDPACKAGE" REFERENCE TYPES *************** +:: ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" REFERENCE TYPE *************** :: THESE ARE NOT STAND ALONE TEST COMMANDS AND NEED A DEVELOPER'S SPECIAL ATTENTION TO WORK. ATTEMPTING TO RUN THE ENTIRE SET OF COMMANDS AS-IS IS LIKELY TO FAIL! :: CREATE A NUGET PACKAGE WITH BELOW COMMAND AND ADD TO LOCAL FOLDER + UPDATE NUGET CONFIG FILE TO READ FROM THAT LOCATION @@ -24,25 +24,25 @@ call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:Re call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-functional-anycpu.xml call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-manual-anycpu.xml -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-manual-anycpu.xml +call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:TargetNetCoreVersion=net8.0 +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-functional-anycpu.xml +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-manual-anycpu.xml call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=x64 -p:TargetNetCoreVersion=net6.0 call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-functional-x64.xml call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-manual-x64.xml -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=x64 -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-functional-x64.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-manual-x64.xml +call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=x64 -p:TargetNetCoreVersion=net8.0 +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-functional-x64.xml +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-manual-x64.xml call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=Win32 -p:TargetNetCoreVersion=net6.0 call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-functional-win32.xml call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net6.0-manual-win32.xml -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=Win32 -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-functional-win32.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net7.0-manual-win32.xml +call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=Package -p:Platform=Win32 -p:TargetNetCoreVersion=net8.0 +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-functional-win32.xml +call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net8.0 -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net8.0-manual-win32.xml :: .NET Framework - REFERENCE TYPE "PACKAGE" @@ -70,74 +70,6 @@ call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:Targ call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Platform="Win32" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" -p:TargetNetFxVersion=net48 --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net48-functional-Win32.xml call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Platform="Win32" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" -p:TargetNetFxVersion=net48 --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:ReferenceType=Package -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\package-net48-manual-Win32.xml -:: REFERENCE TYPE "NETSTANDARDPACKAGE" - -:: .NET - REFERENCE TYPE "NETSTANDARDPACKAGE" - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:TargetNetCoreVersion=net6.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-manual-anycpu.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-manual-anycpu.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:Platform=x64 -p:TargetNetCoreVersion=net6.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-functional-x64.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-manual-x64.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:Platform=x64 -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-functional-x64.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-manual-x64.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:Platform=Win32 -p:TargetNetCoreVersion=net6.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-functional-win32.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net6.0-manual-win32.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandardPackage -p:Platform=Win32 -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-functional-win32.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net7.0-manual-win32.xml - -:: .NET Framework - REFERENCE TYPE "NETSTANDARDPACKAGE" - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:TargetNetFxVersion=net462 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-manual-anycpu.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:TargetNetFxVersion=net48 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-manual-anycpu.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:Platform=x64 -p:TargetNetFxVersion=net462 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-functional-x64.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-manual-x64.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:Platform=x64 -p:TargetNetFxVersion=net48 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-functional-x64.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="x64" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-manual-x64.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:Platform=Win32 -p:TargetNetFxVersion=net462 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-functional-win32.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetFxVersion=net462 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net462-manual-win32.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetFx -p:ReferenceType=NetStandardPackage -p:Platform=Win32 -p:TargetNetFxVersion=net48 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-functional-win32.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" -p:Platform="Win32" -p:TargetNetFxVersion=net48 -p:ReferenceType=NetStandardPackage -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandardpackage-net48-manual-win32.xml - -:: REFERENCE TYPE "NETSTANDARD" (We only build and test AnyCPU with Project Reference) -:: NUGET PACKAGE GENERATION IS NOT SUPPORTED FOR REFERNCE TYPE 'NETSTANDARD' -call :pauseOnError msbuild -p:Configuration="Release" -p:ReferenceType=NetStandard -p:GenerateNuget=false -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandard -p:TargetNetCoreVersion=net6.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandard -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandard-net6.0-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net6.0 -p:ReferenceType=NetStandard -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandard-net6.0-manual-anycpu.xml - -call :pauseOnError msbuild -p:Configuration="Release" -t:BuildTestsNetCore -p:ReferenceType=NetStandard -p:TargetNetCoreVersion=net7.0 -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandard -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandard-net7.0-functional-anycpu.xml -call :pauseOnError dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Configuration="Release" -p:TestTargetOS="Windowsnetcoreapp" --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests" -p:Platform="AnyCPU" -p:TargetNetCoreVersion=net7.0 -p:ReferenceType=NetStandard -l:trx;LogFileName=..\..\..\..\..\artifacts\Results\netstandard-net7.0-manual-anycpu.xml - -:: TESTING 'NETSTANDARD' REFERENCE TYPE WITH .NET FRAMEWORK 4.6.2+ AS TARGET FRAMEWORK IS INVALID CASE AS PROJECT REFERENCE DOES NOT LOAD SNI.DLL IN .NET FRAMEWORK RUNTIME. -:: CASE IS VERIFIED WITH RUNTIME.NATIVE.SYSTEM.DATA.SQLCLIENT.SNI AS WELL. TO TEST .NET FRAMEWORK TARGETS, USE 'NETSTANDARDPACKAGE' REFERENCE TYPE ONLY. - goto :eof :pauseOnError diff --git a/RunProjectReferenceTests.cmd b/RunProjectReferenceTests.cmd index afab55f2a5..ee4a8bca9a 100644 --- a/RunProjectReferenceTests.cmd +++ b/RunProjectReferenceTests.cmd @@ -6,8 +6,8 @@ set netcoreVersion=net6.0 :: Accept two parameters for .NET Framework and .NET versions. :: Examples: -:: - uses net48 and net7.0: -:: > RunProjectReferenceTests.cmd net48 net7.0 +:: - uses net48 and net8.0: +:: > RunProjectReferenceTests.cmd net48 net8.0 :: - uses default target frameworks: :: > RunProjectReferenceTests.cmd :: - uses net48 and default target frameworks for netcore: diff --git a/build.proj b/build.proj index 465f9264c3..8b3310906d 100644 --- a/build.proj +++ b/build.proj @@ -6,6 +6,9 @@ + + false + src\NuGet.config Debug AnyCPU @@ -34,6 +37,10 @@ The provided path should be ended to a `\` character without white spaces: Ex. C:\x86\ --> + + DebugType=portable;DebugSymbols=true;IncludeSymbols=true;SymbolPackageFormat=snupkg;PublishRepositoryUrl=true;RepositoryUrl=https://github.com/dotnet/sqlclient;RepositoryType=git;EmbedUnTrackedSources=true;Deterministic=true; + + $(NugetPackProperties);ContinuousIntegrationBuild=true; @@ -49,22 +56,18 @@ - - - - @@ -111,7 +114,20 @@ - + + + + + + + + + + + + + + @@ -177,16 +193,16 @@ - + - + - + - + @@ -200,11 +216,11 @@ - + - + @@ -217,12 +233,6 @@ - - - - - - @@ -230,10 +240,4 @@ - - - - - - diff --git a/doc/samples/AADAuthenticationCustomDeviceFlowCallback.cs b/doc/samples/AADAuthenticationCustomDeviceFlowCallback.cs index bda3554bbe..d225f64ae8 100644 --- a/doc/samples/AADAuthenticationCustomDeviceFlowCallback.cs +++ b/doc/samples/AADAuthenticationCustomDeviceFlowCallback.cs @@ -1,4 +1,4 @@ -// +// using System; using System.Threading.Tasks; using Microsoft.Identity.Client; diff --git a/doc/samples/AzureKeyVaultProviderExample.cs b/doc/samples/AzureKeyVaultProviderExample.cs index e16a9a63a7..5bd89bb2fd 100644 --- a/doc/samples/AzureKeyVaultProviderExample.cs +++ b/doc/samples/AzureKeyVaultProviderExample.cs @@ -79,11 +79,13 @@ public static void Main(string[] args) } } + // Maintain an instance of the ClientCredential object to take advantage of underlying token caching + private static ClientCredential clientCredential = new ClientCredential(s_clientId, s_clientSecret); + public static async Task AzureActiveDirectoryAuthenticationCallback(string authority, string resource, string scope) { var authContext = new AuthenticationContext(authority); - ClientCredential clientCred = new ClientCredential(s_clientId, s_clientSecret); - AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred); + AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCredential); if (result == null) { throw new InvalidOperationException($"Failed to retrieve an access token for {resource}"); diff --git a/doc/samples/AzureKeyVaultProviderWithEnclaveProviderExample.cs b/doc/samples/AzureKeyVaultProviderWithEnclaveProviderExample.cs index 2091dab322..8b9423ffe8 100644 --- a/doc/samples/AzureKeyVaultProviderWithEnclaveProviderExample.cs +++ b/doc/samples/AzureKeyVaultProviderWithEnclaveProviderExample.cs @@ -81,11 +81,13 @@ static void Main(string[] args) } } + // Maintain an instance of the ClientCredential object to take advantage of underlying token caching + private static ClientCredential clientCredential = new ClientCredential(s_clientId, s_clientSecret); + public static async Task AzureActiveDirectoryAuthenticationCallback(string authority, string resource, string scope) { var authContext = new AuthenticationContext(authority); - ClientCredential clientCred = new ClientCredential(s_clientId, s_clientSecret); - AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred); + AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCredential); if (result == null) { throw new InvalidOperationException($"Failed to retrieve an access token for {resource}"); diff --git a/doc/samples/CustomDeviceCodeFlowAzureAuthenticationProvider.cs b/doc/samples/CustomDeviceCodeFlowAzureAuthenticationProvider.cs index 68d792fef5..7b0de07be1 100644 --- a/doc/samples/CustomDeviceCodeFlowAzureAuthenticationProvider.cs +++ b/doc/samples/CustomDeviceCodeFlowAzureAuthenticationProvider.cs @@ -1,8 +1,11 @@ -// +// using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; -using Microsoft.Identity.Client; using Microsoft.Data.SqlClient; +using Microsoft.Identity.Client; namespace CustomAuthenticationProviderExamples { @@ -12,31 +15,52 @@ namespace CustomAuthenticationProviderExamples /// public class CustomDeviceCodeFlowAzureAuthenticationProvider : SqlAuthenticationProvider { + private const string ClientId = "my-client-id"; + private const string ClientName = "My Application Name"; + private const string DefaultScopeSuffix = "/.default"; + + // Maintain a copy of the PublicClientApplication object to cache the underlying access tokens it provides + private static IPublicClientApplication pcApplication; + public override async Task AcquireTokenAsync(SqlAuthenticationParameters parameters) { - string clientId = "my-client-id"; - string clientName = "My Application Name"; - string s_defaultScopeSuffix = "/.default"; + string[] scopes = [ parameters.Resource.EndsWith(DefaultScopeSuffix) ? parameters.Resource : parameters.Resource + DefaultScopeSuffix ]; - string[] scopes = new string[] { parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix }; + IPublicClientApplication app = pcApplication; + if (app == null) + { + pcApplication = app = PublicClientApplicationBuilder.Create(ClientId) + .WithAuthority(parameters.Authority) + .WithClientName(ClientName) + .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") + .Build(); + } - IPublicClientApplication app = PublicClientApplicationBuilder.Create(clientId) - .WithAuthority(parameters.Authority) - .WithClientName(clientName) - .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") - .Build(); + AuthenticationResult result; + using CancellationTokenSource connectionTimeoutCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(parameters.ConnectionTimeout)); + + try + { + IEnumerable accounts = await app.GetAccountsAsync(); + result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) + .ExecuteAsync(connectionTimeoutCancellation.Token); + } + catch (MsalUiRequiredException) + { + result = await app.AcquireTokenWithDeviceCode(scopes, deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)) + .ExecuteAsync(connectionTimeoutCancellation.Token); + } - AuthenticationResult result = await app.AcquireTokenWithDeviceCode(scopes, - deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)).ExecuteAsync(); return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); } - public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) => authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow); + public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) + => authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow); - private Task CustomDeviceFlowCallback(DeviceCodeResult result) + private static Task CustomDeviceFlowCallback(DeviceCodeResult result) { Console.WriteLine(result.Message); - return Task.FromResult(0); + return Task.CompletedTask; } } diff --git a/doc/samples/SqlBatch_ExecuteReader.cs b/doc/samples/SqlBatch_ExecuteReader.cs new file mode 100644 index 0000000000..eec4e09abf --- /dev/null +++ b/doc/samples/SqlBatch_ExecuteReader.cs @@ -0,0 +1,43 @@ +// +using Microsoft.Data.SqlClient; + +class Program +{ + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + using var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + var results = new List(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } +} +// diff --git a/doc/samples/SqlBulkCopy_ColumnMapping.cs b/doc/samples/SqlBulkCopy_ColumnMapping.cs index 6908e2bbdd..af72a4803d 100644 --- a/doc/samples/SqlBulkCopy_ColumnMapping.cs +++ b/doc/samples/SqlBulkCopy_ColumnMapping.cs @@ -47,9 +47,9 @@ static void Main() new SqlBulkCopyColumnMapping("Name", "ProdName"); bulkCopy.ColumnMappings.Add(mapName); - SqlBulkCopyColumnMapping mapMumber = + SqlBulkCopyColumnMapping mapNumber = new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum"); - bulkCopy.ColumnMappings.Add(mapMumber); + bulkCopy.ColumnMappings.Add(mapNumber); // Write from the source to the destination. try diff --git a/doc/samples/SqlBulkCopy_ColumnMappingRemoveAt.cs b/doc/samples/SqlBulkCopy_ColumnMappingRemoveAt.cs index 9d8091965d..948b3ed05d 100644 --- a/doc/samples/SqlBulkCopy_ColumnMappingRemoveAt.cs +++ b/doc/samples/SqlBulkCopy_ColumnMappingRemoveAt.cs @@ -116,7 +116,7 @@ static void Main() bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; // Rather than clearing mappings that are not necessary - // for the next bulk copyo peration, the unneeded mappings + // for the next bulk copy operation, the unneeded mappings // are removed with the RemoveAt method. bulkCopy.ColumnMappings.RemoveAt(2); bulkCopy.ColumnMappings.RemoveAt(1); diff --git a/doc/samples/SqlConnection_AccessTokenCallback.cs b/doc/samples/SqlConnection_AccessTokenCallback.cs index c761f640fd..3477e8a4de 100644 --- a/doc/samples/SqlConnection_AccessTokenCallback.cs +++ b/doc/samples/SqlConnection_AccessTokenCallback.cs @@ -1,8 +1,11 @@ using System; -using System.Data; // -using Microsoft.Data.SqlClient; +using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; using Azure.Identity; +using Microsoft.Data.SqlClient; class Program { @@ -12,18 +15,41 @@ static void Main() Console.ReadLine(); } + const string defaultScopeSuffix = "/.default"; + + // Reuse credential objects to take advantage of underlying token caches + private static ConcurrentDictionary credentials = new ConcurrentDictionary(); + + // Use a shared callback function for connections that should be in the same connection pool + private static Func> myAccessTokenCallback = + async (authParams, cancellationToken) => + { + string scope = authParams.Resource.EndsWith(defaultScopeSuffix) + ? authParams.Resource + : $"{authParams.Resource}{defaultScopeSuffix}"; + + DefaultAzureCredentialOptions options = new DefaultAzureCredentialOptions(); + options.ManagedIdentityClientId = authParams.UserId; + + // Reuse the same credential object if we are using the same MI Client Id + AccessToken token = await credentials.GetOrAdd(authParams.UserId, new DefaultAzureCredential(options)).GetTokenAsync( + new TokenRequestContext(new string[] { scope }), + cancellationToken); + + return new SqlAuthenticationToken(token.Token, token.ExpiresOn); + }; + private static void OpenSqlConnection() { - string connectionString = GetConnectionString(); - using (SqlConnection connection = new SqlConnection("Data Source=contoso.database.windows.net;Initial Catalog=AdventureWorks;") + // (Optional) Pass a User-Assigned Managed Identity Client ID. + // This will ensure different MI Client IDs are in different connection pools. + string connectionString = "Server=myServer.database.windows.net;Encrypt=Mandatory;UserId=;"; + + using (SqlConnection connection = new SqlConnection(connectionString) { - AccessTokenCallback = async (authParams, cancellationToken) => - { - var cred = new DefaultAzureCredential(); - string scope = authParams.Resource.EndsWith(s_defaultScopeSuffix) ? authParams.Resource : authParams.Resource + s_defaultScopeSuffix; - var token = await cred.GetTokenAsync(new TokenRequestContext(new[] { scope }), cancellationToken); - return new SqlAuthenticationToken(token.Token, token.ExpiresOn); - } + // The callback function is part of the connection pool key. Using a static callback function + // ensures connections will not create a new pool per connection just for the callback. + AccessTokenCallback = myAccessTokenCallback }) { connection.Open(); diff --git a/doc/snippets/Microsoft.Data.Sql/SqlDataSourceEnumerator.xml b/doc/snippets/Microsoft.Data.Sql/SqlDataSourceEnumerator.xml index 55e1f2c057..c06899ed01 100644 --- a/doc/snippets/Microsoft.Data.Sql/SqlDataSourceEnumerator.xml +++ b/doc/snippets/Microsoft.Data.Sql/SqlDataSourceEnumerator.xml @@ -1,65 +1,187 @@ - - - + + - Provides a mechanism for enumerating all available instances of SQL Server within the local network. - - class exposes this information to the application developer, providing a containing information about all the available servers. This returned table contains a list of server instances that matches the list provided when a user attempts to create a new connection, and on the `Connection Properties` dialog box, expands the drop-down list containing all the available servers. - - ]]> - - Enumerating Instances of SQL Server - - - Retrieves a containing information about all visible SQL Server instances. - A containing information about the visible SQL Server instances. - -
10.0.xx for SQL Server 2008
10.50.x for SQL Server 2008 R2
11.0.xx for SQL Server 2012
12.0.xx for SQL Server 2014
13.0.xx for SQL Server 2016
14.0.xx for SQL Server 2017| - -> [!NOTE] -> Due to the nature of the mechanism used by to locate data sources on a network, the method will not always return a complete list of the available servers, and the list might not be the same on every call. If you plan to use this function to let users select a server from a list, make sure that you always also supply an option to type in a name that is not in the list, in case the server enumeration does not return all the available servers. In addition, this method may take a significant amount of time to execute, so be careful about calling it when performance is critical. - -## Examples - The following console application retrieves information about all the visible SQL Server instances and displays the information in the console window. - -[!code-csharp[SqlDataSourceEnumerator.Example#1](~/../sqlclient/doc/samples/SqlDataSourceEnumeratorExample.cs#1)] - - ]]>
-
- Enumerating Instances of SQL Server -
+ + Provides a mechanism for enumerating all available instances of SQL Server within the local network. + + + SQL Server makes it possible for applications to determine the existence of its instances within the current network. The class exposes this information to the application developer, providing a containing information about all the available servers. This returned table contains a list of server instances that matches the list provided when a user attempts to create a new connection, and on the Connection Properties dialog box, expands the drop-down list containing all the available servers. + + + Enumerating Instances of SQL Server + + + + + Retrieves a containing information about all visible SQL Server instances. + + + A containing information about the visible SQL Server instances. + + + + The table returned by this method contains the following columns, all of which contain strings: + + + + + Column + Description + + + ServerName + Name of the server. + + + InstanceName + Name of the server instance. Blank if the server is running as the default instance. + + + IsClustered + Indicates whether the server is part of a cluster. + + + Version + + Version of the server: + + 10.0.xx for SQL Server 2008 + 10.50.x for SQL Server 2008 R2 + 11.0.xx for SQL Server 2012 + 12.0.xx for SQL Server 2014 + 13.0.xx for SQL Server 2016 + 14.0.xx for SQL Server 2017 + + + + + + Due to the nature of the mechanism used by to locate data sources on a network, the method will not always return a complete list of the available servers, and the list might not be the same on every call. If you plan to use this function to let users select a server from a list, make sure that you always also supply an option to type in a name that is not in the list, in case the server enumeration does not return all the available servers. In addition, this method may take a significant amount of time to execute, so be careful about calling it when performance is critical. + + + + + + The following console application retrieves information about all the visible SQL Server instances and displays the information in the console window. + + + + using System; + using Microsoft.Data.Sql; + + class Program + { + static void Main() + { + // Retrieve the enumerator instance and then the data. + SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance; + System.Data.DataTable table = instance.GetDataSources(); + + // Display the contents of the table. + DisplayData(table); + + Console.WriteLine("Press any key to continue."); + Console.ReadKey(); + } + + private static void DisplayData(System.Data.DataTable table) + { + foreach (System.Data.DataRow row in table.Rows) + { + foreach (System.Data.DataColumn col in table.Columns) + { + Console.WriteLine("{0} = {1}", col.ColumnName, row[col]); + } + Console.WriteLine("============================"); + } + } + } + + + + Enumerating Instances of SQL Server + + - Gets an instance of the , which can be used to retrieve information about available SQL Server instances. - An instance of the used to retrieve information about available SQL Server instances. - - class does not provide a constructor. Use the property to retrieve an instance of the class instead. - -[!code-csharp[SqlDataSourceEnumeratorExample#1](~/../sqlclient/doc/samples/SqlDataSourceEnumeratorExample.cs#1)] - -## Examples -The following console application displays a list of all the available SQL Server 2005 instances within the local network. This code uses the method to filter the rows in the table returned by the method. - [!code-csharp[SqlDataSourceEnumeratorVersionExample#1](~/../sqlclient/doc/samples/SqlDataSourceEnumeratorVersionExample.cs#1)] - - ]]> - - Enumerating Instances of SQL Server - + + Gets an instance of the , which can be used to retrieve information about available SQL Server instances. + + + An instance of the used to retrieve information about available SQL Server instances. + + + + The class does not provide a constructor. Use the property to retrieve an instance of the class instead. + + + + using System; + using Microsoft.Data.Sql; + + class Program + { + static void Main() + { + // Retrieve the enumerator instance and then the data. + SqlDataSourceEnumerator instance = + SqlDataSourceEnumerator.Instance; + System.Data.DataTable table = instance.GetDataSources(); + + // Display the contents of the table. + DisplayData(table); + + Console.WriteLine("Press any key to continue."); + Console.ReadKey(); + } + + private static void DisplayData(System.Data.DataTable table) + { + foreach (System.Data.DataRow row in table.Rows) + { + foreach (System.Data.DataColumn col in table.Columns) + { + Console.WriteLine("{0} = {1}", col.ColumnName, row[col]); + } + Console.WriteLine("============================"); + } + } + } + + + + + The following console application displays a list of all the available SQL Server 2005 instances within the local network. This code uses the method to filter the rows in the table returned by the method. + + + + using System; + using Microsoft.Data.Sql; + + class Program + { + static void Main() + { + // Retrieve the enumerator instance, and + // then retrieve the data sources. + SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance; + System.Data.DataTable table = instance.GetDataSources(); + + // Filter the sources to just show SQL Server 2012 instances. + System.Data.DataRow[] rows = table.Select("Version LIKE '11%'"); + foreach (System.Data.DataRow row in rows) + { + Console.WriteLine(row["ServerName"]); + } + + Console.WriteLine("Press any key to continue."); + Console.ReadKey(); + } + } + + + + Enumerating Instances of SQL Server + -
+
diff --git a/doc/snippets/Microsoft.Data.Sql/SqlNotificationRequest.xml b/doc/snippets/Microsoft.Data.Sql/SqlNotificationRequest.xml index 8a60e5c16c..84c1a02c13 100644 --- a/doc/snippets/Microsoft.Data.Sql/SqlNotificationRequest.xml +++ b/doc/snippets/Microsoft.Data.Sql/SqlNotificationRequest.xml @@ -1,98 +1,120 @@ - - - - - Represents a request for notification for a given command. - - class provides a simpler way of using query notifications. However, if you need fine control over when notifications occur, or you need to customize the message data returned as part of a notification, the class is the one to use. - -]]> - - Using Query Notifications - - - Creates a new instance of the class with default values. - - object, that instance must have its and properties initialized before assigning the object to a object's property. The default values used by the constructor are NULL (`Nothing` in Visual Basic) for the , an empty string for the , and zero for the . - -]]> - - Using Query Notifications - - - A string that contains an application-specific identifier for this notification. It is not used by the notifications infrastructure, but it allows you to associate notifications with the application state. The value indicated in this parameter is included in the Service Broker queue message. - A string that contains the Service Broker service name where notification messages are posted, and it must include a database name or a Service Broker instance GUID that restricts the scope of the service name lookup to a particular database. For more information about the format of the parameter, see . - The time, in seconds, to wait for a notification message. - Creates a new instance of the class with a user-defined string that identifies a particular notification request, the name of a predefined SQL Server 2005 Service Broker service name, and the time-out period, measured in seconds. - - instance, providing your own identifier, the SQL Server 2005 Service Broker service name, and a time-out value. - -]]> - - The value of the parameter is NULL. - The or parameter is longer than or the value in the parameter is less than zero. - Using Query Notifications - - - Gets or sets the SQL Server Service Broker service name where notification messages are posted. - - that contains the SQL Server 2005 Service Broker service name where notification messages are posted and the database or service broker instance GUID to scope the server name lookup. - - property has the following format: - -`service={;(local database=|broker instance=)}` - -For example, if you use the service "myservice" in the database "AdventureWorks" the format is: - -`service=myservice;local database=AdventureWorks` - -The SQL Server Service Broker service must be previously configured on the server. In addition, a Service Broker service and queue must be defined and security access granted as needed. See the SQL Server 2005 documentation for more information. - -]]> - - The value is NULL. - The value is longer than . - Using Query Notifications - - - Gets or sets a value that specifies how long SQL Server waits for a change to occur before the operation times out. - A signed integer value that specifies, in seconds, how long SQL Server waits for a change to occur before the operation times out. - - property defaults to the value set on the server. - -]]> - - The value is less than zero. - Using Query Notifications - - - Gets or sets an application-specific identifier for this notification. - A value of the application-specific identifier for this notification. - - property is included in the SQL Server 2005 queue message. - -]]> - - The value is longer than . - Using Query Notifications - - + + + + + Represents a request for notification for a given command. + + + This class provides low-level access to the query notification services exposed by SQL Server 2005. For most applications the class provides a simpler way of using query notifications. However, if you need fine control over when notifications occur, or you need to customize the message data returned as part of a notification, the class is the one to use. + + + Using Query Notifications + + + + + Creates a new instance of the class with default values. + + + If the parameterless constructor is used to create a object, that instance must have its and properties initialized before assigning the object to a object's property. The default values used by the constructor are (Nothing in Visual Basic) for the , an empty string for the , and zero for the . + + + Using Query Notifications + + + + + A string that contains an application-specific identifier for this notification. It is not used by the notifications infrastructure, but it allows you to associate notifications with the application state. The value indicated in this parameter is included in the Service Broker queue message. + + + A string that contains the Service Broker service name where notification messages are posted, and it must include a database name or a Service Broker instance GUID that restricts the scope of the service name lookup to a particular database. For more information about the format of the parameter, see . + + + The time, in seconds, to wait for a notification message. + + + Creates a new instance of the class with a user-defined string that identifies a particular notification request, the name of a predefined SQL Server 2005 Service Broker service name, and the time-out period, measured in seconds. + + + This constructor allows you to initialize a new instance, providing your own identifier, the SQL Server 2005 Service Broker service name, and a time-out value. + + + The value of the parameter is . + + + The or parameter is longer than or the value in the parameter is less than zero. + + + Using Query Notifications + + + + + Gets or sets the SQL Server Service Broker service name where notification messages are posted. + + + that contains the SQL Server 2005 Service Broker service name where notification messages are posted and the database or service broker instance GUID to scope the server name lookup. + + + + The value of the property has the following format: + + + service=<service-name>{;(local database=<database>|broker instance=<broker instance>)} + + + For example, if you use the service "myservice" in the database "AdventureWorks" the format is: + + + service=myservice;local database=AdventureWorks + + + The SQL Server Service Broker service must be previously configured on the server. In addition, a Service Broker service and queue must be defined and security access granted as needed. See the SQL Server 2005 documentation for more information. + + + + The value is . + + + The value is longer than . + + + Using Query Notifications + + + + + Gets or sets a value that specifies how long SQL Server waits for a change to occur before the operation times out. + + + A signed integer value that specifies, in seconds, how long SQL Server waits for a change to occur before the operation times out. + + + After the time-out period expires, the notification is sent even if no change takes place. The property defaults to the value set on the server. + + + The value is less than zero. + + + Using Query Notifications + + + + + Gets or sets an application-specific identifier for this notification. + + + A value of the application-specific identifier for this notification. + + + This value is not used by the notifications infrastructure. Instead, it is a mechanism that allows an application to associate notifications with application state. The value specified in the property is included in the SQL Server 2005 queue message. + + + The value is longer than . + + + Using Query Notifications + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/ColumnSensitivity.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/ColumnSensitivity.xml index 2c43af620c..bdafe9e84b 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/ColumnSensitivity.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/ColumnSensitivity.xml @@ -1,16 +1,25 @@ - - - - - Represents the Data Classification Sensitivity Information for columns as configured in Database. - - - Initializes a new instance of the class. - List of sensitivity properties. - - - Returns the list of sensitivity properties as received from Server for this 'ColumnSensitivity' information - List of sensitivity properties. - - + + + + + Represents the Data Classification Sensitivity Information for columns as configured in Database. + + + + + Initializes a new instance of the class. + + + List of sensitivity properties. + + + + + Returns the list of sensitivity properties as received from Server for this information. + + + List of sensitivity properties. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/InformationType.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/InformationType.xml index ff2dca0c3c..64e6d14011 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/InformationType.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/InformationType.xml @@ -1,21 +1,36 @@ - - - - - Represents the Data Classification Information Types as received from SQL Server for the active 'SqlDataReader' - - - Initializes a new instance of the class. - Name of Information Type. - ID of Information Type. - - - Gets the ID for this 'InformationType' object - ID of Information Type. - - - Gets the name for this 'InformationType' object - Name of Information Type. - - + + + + + Represents the Data Classification Information Types as received from SQL Server for the active + + + + + Initializes a new instance of the class. + + + Name of Information Type. + + + ID of Information Type. + + + + + Gets the ID for this object + + + ID of Information Type. + + + + + Gets the name for this object + + + Name of Information Type. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/Label.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/Label.xml index 7d75923abe..01e90c02a2 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/Label.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/Label.xml @@ -1,21 +1,36 @@ - - - - - - Initializes a new instance of the class. - Name of label. - ID of label. - - - Gets the ID for this 'Label' object - ID of label. - - - Gets the name for this 'Label' object - Name of label. - - + + + + + + Initializes a new instance of the class. + + + Name of label. + + + ID of label. + + + + + Gets the ID for this object + + + ID of label. + + + + + Gets the name for this object + + + Name of label. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityClassification.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityClassification.xml index 83707533b1..5dd462add6 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityClassification.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityClassification.xml @@ -1,49 +1,93 @@ - - - - - Provides the functionlity to retrieve Sensitivity Classification data as received from SQL Server for the active 'SqlDataReader' - - - Returns the column sensitivity for this 'SensitivityClassification' Object - List of column sensitivities. - - - Returns the information types collection for this 'SensitivityClassification' Object - List of information types. - - - Returns the labels collection for this 'SensitivityClassification' Object - List of labels. - - - Returns the relative sensitivity rank for the query associated with the active 'SqlDataReader'. - Relative sensitivity ranking for this query. - - - - - - - - Initializes a new instance of the class. - List of labels. - List of information types. - List of column sensitivities. - Relative sensitivity rank for the query associated with the active 'SqlDataReader'. - - + + + + + Provides the functionality to retrieve Sensitivity Classification data as received from SQL Server for the active . + + + + + Returns the column sensitivity for this Object + + + List of column sensitivities. + + + + + Returns the information types collection for this Object + + + List of information types. + + + + + Returns the labels collection for this Object + + + List of labels. + + + + + Returns the relative sensitivity rank for the query associated with the active . + + + Relative sensitivity ranking for this query. + + + + A relative sensitivity ranking of the query. Available values are as below: + + + + Sensitivity Rank + Description + + + -1 + Not Defined (default) + + + 0 + None + + + 10 + Low + + + 20 + Medium + + + 30 + High + + + 40 + Critical + + + + + + + Initializes a new instance of the class. + + + List of labels. + + + List of information types. + + + List of column sensitivities. + + + Relative sensitivity rank for the query associated with the active . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityProperty.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityProperty.xml index 5fb61f161c..caf12116a8 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityProperty.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityProperty.xml @@ -1,44 +1,82 @@ - - - - - Represents the Data Classification Sensitivity Information for columns as configured in Database. - - - Initializes a new instance of the class. - Label for this SensitivityProperty. - Information type for this SensitivityProperty. - Sensitivity rank for this SensitivityProperty. - - - Returns the information type for this 'SensitivityProperty' Object - Information type for this SensitivityProperty. - - - - Returns the sensitivity rank for this 'SensitivityProperty' Object - Sensitivity rank for this SensitivityProperty. - - - - - - - + + + + + Represents the Data Classification Sensitivity Information for columns as configured in Database. + + + + + Initializes a new instance of the class. + + + Label for this . + + + Information type for this . + + + Sensitivity rank for this . + + + + + Returns the information type for this Object + + + Information type for this . + + + + + + Returns the sensitivity rank for this Object + + + Sensitivity rank for this . + + + + A relative sensitivity ranking of a column that is part of per column data. Available values are as below: + + + + Sensitivity Rank + Description + + + -1 + Not Defined (default) + + + 0 + None + + + 10 + Low + + + 20 + Medium + + + 30 + High + + + 40 + Critical + + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityRank.xml b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityRank.xml index 41e215e29e..77098fe7a8 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityRank.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.DataClassification/SensitivityRank.xml @@ -1,17 +1,32 @@ - - + - A relative ranking of the sensitivity of a query or of a column that is part of percolumn data. - It is an identifier based on a predefined set of values which define sensitivity rank. Used by other services like Advanced Threat Protection to detect anomalies based on their rank. + + A relative ranking of the sensitivity of a query or of a column that is part of per column data. + + + It is an identifier based on a predefined set of values which define sensitivity rank. Used by other services like Advanced Threat Protection to detect anomalies based on their rank. + - No sensitivity rank defined. - Corresponds to rank value of 0. - Corresponds to rank value of 10. - Corresponds to rank value 20. - Corresponds to rank value 30. - Corresponds to rank value 40. + + No sensitivity rank defined. + + + Corresponds to rank value of 0. + + + Corresponds to rank value of 10. + + + Corresponds to rank value 20. + + + Corresponds to rank value 30. + + + Corresponds to rank value 40. + diff --git a/doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml b/doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml index a2481e9363..7b0af6f6c9 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml @@ -1,789 +1,1508 @@ - - - - - Represents a single row of data and its metadata. - - to send result sets to the client from managed code stored-procedures. - - When writing common language runtime (CLR) applications, you should re-use existing `SqlDataRecord` objects instead of creating new ones every time. Creating many new `SqlDataRecord` objects could severely deplete memory and adversely affect performance. - - - -## Examples - The following example shows how to create several objects, which describe the column metadata of a record, and creating a . The column values of the are set and the is sent to the calling program by using the class. - - [!code-csharp[SqlDataRecord Samples#1](~/../sqlclient/doc/samples/SqlDataRecord.cs#1)] - - ]]> - - - - An array of objects that describe each column in the . - Inititializes a new instance with the schema based on the array of objects passed as an argument. - - object from two objects, which indicate the column name and data type. - - [!code-csharp[SqlDataRecord Samples#2](~/../sqlclient/doc/samples/SqlDataRecord.cs#2)] - - ]]> - - The is . - - - Gets the number of columns in the data row. This property is read-only. - The number of columns in the data row as an integer. - To be added. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - The offset into the field value to start retrieving bytes. - The target buffer to which to copy bytes. - The offset into the buffer to which to start copying bytes. - The number of bytes to copy to the buffer. - Gets the value for the column specified by the ordinal as an array of objects. - The number of bytes copied. - - repeatedly, adjusting the `fieldOffset` parameter accordingly in each call. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - The offset into the field value to start retrieving characters. - The target buffer to copy chars to. - The offset into the buffer to start copying chars to. - The number of chars to copy to the buffer. - Gets the value for the column specified by the ordinal as an array of objects. - The number of characters copied. - - repeatedly adjusting the `fieldOffset` parameter accordingly in each call. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - To be added. - To be added. - To be added. - To be added. - - - The zero-based ordinal of the column. - Returns the name of the data type for the column specified by the ordinal argument. - A that contains the data type of the column. - - - - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based column ordinal. - Returns the specified column's data as a . - The value of the specified column as a . - To be added. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns a object representing the common language runtime (CLR) type that maps to the SQL Server type of the column specified by the argument. - The column type as a object. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column is of a user-defined type that is not available to the calling application domain. - The column is of a user-defined type that is not available to the calling application domain. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column specified by is null. - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns the name of the column specified by the ordinal argument. - A containing the column name. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The name of the column to look up. - Returns the column ordinal specified by the column name. - The zero-based ordinal of the column as an integer. - To be added. - - is . - The column name could not be found. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns a object that represents the type (as a SQL Server type, defined in ) that maps to the SQL Server type of the column. - The column type as a object. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - The column is of a user-defined type that is not available to the calling application domain. - The column is of a user-defined type that is not available to the calling application domain. - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns a object, describing the metadata of the column specified by the column ordinal. - The column metadata as a object. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns the data value stored in the column, expressed as a SQL Server type, specified by the column ordinal. - The value of the column, expressed as a SQL Server type, as a . - - property is true. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - - The array into which to copy the values column values. - Returns the values for all the columns in the record, expressed as SQL Server types, in an array. - An that indicates the number of columns copied. - - property is true. - - The length of the `values` array does not need to match the number of columns in the record. If the array length is greater than the number of columns, all of the column values are copied into the array; if it is less, only the array length number of column values are copied into the array, starting at the column value with ordinal 0. - - ]]> - - - is . - There is a type mismatch. - - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based ordinal of the column. - Gets the value for the column specified by the ordinal as a . - The column value as a . - To be added. - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The zero-based column ordinal. - Returns the specified column's data as a . - The value of the specified column as a . - To be added. - - - The zero-based ordinal of the column. - Returns the common language runtime (CLR) type value for the column specified by the ordinal argument. - The CLR type value of the column specified by the ordinal. - - is returned. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - There is a type mismatch. - - - The array into which to copy the values column values. - Returns the values for all the columns in the record, expressed as common language runtime (CLR) types, in an array. - An that indicates the number of columns copied. - - is returned. - - The length of the `values` array does not need to match the number of columns in the record. If the array length is greater than the number of columns, all of the column values are copied into the array; if it is less, only the array length number of column values is copied into the array, starting at the column value with ordinal 0. - - ]]> - - - is . - There is a type mismatch. - - - The zero-based ordinal of the column. - Returns true if the column specified by the column ordinal parameter is null. - - if the column is null; otherwise. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - Gets the common language runtime (CLR) type value for the column. - - - The zero-based ordinal of the column. - Gets the common language runtime (CLR) type value for the column specified by the column argument. - The CLR type value of the column specified by the . - - is returned. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - - - The name of the column. - Gets the common language runtime (CLR) type value for the column specified by the column argument. - The CLR type value of the column specified by the . - - is returned. - - ]]> - - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The offset into the field value to start copying bytes. - The target buffer from which to copy bytes. - The offset into the buffer from which to start copying bytes. - The number of bytes to copy from the buffer. - Sets the data stored in the column to the specified array of values. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The offset into the field value to start copying characters. - The target buffer from which to copy chars. - The offset into the buffer from which to start copying chars. - The number of chars to copy from the buffer. - Sets the data stored in the column to the specified array of values. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the value of the column specified to the value. - To be added. - - - The zero-based ordinal of the column. - Sets the value in the specified column to . - To be added. - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the data stored in the column to the specified value. - To be added. - The is less than 0 or greater than the number of columns (that is, ). - - - The zero-based ordinal of the column. - The new value of the column. - Sets the value of the column specified to the . - To be added. - The passed in is a negative number. - The value passed in is greater than 24 hours in length. - - - The zero-based ordinal of the column. - The new value for the specified column. - Sets a new value, expressed as a common language runtime (CLR) type, for the column specified by the column ordinal. - - instance. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - - - The array of new values, expressed as CLR types boxed as references, for the instance. - Sets new values for all of the columns in the . These values are expressed as common language runtime (CLR) types. - The number of column values set as an integer. - - instance. - - ]]> - - - is . - The size of values does not match the number of columns in the instance. - - - The zero-based ordinal of the column. - Not supported in this release. - - - - Always throws an exception. - - if called. - - ]]> - - The is less than 0 or greater than the number of columns (that is, ). - - + + + + + Represents a single row of data and its metadata. + + + + This class is used together with to send result sets to the client from managed code stored-procedures. + + + When writing common language runtime (CLR) applications, you should re-use existing SqlDataRecord objects instead of creating new ones every time. Creating many new SqlDataRecord objects could severely deplete memory and adversely affect performance. + + + + + The following example shows how to create several objects, which describe the column metadata of a record, and creating a . The column values of the are set and the is sent to the calling program by using the class. + + + + using Microsoft.Data.SqlClient.Server; + + [Microsoft.Data.SqlClient.Server.SqlProcedure] + public static void CreateNewRecord() + { + + // Variables. + SqlDataRecord record; + + // Create a new record with the column metadata. The constructor is + // able to accept a variable number of parameters. + record = new SqlDataRecord(new SqlMetaData[] { new SqlMetaData("Column1", SqlDbType.NVarChar, 12), + new SqlMetaData("Column2", SqlDbType.Int), + new SqlMetaData("Column3", SqlDbType.DateTime) }); + + // Set the record fields. + record.SetString(0, "Hello World!"); + record.SetInt32(1, 42); + record.SetDateTime(2, DateTime.Now); + + // Send the record to the calling program. + SqlContext.Pipe.Send(record); + } + + + + + + An array of objects that describe each column in the . + + + Initializes a new instance with the schema based on the array of objects passed as an argument. + + + + The following example shows how to create a new object from two objects, which indicate the column name and data type. + + + + using Microsoft.Data.SqlClient.Server; + + // Variables. + SqlMetaData column1Info; + SqlMetaData column2Info; + SqlDataRecord record; + + // Create the column metadata. + column1Info = new SqlMetaData("Column1", SqlDbType.NVarChar, 12); + column2Info = new SqlMetaData("Column2", SqlDbType.Int); + + // Create a new record with the column metadata. + record = new SqlDataRecord(new SqlMetaData[] { column1Info, column2Info }); + + + // Set the record fields. + record.SetString(0, "Hello World!"); + record.SetInt32(1, 42); + + // Send the record to the calling program. + SqlContext.Pipe.Send(record); + + + + The is . + + + + + Gets the number of columns in the data row. This property is read-only. + + + The number of columns in the data row as an integer. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is null. + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is null. + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + The offset into the field value to start retrieving bytes. + + + The target buffer to which to copy bytes. + + + The offset into the buffer to which to start copying bytes. + + + The number of bytes to copy to the buffer. + + + Gets the value for the column specified by the ordinal as an array of objects. + + + The number of bytes copied. + + + + This method enables you to obtain a binary value either in a single call or in chunks. Getting the value in chunks is useful for large values or values of unknown size. + + + To obtain the value in several chunks, allocate a byte array of the chunk-size and call GetBytes repeatedly, adjusting the parameter accordingly in each call. + + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + The offset into the field value to start retrieving characters. + + + The target buffer to copy chars to. + + + The offset into the buffer to start copying chars to. + + + The number of chars to copy to the buffer. + + + Gets the value for the column specified by the ordinal as an array of objects. + + + The number of characters copied. + + + + This method enables you to obtain a character value either in a single call or in chunks. Getting the value in chunks is useful for large values or values of unknown size. + + + To obtain the value in several chunks, allocate a char array of the chunk-size and call GetChars repeatedly adjusting the parameter accordingly in each call. + + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is null. + + + There is a type mismatch. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + The zero-based ordinal of the column. + + + Returns the name of the data type for the column specified by the ordinal argument. + + + A that contains the data type of the column. + + + This method returns the type name as known in the SQL Server type-system. For user-defined types (UDTs), it returns the three-part name that was used to register the type with SQL Server. + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based column ordinal. + + + Returns the specified column's data as a . + + + The value of the specified column as a . + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns a object representing the common language runtime (CLR) type that maps to the SQL Server type of the column specified by the argument. + + + The column type as a object. + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column is of a user-defined type that is not available to the calling application domain. + + + The column is of a user-defined type that is not available to the calling application domain. + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column specified by is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns the name of the column specified by the ordinal argument. + + + A containing the column name. + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The name of the column to look up. + + + Returns the column ordinal specified by the column name. + + + The zero-based ordinal of the column as an integer. + + + is . + + + The column name could not be found. + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns a object that represents the type (as a SQL Server type, defined in ) that maps to the SQL Server type of the column. + + + The column type as a object. + + + The is less than 0 or greater than the number of columns (that is, ). + + + The column is of a user-defined type that is not available to the calling application domain. + + + The column is of a user-defined type that is not available to the calling application domain. + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns a object, describing the metadata of the column specified by the column ordinal. + + + The column metadata as a object. + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns the data value stored in the column, expressed as a SQL Server type, specified by the column ordinal. + + + The value of the column, expressed as a SQL Server type, as a . + + + For null values, a SQL Server type instance is returned where the property is true. + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + + The array into which to copy the values column values. + + + Returns the values for all the columns in the record, expressed as SQL Server types, in an array. + + + An that indicates the number of columns copied. + + + + The SQL Server type values of the column are copied into the array that is passed as a parameter. For null values, a Sql type instance is returned where the property is true. + + + The length of the array does not need to match the number of columns in the record. If the array length is greater than the number of columns, all the column values are copied into the array; if it is less, only the array length number of column values are copied into the array, starting at the column value with ordinal 0. + + + + is . + + + There is a type mismatch. + + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Gets the value for the column specified by the ordinal as a . + + + The column value as a . + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The zero-based column ordinal. + + + Returns the specified column's data as a . + + + The value of the specified column as a . + + + + + The zero-based ordinal of the column. + + + Returns the common language runtime (CLR) type value for the column specified by the ordinal argument. + + + The CLR type value of the column specified by the ordinal. + + + For columns with null value, is returned. + + + The is less than 0 or greater than the number of columns (that is, ). + + + There is a type mismatch. + + + + + The array into which to copy the values column values. + + + Returns the values for all the columns in the record, expressed as common language runtime (CLR) types, in an array. + + + An that indicates the number of columns copied. + + + + The CLR type values of the column are copied into the array that is passed as a parameter. For columns with null value, is returned. + + + The length of the array does not need to match the number of columns in the record. If the array length is greater than the number of columns, all the column values are copied into the array; if it is less, only the array length number of column values is copied into the array, starting at the column value with ordinal 0. + + + + is . + + + There is a type mismatch. + + + + + The zero-based ordinal of the column. + + + Returns if the column specified by the column ordinal parameter is null. + + + if the column is null; otherwise. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + Gets the common language runtime (CLR) type value for the column. + + + + + The zero-based ordinal of the column. + + + Gets the common language runtime (CLR) type value for the column specified by the column argument. + + + The CLR type value of the column specified by the . + + + For columns with null value, is returned. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The name of the column. + + + Gets the common language runtime (CLR) type value for the column specified by the column argument. + + + The CLR type value of the column specified by the . + + + For columns with null value, is returned. + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The offset into the field value to start copying bytes. + + + The target buffer from which to copy bytes. + + + The offset into the buffer from which to start copying bytes. + + + The number of bytes to copy from the buffer. + + + Sets the data stored in the column to the specified array of values. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The offset into the field value to start copying characters. + + + The target buffer from which to copy chars. + + + The offset into the buffer from which to start copying chars. + + + The number of chars to copy from the buffer. + + + Sets the data stored in the column to the specified array of values. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the value of the column specified to the value. + + + + + The zero-based ordinal of the column. + + + Sets the value in the specified column to . + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the data stored in the column to the specified value. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The zero-based ordinal of the column. + + + The new value of the column. + + + Sets the value of the column specified to the . + + + The passed in is a negative number. + + + The value passed in is greater than 24 hours in length. + + + + + The zero-based ordinal of the column. + + + The new value for the specified column. + + + Sets a new value, expressed as a common language runtime (CLR) type, for the column specified by the column ordinal. + + + is a SQL type boxed as a instance. + + + The is less than 0 or greater than the number of columns (that is, ). + + + + + The array of new values, expressed as CLR types boxed as references, for the instance. + + + Sets new values for all the columns in the . These values are expressed as common language runtime (CLR) types. + + + The number of column values set as an integer. + + + The length of values must match the number of columns in the instance. + + + is . + + + The size of values does not match the number of columns in the instance. + + + + + The zero-based ordinal of the column. + + + Not supported in this release. + + + Always throws an exception. + + + This method is not supported in this release, and throws if called. + + + The is less than 0 or greater than the number of columns (that is, ). + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.Server/SqlMetaData.xml b/doc/snippets/Microsoft.Data.SqlClient.Server/SqlMetaData.xml index 016b6e6ee3..47b515b911 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.Server/SqlMetaData.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.Server/SqlMetaData.xml @@ -1,896 +1,1726 @@ - - - - - Specifies and retrieves metadata information from parameters and columns of objects. This class cannot be inherited. - - objects, which describe the column metadata of a record, and the creation of a . The column values of the are set and the is sent to the calling program using the class. - -[!code-csharp[SqlMetaData Samples#1](~/../sqlclient/doc/samples/SqlMetaData.cs#1)] - -]]> - - - - Initializes a new instance of the class. - - - The name of the column. - The SQL Server type of the parameter or column. - Initializes a new instance of the class with the specified column name and type. - - , , , and properties are set to `null`): - -|SqlDbType|Maximum length|Precision|Scale|Locale|Compare options| -|---------------|--------------------|---------------|-----------|------------|---------------------| -|`Bit`|1|1|0|0|None| -|`BigInt`|8|19|0|0|None| -|`DateTime`|8|23|3|0|None| -|`Decimal`|9|18|0|0|None| -|`Float`|8|53|0|0|None| -|`Int`|4|10|0|0|None| -|`Money`|8|19|4|0|None| -|`Numeric`|9|18|0|0|None| -|`SmallDateTime`|4|16|0|0|None| -|`SmallInt`|2|5|0|0|None| -|`SmallMoney`|4|10|4|0|None| -|`TimeStamp`|8|0|0|0|None| -|`TinyInt`|1|3|0|0|None| -|`UniqueIdentifier`|16|0|0|0|None| -|`Xml`|Max (-1)|0|0|0|IgnoreCase, IgnoreKanaType, IgnoreWidth| - -## Examples -The following example creates a new object by specifying the column name and a column data type of .`Int`. - -[!code-csharp[SqlMetaData Samples#3](~/../sqlclient/doc/samples/SqlMetaData.cs#3)] - -]]> - - The is . - A that is not allowed was passed to the constructor as . - - - The name of the column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - Initializes a new instance of the class with the specified column name, type, and maximum length. - - , or -1 is allowed for a `dbType` of `Text`, `NText`, or `Image`. - -For a `dbType` of `Varchar`, `Nvarchar`, or `VarBinary`, a length specification of , or -1, declares the metadata as varchar(max), nvarchar(max), or nvarbinary(max), respectively. - -The following are the default values assigned to `dbType`, depending on the `SqlDbType` (the , , , and properties are set to `null`): - -|SqlDbType|Precision|Scale|Locale|Compare options| -|---------------|---------------|-----------|------------|---------------------| -|Binary|0|0|0|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|Char|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|Image|0|0|0|None| -|NChar|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|NText|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|NVarChar|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|Text|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|VarBinary|0|0||IgnoreCase, IgnoreKanaType, IgnoreWidth| -|VarChar|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| - - -## Examples -The following example creates a new object by specifying the column name, a column data type of `.NVarChar`, and a maximum length of 12 characters. - -[!code-csharp[SqlMetaData Samples#2](~/../sqlclient/doc/samples/SqlMetaData.cs#2)] - -]]> - - The is . - A SqlDbType that is not allowed was passed to the constructor as . - - - The name of the column. - The SQL Server type of the parameter or column. - A instance that points to the UDT. - Initializes a new instance of the class with the specified column name, type, and user-defined type (UDT). - - , , , and properties are set to `null`): - -|SqlDbType|Maximum length|Precision|Scale|Locale|Compare options| -|---------------|--------------------|---------------|-----------|------------|---------------------| -|UDT|\ or -1|0|0|0|None| - -]]> - - The is . - A SqlDbType that is not allowed was passed to the constructor as , or points to a type that does not have declared. - - - The name of the parameter or column. - The SQL Server type of the parameter or column. - The precision of the parameter or column. - The scale of the parameter or column. - Initializes a new instance of the class with the specified column name, type, precision, and scale. - - , , , and properties are set to `null`): - -|SqlDbType|Maximum length|Precision|Scale|Locale|Compare options| -|---------------|--------------------|---------------|-----------|------------|---------------------| -|Decimal|9|18|0|0|None| - -]]> - - The is . - A that is not allowed was passed to the constructor as , or was greater than . - - - The name of the column. - The SQL Server type of the parameter or column. - A instance that points to the UDT. - The SQL Server type name for . - Initializes a new instance of the class with the specified column name, user-defined type (UDT), and SQLServer type. - - - The name of the parameter or column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - The locale ID of the parameter or column. - The comparison rules of the parameter or column. - Initializes a new instance of the class with the specified column name, type, maximum length, locale, and compare options. - - , or -1, is allowed for a `dbType` of `Text` or `NText`. - -For a `dbType` of `Varchar` or `Nvarchar`, a length specification of , or -1, declares the metadata as varchar(max) and nvarchar(max), respectively. - -The following are the default values assigned to `dbType`, depending on the `SqlDbType` (the , , , and properties are set to `null`): - -|SqlDbType|Precision|Scale| -|---------------|---------------|-----------| -|`Char`|0|0| -|`NChar`|0|0| -|`NText`|0|0| -|`NVarChar`|0|0| -|`Text`|0|0| -|`VarChar`|0|0| - -]]> - - The is . - A SqlDbType that is not allowed was passed to the constructor as . - - - The name of the column. - The SQL Server type of the parameter or column. - The database name of the XML schema collection of a typed XML instance. - The relational schema name of the XML schema collection of a typed XML instance. - The name of the XML schema collection of a typed XML instance. - Initializes a new instance of the class with the specified column name, type, database name, owning schema, and object name. - - - - The is , or is when and are non-. - A SqlDbType that is not allowed was passed to the constructor as . - - - The name of the column. - The SQL Server type of the parameter or column. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, and default server. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, type, maximum length, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The precision of the parameter or column. - The scale of the parameter or column. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, type, precision, scale, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - The precision of the parameter or column. - The scale of the parameter or column. - The locale ID of the parameter or column. - The comparison rules of the parameter or column. - A instance that points to the UDT. - Initializes a new instance of the class with the specified column name, type, maximum length, precision, scale, locale ID, compare options, and user-defined type (UDT). - - , , , and properties are set to `null`): - -|SqlDbType|Maximum length|Precision|Scale|Locale|Compare options| -|---------------|--------------------|---------------|-----------|------------|---------------------| -|`BigInt`|8|19|0|0|None| -|`Bit`|1|1|0|0|None| -|`DateTime`|8|23|3|0|None| -|`Decimal`|9|18|0|0|None| -|`Float`|8|53|0|0|None| -|`Image`|Max (-1)|0|0|0|None| -|`Int`|4|10|0|0|None| -|`Money`|8|19|4|0|None| -|`Ntext`|Max (-1)|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|`Real`|4|24|0|0|None| -|`Row`|\|0|0|0|None| -|`SmallDateTime`|4|16|0|0|None| -|`SmallInt`|2|5|0|0|None| -|`SmallMoney`|4|10|4|0|None| -|`Text`|Max (-1)|0|0|\|IgnoreCase, IgnoreKanaType, IgnoreWidth| -|`TimeStamp`|8|0|0|0|None| -|`TinyInt`|1|3|0|0|None| -|`UniqueIdentifier`|16|0|0|0|None| -|`UDT`|\ or -1|0|0|0|None| -|`Variant`|8016|0|0|0|None| -|`Xml`|Max (-1)|0|0|0|IgnoreCase, IgnoreKanaType, IgnoreWidth| - -]]> - - The is . - A that is not allowed was passed to the constructor as , or points to a type that does not have declared. - - - The name of the column. - The SQL Server type of the parameter or column. - A instance that points to the UDT. - The SQL Server type name for . - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, type, user-defined type, SQL Server type, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - The locale ID of the parameter or column. - The comparison rules of the parameter or column. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, type, maximum length, locale, compare options, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The database name of the XML schema collection of a typed XML instance. - The relational schema name of the XML schema collection of a typed XML instance. - The name of the XML schema collection of a typed XML instance. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, database name, owning schema, object name, and default server. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - The name of the column. - The SQL Server type of the parameter or column. - The maximum length of the specified type. - The precision of the parameter or column. - The scale of the parameter or column. - The locale ID of the parameter or column. - The comparison rules of the parameter or column. - A instance that points to the UDT. - Specifies whether this column should use the default server value. - Specifies if the column in the table-valued parameter is unique. - Specifies the sort order for a column. - Specifies the ordinal of the sort column. - Initializes a new instance of the class with the specified column name, type, maximum length, precision, scale, locale ID, compare options, and user-defined type (UDT). This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. - - - - - - Validates the specified value against the metadata, and adjusts the value if necessary. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified array of values against the metadata, and adjusts the value if necessary. - The adjusted value as an array of values. - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified array of values against the metadata, and adjusts the value if necessary. - The adjusted value as an array values. - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as an array of values. - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as a . - To be added. - - does not match the type, or could not be adjusted. - - - The value to validate against the instance. - Validates the specified value against the metadata, and adjusts the value if necessary. - The adjusted value as an array of values. - To be added. - - does not match the type, or could not be adjusted. - - - Gets the comparison rules used for the column or parameter. - The comparison rules used for the column or parameter as a . - To be added. - - - Gets the data type of the column or parameter. - The data type of the column or parameter as a . - - .`String`. - -]]> - - - - The object used from which the metadata is inferred. - The name assigned to the returned instance. - Infers the metadata from the specified object and returns it as a instance. - The inferred metadata as a instance. - To be added. - The is . - - - Indicates if the column in the table-valued parameter is unique. - A value. - - constructors. - -For more information, see [Table-Valued Parameters](/sql/connect/ado-net/sql/table-valued-parameters). - -]]> - - - - Gets the locale ID of the column or parameter. - The locale ID of the column or parameter as a . - - - - - - Gets the length of , , and data types. - The length of , , and data types. - - - - - - Gets the maximum length of the column or parameter. - The maximum length of the column or parameter as a . - - .`Row` this returns the number of columns in the row metadata instance. - -The default value is 0. - -]]> - - - - Gets the name of the column or parameter. - The name of the column or parameter as a . - To be added. - - - Gets the precision of the column or parameter. - The precision of the column or parameter as a . - - - - - - Gets the scale of the column or parameter. - The scale of the column or parameter. - - - - - - Returns the sort order for a column. - A object. - - constructors. - -For more information, see [Table-Valued Parameters](/sql/connect/ado-net/sql/table-valued-parameters). - -]]> - - - - Returns the ordinal of the sort column. - The ordinal of the sort column. - - constructors. - -For more information, see [Table-Valued Parameters](/sql/connect/ado-net/sql/table-valued-parameters). - -]]> - - - - Gets the data type of the column or parameter. - The data type of the column or parameter as a . - - - - - - Gets the common language runtime (CLR) type of a user-defined type (UDT). - The CLR type name of a user-defined type as a . - - is not a UDT type. `Null` may also returned for valid UDT result sets where the assembly is not available to the application. - -]]> - - - - Gets the three-part name of the user-defined type (UDT) or the SQL Server type represented by the instance. - The name of the UDT or SQL Server type as a . - - - - - - Reports whether this column should use the default server value. - A value. - - constructors. - -]]> - - - - Gets the name of the database where the schema collection for this XML instance is located. - The name of the database where the schema collection for this XML instance is located as a . - - and are also null. - -]]> - - - - Gets the name of the schema collection for this XML instance. - The name of the schema collection for this XML instance as a . - - and are also `null`. - -]]> - - - - Gets the owning relational schema where the schema collection for this XML instance is located. - The owning relational schema where the schema collection for this XML instance is located as a . - - and are also `null`. - -]]> - - - + + + + + Specifies and retrieves metadata information from parameters and columns of objects. This class cannot be inherited. + + + + The following example shows the creation of several objects, which describe the column metadata of a record, and the creation of a . The column values of the are set and the is sent to the calling program using the class. + + + + using Microsoft.Data.SqlClient.Server; + + [Microsoft.Data.SqlClient.Server.SqlProcedure] + public static void CreateNewRecord() + { + // Variables. + SqlMetaData column1Info; + SqlMetaData column2Info; + SqlMetaData column3Info; + SqlDataRecord record; + + // Create the column metadata. + column1Info = new SqlMetaData("Column1", SqlDbType.NVarChar, 12); + column2Info = new SqlMetaData("Column2", SqlDbType.Int); + column3Info = new SqlMetaData("Column3", SqlDbType.DateTime); + + // Create a new record with the column metadata. + record = new SqlDataRecord(new SqlMetaData[] { + column1Info, + column2Info, + column3Info }); + + // Set the record fields. + record.SetString(0, "Hello World!"); + record.SetInt32(1, 42); + record.SetDateTime(2, DateTime.Now); + + // Send the record to the calling program. + SqlContext.Pipe.Send(record); + } + + + + + + Initializes a new instance of the class. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + Initializes a new instance of the class with the specified column name and type. + + + + Only the following are allowed to be passed to this constructor as : , , , , , , , Numeric, , , , , , , . + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Maximum length + Precision + Scale + Locale + Compare options + + + + 1 + 1 + 0 + 0 + None + + + + 8 + 19 + 0 + 0 + None + + + + 8 + 23 + 3 + 0 + None + + + + 9 + 18 + 0 + 0 + None + + + + 8 + 53 + 0 + 0 + None + + + + 4 + 10 + 0 + 0 + None + + + + 8 + 19 + 4 + 0 + None + + + Numeric + 9 + 18 + 0 + 0 + None + + + + 4 + 16 + 0 + 0 + None + + + + 2 + 5 + 0 + 0 + None + + + + 4 + 10 + 4 + 0 + None + + + + 8 + 0 + 0 + 0 + None + + + + 1 + 3 + 0 + 0 + None + + + + 16 + 0 + 0 + 0 + None + + + + Max (-1) + 0 + 0 + 0 + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + + + + The following example creates a new object by specifying the column name and a column data type of + + + + using Microsoft.Data.SqlClient.Server; + + public static void CreateSqlMetaData2() + { + SqlMetaData columnInfo; + columnInfo = new SqlMetaData("Column2", SqlDbType.Int); + } + + + + The is . + + + A that is not allowed was passed to the constructor as . + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + Initializes a new instance of the class with the specified column name, type, and maximum length. + + + + Only the following are allowed to be passed to the constructor as : , , , , , , , , . + + + Only a specification of , or -1 is allowed for a of , , or . + + + For a of , , or , a length specification of , or -1, declares the metadata as VARCHAR(MAX), NVARCHAR(MAX), or NVARBINARY(MAX), respectively. + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Precision + Scale + Locale + Compare options + + + + 0 + 0 + 0 + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + 0 + None + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + + + + The following example creates a new object by specifying the column name, a column data type of , and a maximum length of 12 characters. + + + + using Microsoft.Data.SqlClient.Server; + + public static void CreateSqlMetaData1() + { + SqlMetaData columnInfo; + columnInfo = new SqlMetaData("Column1", SqlDbType.NVarChar, 12); + } + + + + The is . + + + A SqlDbType that is not allowed was passed to the constructor as . + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + A instance that points to the UDT. + + + Initializes a new instance of the class with the specified column name, type, and user-defined type (UDT). + + + + Only the following is allowed to be passed to the constructor as : . + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Maximum length + Precision + Scale + Locale + Compare options + + + + <Max length of the type> or -1 + 0 + 0 + 0 + None + + + + + + The is . + + + A that is not allowed was passed to the constructor as , or points to a type that does not have declared. + + + + + The name of the parameter or column. + + + The SQL Server type of the parameter or column. + + + The precision of the parameter or column. + + + The scale of the parameter or column. + + + Initializes a new instance of the class with the specified column name, type, precision, and scale. + + + + Only the following is allowed to be passed to the constructor as : . + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Maximum length + Precision + Scale + Locale + Compare options + + + + 9 + 18 + 0 + 0 + None + + + + + + The is . + + + A that is not allowed was passed to the constructor as , or was greater than . + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + A instance that points to the UDT. + + + The SQL Server type name for . + + + Initializes a new instance of the class with the specified column name, user-defined type (UDT), and SQLServer type. + + + + + The name of the parameter or column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + The locale ID of the parameter or column. + + + The comparison rules of the parameter or column. + + + Initializes a new instance of the class with the specified column name, type, maximum length, locale, and compare options. + + + + Only the following are allowed to be passed to the constructor as : , , , , , . + + + Only a specification of , or -1, is allowed for a of or . + + + For a of or , a length specification of , or -1, declares the metadata as VARCHAR(MAX) and NVARCHAR(MAX), respectively. + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Precision + Scale + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + + + The is . + + + A that is not allowed was passed to the constructor as . + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The database name of the XML schema collection of a typed XML instance. + + + The relational schema name of the XML schema collection of a typed XML instance. + + + The name of the XML schema collection of a typed XML instance. + + + Initializes a new instance of the class with the specified column name, type, database name, owning schema, and object name. + + + + Only the following is allowed to be passed to the constructor as : . + + + The following are the default values assigned to , depending on the : + + + + + SqlDbType + Maximum length + Precision + Scale + Locale + Compare options + + + + Max (-1) + 0 + 0 + 0 + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + + + The is , or is when and are non- . + + + A SqlDbType that is not allowed was passed to the constructor as . + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, and default server. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, type, maximum length, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The precision of the parameter or column. + + + The scale of the parameter or column. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, type, precision, scale, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + The precision of the parameter or column. + + + The scale of the parameter or column. + + + The locale ID of the parameter or column. + + + The comparison rules of the parameter or column. + + + A instance that points to the UDT. + + + Initializes a new instance of the class with the specified column name, type, maximum length, precision, scale, locale ID, compare options, and user-defined type (UDT). + + + + Only the following are allowed to be passed to the constructor as : , , , , , , , , , Numeric, , , , , , , , , , , . + + + The following are the default values assigned to , depending on the (the , , , and properties are set to ): + + + + + SqlDbType + Maximum length + Precision + Scale + Locale + Compare options + + + + 8 + 19 + 0 + 0 + None + + + + 1 + 1 + 0 + 0 + None + + + + 8 + 23 + 3 + 0 + None + + + + 9 + 18 + 0 + 0 + None + + + + 8 + 53 + 0 + 0 + None + + + + Max (-1) + 0 + 0 + 0 + None + + + + 4 + 10 + 0 + 0 + None + + + + 8 + 19 + 4 + 0 + None + + + + Max (-1) + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 4 + 24 + 0 + 0 + None + + + Row + <number of columns> + 0 + 0 + 0 + None + + + + 4 + 16 + 0 + 0 + None + + + + 2 + 5 + 0 + 0 + None + + + + 4 + 10 + 4 + 0 + None + + + + Max (-1) + 0 + 0 + <thread> + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + 8 + 0 + 0 + 0 + None + + + + 1 + 3 + 0 + 0 + None + + + + 16 + 0 + 0 + 0 + None + + + + <Max length of the type> or -1 + 0 + 0 + 0 + None + + + + 8016 + 0 + 0 + 0 + None + + + + Max (-1) + 0 + 0 + 0 + IgnoreCase, IgnoreKanaType, IgnoreWidth + + + + + + The is . + + + A that is not allowed was passed to the constructor as , or points to a type that does not have declared. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + A instance that points to the UDT. + + + The SQL Server type name for . + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, type, user-defined type, SQL Server type, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + The locale ID of the parameter or column. + + + The comparison rules of the parameter or column. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, type, maximum length, locale, compare options, and server default. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The database name of the XML schema collection of a typed XML instance. + + + The relational schema name of the XML schema collection of a typed XML instance. + + + The name of the XML schema collection of a typed XML instance. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, database name, owning schema, object name, and default server. This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + The name of the column. + + + The SQL Server type of the parameter or column. + + + The maximum length of the specified type. + + + The precision of the parameter or column. + + + The scale of the parameter or column. + + + The locale ID of the parameter or column. + + + The comparison rules of the parameter or column. + + + A instance that points to the UDT. + + + Specifies whether this column should use the default server value. + + + Specifies if the column in the table-valued parameter is unique. + + + Specifies the sort order for a column. + + + Specifies the ordinal of the sort column. + + + Initializes a new instance of the class with the specified column name, type, maximum length, precision, scale, locale ID, compare options, and user-defined type (UDT). This form of the constructor supports table-valued parameters by allowing you to specify if the column is unique in the table-valued parameter, the sort order for the column, and the ordinal of the sort column. + + + For more information, see Table-Valued Parameters. + + + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + + does not match the type, or could not be adjusted. + + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified array of values against the metadata, and adjusts the value if necessary. + + + The adjusted value as an array of values. + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified array of values against the metadata, and adjusts the value if necessary. + + + The adjusted value as an array values. + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as an array of values. + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as a . + + does not match the type, or could not be adjusted. + + + + The value to validate against the instance. + + + Validates the specified value against the metadata, and adjusts the value if necessary. + + + The adjusted value as an array of values. + + does not match the type, or could not be adjusted. + + + + Gets the comparison rules used for the column or parameter. + + + The comparison rules used for the column or parameter as a . + + + To be added. + + + + + Gets the data type of the column or parameter. + + + The data type of the column or parameter as a . + + + The default type is . + + + + + The object used from which the metadata is inferred. + + + The name assigned to the returned instance. + + + Infers the metadata from the specified object and returns it as a instance. + + + The inferred metadata as a instance. + + + The is . + + + + + Indicates if the column in the table-valued parameter is unique. + + + A value. + + + + The default is . + + + This property can only be set in one of the constructors. + + + For more information, see Table-Valued Parameters. + + + + + + Gets the locale ID of the column or parameter. + + + The locale ID of the column or parameter as a . + + + + The default value is the current locale of the current thread for string-valued s, and 0 for s that do not support collation. + + + Returns 0 if the collation of the underlying column type is not defined. + + + + + + Gets the length of TEXT, NTEXT, and IMAGE data types. + + + The length of TEXT, NTEXT, and IMAGE data types. + + + The default value is -1. + + + + + Gets the maximum length of the column or parameter. + + + The maximum length of the column or parameter as a . + + + + The potential maximum length for values of the specified column. Returns 0 for types other than fixed and varying length character and binary types. For variable size columns or parameters declared with the Max constructor parameter, it returns -1. + + + For Row this returns the number of columns in the row metadata instance. + + + The default value is 0. + + + + + + Gets the name of the column or parameter. + + + The name of the column or parameter as a . + + + + + Gets the precision of the column or parameter. + + + The precision of the column or parameter as a . + + + Returns 0 if the precision of the underlying column type is not defined. + + + + + Gets the scale of the column or parameter. + + + The scale of the column or parameter. + + + Returns 0 if the scale of the underlying column type is not defined. + + + + + Returns the sort order for a column. + + + A object. + + + + This property can only be set in one of the constructors. + + + For more information, see Table-Valued Parameters. + + + + + + Returns the ordinal of the sort column. + + + The ordinal of the sort column. + + + + The default is 1. + + + This property can only be set in one of the constructors. + + + For more information, see Table-Valued Parameters. + + + + + + Gets the data type of the column or parameter. + + + The data type of the column or parameter as a . + + + The default value is . + + + + + Gets the common language runtime (CLR) type of user-defined type (UDT). + + + The CLR type name of a user-defined type as a . + + + + The default value is . + + + Returns if is not a UDT type. may also returned for valid UDT result sets where the assembly is not available to the application. + + + + + + Gets the three-part name of the user-defined type (UDT) or the SQL Server type represented by the instance. + + + The name of the UDT or SQL Server type as a . + + + The default value is . + + + + + Reports whether this column should use the default server value. + + + A value. + + + + The default is . + + + This property can only be set in one of the constructors. + + + + + + Gets the name of the database where the schema collection for this XML instance is located. + + + The name of the database where the schema collection for this XML instance is located as a . + + + + The default value is . + + + This property may be if the collection is defined within the current database. It is also if there is no schema collection, in which case and are also . + + + + + + Gets the name of the schema collection for this XML instance. + + + The name of the schema collection for this XML instance as a . + + + + The default value is . + + + This value is if there is no associated schema collection. If the value is , then and are also . + + + + + + Gets the owning relational schema where the schema collection for this XML instance is located. + + + The owning relational schema where the schema collection for this XML instance is located as a . + + + + The default value is . + + + This value may be if the collection is defined within the current database and default schema. It is also null if there is no schema collection, in which case and are also . + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient.Server/TriggerAction.xml b/doc/snippets/Microsoft.Data.SqlClient.Server/TriggerAction.xml index 1830794d18..5c715df261 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.Server/TriggerAction.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.Server/TriggerAction.xml @@ -1,244 +1,389 @@ - - - - - The enumeration is used by the class to indicate what action fired the trigger. - - enumeration is used by the class to indicate what action fired the trigger. - - ]]> - - - - An ALTER APPLICATION ROLE Transact-SQL statement was executed. - - - An ALTER ASSEMBLY Transact-SQL statement was executed. - - - An ALTER_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. - - - An ALTER FUNCTION Transact-SQL statement was executed. - - - An ALTER INDEX Transact-SQL statement was executed. - - - An ALTER LOGIN Transact-SQL statement was executed. - - - An ALTER PARTITION FUNCTION Transact-SQL statement was executed. - - - An ALTER PARTITION SCHEME Transact-SQL statement was executed. - - - An ALTER PROCEDURE Transact-SQL statement was executed. - - - An ALTER QUEUE Transact-SQL statement was executed. - - - An ALTER ROLE Transact-SQL statement was executed. - - - An ALTER ROUTE Transact-SQL statement was executed. - - - An ALTER SCHEMA Transact-SQL statement was executed. - - - An ALTER SERVICE Transact-SQL statement was executed. - - - An ALTER TABLE Transact-SQL statement was executed. - - - An ALTER TRIGGER Transact-SQL statement was executed. - - - An ALTER USER Transact-SQL statement was executed. - - - An ALTER VIEW Transact-SQL statement was executed. - - - A CREATE APPLICATION ROLE Transact-SQL statement was executed. - - - A CREATE ASSEMBLY Transact-SQL statement was executed. - - - A CREATE_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. - - - A CREATE CONTRACT Transact-SQL statement was executed. - - - A CREATE EVENT NOTIFICATION Transact-SQL statement was executed. - - - A CREATE FUNCTION Transact-SQL statement was executed. - - - A CREATE INDEX Transact-SQL statement was executed. - - - A CREATE LOGIN Transact-SQL statement was executed. - - - A CREATE MESSAGE TYPE Transact-SQL statement was executed. - - - A CREATE PARTITION FUNCTION Transact-SQL statement was executed. - - - A CREATE PARTITION SCHEME Transact-SQL statement was executed. - - - A CREATE PROCEDURE Transact-SQL statement was executed. - - - A CREATE QUEUE Transact-SQL statement was executed. - - - A CREATE ROLE Transact-SQL statement was executed. - - - A CREATE ROUTE Transact-SQL statement was executed. - - - A CREATE SCHEMA Transact-SQL statement was executed. - - - Not available. - - - A CREATE SERVICE Transact-SQL statement was executed. - - - A CREATE SYNONYM Transact-SQL statement was executed. - - - A CREATE TABLE Transact-SQL statement was executed. - - - A CREATE TRIGGER Transact-SQL statement was executed. - - - A CREATE TYPE Transact-SQL statement was executed. - - - A CREATE USER Transact-SQL statement was executed. - - - A CREATE VIEW Transact-SQL statement was executed. - - - A DELETE Transact-SQL statement was executed. - - - A DENY Object Permissions Transact-SQL statement was executed. - - - A DENY Transact-SQL statement was executed. - - - A DROP APPLICATION ROLE Transact-SQL statement was executed. - - - A DROP ASSEMBLY Transact-SQL statement was executed. - - - A DROP_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. - - - A DROP CONTRACT Transact-SQL statement was executed. - - - A DROP EVENT NOTIFICATION Transact-SQL statement was executed. - - - A DROP FUNCTION Transact-SQL statement was executed. - - - A DROP INDEX Transact-SQL statement was executed. - - - A DROP LOGIN Transact-SQL statement was executed. - - - A DROP MESSAGE TYPE Transact-SQL statement was executed. - - - A DROP PARTITION FUNCTION Transact-SQL statement was executed. - - - A DROP PARTITION SCHEME Transact-SQL statement was executed. - - - A DROP PROCEDURE Transact-SQL statement was executed. - - - A DROP QUEUE Transact-SQL statement was executed. - - - A DROP ROLE Transact-SQL statement was executed. - - - A DROP ROUTE Transact-SQL statement was executed. - - - A DROP SCHEMA Transact-SQL statement was executed. - - - Not available. - - - A DROP SERVICE Transact-SQL statement was executed. - - - A DROP SYNONYM Transact-SQL statement was executed. - - - A DROP TABLE Transact-SQL statement was executed. - - - A DROP TRIGGER Transact-SQL statement was executed. - - - A DROP TYPE Transact-SQL statement was executed. - - - A DROP USER Transact-SQL statement was executed. - - - A DROP VIEW Transact-SQL statement was executed. - - - A GRANT OBJECT Transact-SQL statement was executed. - - - A GRANT Transact-SQL statement was executed. - - - An INSERT Transact-SQL statement was executed. - - - An invalid trigger action, one that is not exposed to the user, occurred. - - - A REVOKE OBJECT Transact-SQL statement was executed. - - - A REVOKE Transact-SQL statement was executed. - - - An UPDATE Transact-SQL statement was executed. - - + + + + + The enumeration is used by the class to indicate what action fired the trigger. + + + + + An ALTER APPLICATION ROLE Transact-SQL statement was executed. + + + + + An ALTER ASSEMBLY Transact-SQL statement was executed. + + + + + An ALTER_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. + + + + + An ALTER FUNCTION Transact-SQL statement was executed. + + + + + An ALTER INDEX Transact-SQL statement was executed. + + + + + An ALTER LOGIN Transact-SQL statement was executed. + + + + + An ALTER PARTITION FUNCTION Transact-SQL statement was executed. + + + + + An ALTER PARTITION SCHEME Transact-SQL statement was executed. + + + + + An ALTER PROCEDURE Transact-SQL statement was executed. + + + + + An ALTER QUEUE Transact-SQL statement was executed. + + + + + An ALTER ROLE Transact-SQL statement was executed. + + + + + An ALTER ROUTE Transact-SQL statement was executed. + + + + + An ALTER SCHEMA Transact-SQL statement was executed. + + + + + An ALTER SERVICE Transact-SQL statement was executed. + + + + + An ALTER TABLE Transact-SQL statement was executed. + + + + + An ALTER TRIGGER Transact-SQL statement was executed. + + + + + An ALTER USER Transact-SQL statement was executed. + + + + + An ALTER VIEW Transact-SQL statement was executed. + + + + + A CREATE APPLICATION ROLE Transact-SQL statement was executed. + + + + + A CREATE ASSEMBLY Transact-SQL statement was executed. + + + + + A CREATE_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. + + + + + A CREATE CONTRACT Transact-SQL statement was executed. + + + + + A CREATE EVENT NOTIFICATION Transact-SQL statement was executed. + + + + + A CREATE FUNCTION Transact-SQL statement was executed. + + + + + A CREATE INDEX Transact-SQL statement was executed. + + + + + A CREATE LOGIN Transact-SQL statement was executed. + + + + + A CREATE MESSAGE TYPE Transact-SQL statement was executed. + + + + + A CREATE PARTITION FUNCTION Transact-SQL statement was executed. + + + + + A CREATE PARTITION SCHEME Transact-SQL statement was executed. + + + + + A CREATE PROCEDURE Transact-SQL statement was executed. + + + + + A CREATE QUEUE Transact-SQL statement was executed. + + + + + A CREATE ROLE Transact-SQL statement was executed. + + + + + A CREATE ROUTE Transact-SQL statement was executed. + + + + + A CREATE SCHEMA Transact-SQL statement was executed. + + + + + Not available. + + + + + A CREATE SERVICE Transact-SQL statement was executed. + + + + + A CREATE SYNONYM Transact-SQL statement was executed. + + + + + A CREATE TABLE Transact-SQL statement was executed. + + + + + A CREATE TRIGGER Transact-SQL statement was executed. + + + + + A CREATE TYPE Transact-SQL statement was executed. + + + + + A CREATE USER Transact-SQL statement was executed. + + + + + A CREATE VIEW Transact-SQL statement was executed. + + + + + A DELETE Transact-SQL statement was executed. + + + + + A DENY Object Permissions Transact-SQL statement was executed. + + + + + A DENY Transact-SQL statement was executed. + + + + + A DROP APPLICATION ROLE Transact-SQL statement was executed. + + + + + A DROP ASSEMBLY Transact-SQL statement was executed. + + + + + A DROP_REMOTE_SERVICE_BINDING event type was specified when an event notification was created on the database or server instance. + + + + + A DROP CONTRACT Transact-SQL statement was executed. + + + + + A DROP EVENT NOTIFICATION Transact-SQL statement was executed. + + + + + A DROP FUNCTION Transact-SQL statement was executed. + + + + + A DROP INDEX Transact-SQL statement was executed. + + + + + A DROP LOGIN Transact-SQL statement was executed. + + + + + A DROP MESSAGE TYPE Transact-SQL statement was executed. + + + + + A DROP PARTITION FUNCTION Transact-SQL statement was executed. + + + + + A DROP PARTITION SCHEME Transact-SQL statement was executed. + + + + + A DROP PROCEDURE Transact-SQL statement was executed. + + + + + A DROP QUEUE Transact-SQL statement was executed. + + + + + A DROP ROLE Transact-SQL statement was executed. + + + + + A DROP ROUTE Transact-SQL statement was executed. + + + + + A DROP SCHEMA Transact-SQL statement was executed. + + + + + Not available. + + + + + A DROP SERVICE Transact-SQL statement was executed. + + + + + A DROP SYNONYM Transact-SQL statement was executed. + + + + + A DROP TABLE Transact-SQL statement was executed. + + + + + A DROP TRIGGER Transact-SQL statement was executed. + + + + + A DROP TYPE Transact-SQL statement was executed. + + + + + A DROP USER Transact-SQL statement was executed. + + + + + A DROP VIEW Transact-SQL statement was executed. + + + + + A GRANT OBJECT Transact-SQL statement was executed. + + + + + A GRANT Transact-SQL statement was executed. + + + + + An INSERT Transact-SQL statement was executed. + + + + + An invalid trigger action, one that is not exposed to the user, occurred. + + + + + A REVOKE OBJECT Transact-SQL statement was executed. + + + + + A REVOKE Transact-SQL statement was executed. + + + + + An UPDATE Transact-SQL statement was executed. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml index 5a69be7478..a6444f700a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml @@ -2,7 +2,7 @@ - This class implements and is used for active directory federated authentication mechanisms. + This class implements and is used for active directory federated authentication mechanisms. @@ -11,78 +11,165 @@ - Client Application Id to be used for acquiring an access token for federated authentication. The driver uses its own application client id by default. + + Client Application Id to be used for acquiring an access token for federated authentication. The driver uses its own application client id by default. + Initializes the class with the provided application client id. - - - + The following example demonstrates providing a user-defined application client id to SqlClient for the "Active Directory Interactive" authentication method: + + using System; + using Microsoft.Data.SqlClient; -## Examples - The following example demonstrates providing a user-defined application client id to SqlClient for the "Active Directory Interactive" authentication method: - - [!code-csharp[ActiveDirectory_ApplicationClientId Example#1](~/../sqlclient/doc/samples/ApplicationClientIdAzureAuthenticationProvider.cs#1)] - - ]]> - - + namespace CustomAuthenticationProviderExamples + { + public class Program + { + public static void Main() + { + // Supported for all authentication modes supported by ActiveDirectoryAuthenticationProvider + ActiveDirectoryAuthenticationProvider provider = new ActiveDirectoryAuthenticationProvider("<application_client_id>"); + if (provider.IsSupported(SqlAuthenticationMethod.ActiveDirectoryInteractive)) + { + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, provider); + } + + using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Interactive;Database=>db<;")) + { + sqlConnection.Open(); + Console.WriteLine("Connected successfully!"); + } + } + } + } + + - The callback method to be used with 'Active Directory Device Code Flow' authentication. - (Optional) Client Application Id to be used for acquiring an access token for federated authentication. The driver uses its own application client id by default. + + The callback method to be used with 'Active Directory Device Code Flow' authentication. + + + (Optional) Client Application Id to be used for acquiring an access token for federated authentication. The driver uses its own application client id by default. + Initializes the class with the provided device code flow callback method and application client id. - The Active Directory authentication parameters passed to authentication providers. - Acquires a security token from the authority. - Represents an asynchronous operation that returns the authentication token. + + The Active Directory authentication parameters passed to authentication providers. + + + Acquires a security token from the authority. + + + Represents an asynchronous operation that returns the authentication token. + - Clears cached user tokens from the token provider. - This will cause interactive authentication prompts to appear again if tokens were previously being obtained from the cache. + + Clears cached user tokens from the token provider. + + + This will cause interactive authentication prompts to appear again if tokens were previously being obtained from the cache. + - The callback method to be used with 'Active Directory Device Code Flow' authentication. - Sets the callback method, overriding the default implementation that processes the result for 'Active Directory Device Code Flow' authentication. - - - + The callback method to be used with 'Active Directory Device Code Flow' authentication. + + + Sets the callback method, overriding the default implementation that processes the result for 'Active Directory Device Code Flow' authentication. + + + The following example demonstrates providing a custom device flow callback to SqlClient for the Device Code Flow authentication method: + + using System; + using System.Threading.Tasks; + using Microsoft.Identity.Client; + using Microsoft.Data.SqlClient; -[!code-csharp[ActiveDirectory_DeviceCodeFlowCallback Example#1](~/../sqlclient/doc/samples/AADAuthenticationCustomDeviceFlowCallback.cs#1)] - -]]> - - + namespace CustomAuthenticationProviderExamples + { + public class Program + { + public static void Main() + { + SqlAuthenticationProvider authProvider = new ActiveDirectoryAuthenticationProvider(CustomDeviceFlowCallback); + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, authProvider); + using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Device Code Flow;Database=<db>;")) + { + sqlConnection.Open(); + Console.WriteLine("Connected successfully!"); + } + } + + private static Task CustomDeviceFlowCallback(DeviceCodeResult result) + { + // Provide custom logic to process result information and read device code. + Console.WriteLine(result.Message); + return Task.FromResult(0); + } + } + } + + + - The parent as an object, in order to be used from shared .NET Standard assemblies. - Sets a reference to the ViewController (if using Xamarin.iOS), Activity (if using Xamarin.Android) IWin32Window or IntPtr (if using .NET Framework). Used for invoking the browser for Active Directory Interactive authentication. - Mandatory to be set only on Android. See https://aka.ms/msal-net-android-activity for further documentation and details. + + The parent as an object, in order to be used from shared .NET Standard assemblies. + + + Sets a reference to the ViewController (if using Xamarin.iOS), Activity (if using Xamarin.Android) IWin32Window or IntPtr (if using .NET Framework). Used for invoking the browser for Active Directory Interactive authentication. + + + Mandatory to be set only on Android. See https://aka.ms/msal-net-android-activity for further documentation and details. + - A function to return the current window. - Sets a reference to the current that triggers the browser to be shown. Used to center the browser pop-up onto this window." + + A function to return the current window. + + + Sets a reference to the current that triggers the browser to be shown. Used to center the browser pop-up onto this window." + - The callback method to be called by MSAL.NET to delegate the Web user interface with the Secure Token Service (STS). - Sets a callback method which is invoked with a custom Web UI instance that will let the user sign-in with Azure Active Directory, present consent if needed, and get back the authorization code. Applicable when working with Active Directory Interactive authentication. - The "authorizationUri" is crafted to leverage PKCE in order to protect the token from a man in the middle attack. Only MSAL.NET can redeem the code. In the event of cancellation, the implementer should return . + + The callback method to be called by MSAL.NET to delegate the Web user interface with the Secure Token Service (STS). + + + Sets a callback method which is invoked with a custom Web UI instance that will let the user sign-in with Azure Active Directory, present consent if needed, and get back the authorization code. Applicable when working with Active Directory Interactive authentication. + + + The "authorizationUri" is crafted to leverage PKCE in order to protect the token from a man in the middle attack. Only MSAL.NET can redeem the code. In the event of cancellation, the implementer should return . + - The authentication method. - This method is called immediately before the provider is added to authentication provider registry. - Avoid performing long-waiting tasks in this method, since it can block other threads from accessing the provider registry. + + The authentication method. + + + This method is called immediately before the provider is added to authentication provider registry. + + + Avoid performing long-waiting tasks in this method, since it can block other threads from accessing the provider registry. + - The authentication method. - This method is called immediately before the provider is removed from the authentication provider registry. - For example, this method is called when a different provider with the same authentication method overrides this provider in the authentication provider registry. Avoid performing long-waiting task in this method, since it can block other threads from accessing the provider registry. + + The authentication method. + + + This method is called immediately before the provider is removed from the authentication provider registry. + + + For example, this method is called when a different provider with the same authentication method overrides this provider in the authentication provider registry. Avoid performing long-waiting task in this method, since it can block other threads from accessing the provider registry. + The authentication method. @@ -91,23 +178,17 @@ The following example demonstrates providing a custom device flow callback to Sq if the specified authentication method is supported; otherwise, . - - are: - -- Active Directory Password -- Active Directory Integrated -- Active Directory Interactive -- Active Directory Service Principal -- Active Directory Device Code Flow -- Active Directory Managed Identity -- Active Directory MSI -- Active Directory Default - - ]]> - + The supported authentication modes with are: + + Active Directory Password + Active Directory Integrated + Active Directory Interactive + Active Directory Service Principal + Active Directory Device Code Flow + Active Directory Managed Identity + Active Directory MSI + Active Directory Default + diff --git a/doc/snippets/Microsoft.Data.SqlClient/ApplicationIntent.xml b/doc/snippets/Microsoft.Data.SqlClient/ApplicationIntent.xml index e4c32bb13d..621c3461c3 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/ApplicationIntent.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/ApplicationIntent.xml @@ -1,20 +1,23 @@ - - - - - Specifies a value for . Possible values are and . - - To be added. - - - The application workload type when connecting to a server is read write. - 0 - 0 - - - The application workload type when connecting to a server is read only. - 1 - 1 - - + + + + + Specifies a value for . Possible values are and . + + + + + The application workload type when connecting to a server is read write. + + 0 + 0 + + + + The application workload type when connecting to a server is read only. + + 1 + 1 + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/OnChangeEventHandler.xml b/doc/snippets/Microsoft.Data.SqlClient/OnChangeEventHandler.xml index 57c5fbf909..1ec1ff2ee3 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/OnChangeEventHandler.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/OnChangeEventHandler.xml @@ -1,17 +1,16 @@ - - - - The source of the event. - A object that contains the event data. - Handles the event that is fired when a notification is received for any of the commands associated with a object. - - event does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate . - -]]> - - - + + + + The source of the event. + + A object that contains the event data. + + + Handles the event that is fired when a notification is received for any of the commands associated with a object. + + + The event does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/PoolBlockingPeriod.xml b/doc/snippets/Microsoft.Data.SqlClient/PoolBlockingPeriod.xml index 43f4046304..acd15441e7 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/PoolBlockingPeriod.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/PoolBlockingPeriod.xml @@ -1,20 +1,20 @@ - - - Specifies a value for the property. - To be added. - - - Blocking period OFF for Azure SQL servers, but ON for all other SQL servers. - 0 - - - Blocking period ON for all SQL servers including Azure SQL servers. - 1 - - - Blocking period OFF for Azure SQL servers, but ON for all other SQL servers. - 2 - - + + + Specifies a value for the property. + To be added. + + + Blocking period OFF for Azure SQL servers, but ON for all other SQL servers. + 0 + + + Blocking period ON for all SQL servers including Azure SQL servers. + 1 + + + Blocking period OFF for all SQL servers, including Azure SQL servers. + 2 + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SQLDebugging.xml b/doc/snippets/Microsoft.Data.SqlClient/SQLDebugging.xml index c56e9bc8fe..d9f7a5f014 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SQLDebugging.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SQLDebugging.xml @@ -1,16 +1,14 @@ - - - - - Included to support debugging applications. Not intended for direct use. - - To be added. - - - - Initiates instance of class object. Not intended for direct use. - - To be added. - - + + + + + Included to support debugging applications. Not intended for direct use. + + + + + Initiates instance of class object. Not intended for direct use. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SortOrder.xml b/doc/snippets/Microsoft.Data.SqlClient/SortOrder.xml index 7a6def3284..d28534a83f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SortOrder.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SortOrder.xml @@ -1,25 +1,22 @@ - - - - - Specifies how rows of data are sorted. - - To be added. - - - The default. No sort order is specified. - -1 - -1 - - - Rows are sorted in ascending order. - 0 - 0 - - - Rows are sorted in descending order. - 1 - 1 - - + + + + Specifies how rows of data are sorted. + + + The default. No sort order is specified. + -1 + -1 + + + Rows are sorted in ascending order. + 0 + 0 + + + Rows are sorted in descending order. + 1 + 1 + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationInitializer.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationInitializer.xml index 41a3734d3d..8c64ac37de 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationInitializer.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationInitializer.xml @@ -1,14 +1,19 @@ - - - - Called from constructors in derived classes to initialize the class. - To be added. - - - Default Constructor to initialize the class. - - - When overridden in a derived class, initializes the authentication initializer. This method is called by the constructor during startup. - - + + + + + Called during the opening of the first instance to specify an Authentication connection string attribute. + + + + + Default constructor to instantiate the class. + + + + + When overridden in a derived class, initializes the authentication initializer. This method is called immediately after the constructor during the opening of the first instance to specify an Authentication connection string attribute. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml index a52a2ec41a..cd15a65ec2 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml @@ -1,49 +1,51 @@ - - - Describes the different SQL authentication methods that can be used by a client connecting to Azure SQL Database. For details, see Connecting to SQL Database By Using Azure Active Directory Authentication. - - To be added. - - - The authentication method is not specified. - 0 - - - The authentication method is Sql Password. - 1 - - - The authentication method uses Active Directory Password. Use Active Directory Password to connect to a SQL Database using an Azure AD principal name and password. - 2 - - - The authentication method uses Active Directory Integrated. Use Active Directory Integrated to connect to a SQL Database using integrated Windows authentication. - 3 - - - The authentication method uses Active Directory Interactive. Use Active Directory Interactive to connect to a SQL Database with an interactive authentication flow. - 4 - - - The authentication method uses Active Directory Service Principal. Use Active Directory Service Principal to connect to a SQL Database using the client ID and secret of a service principal identity. - 5 - - - The authentication method uses Active Directory Device Code Flow. Use Active Directory Device Code Flow to connect to a SQL Database from devices and operating systems that do not provide a Web browser, using another device to perform interactive authentication. - 6 - - - The authentication method uses Active Directory Managed Identity. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. - 7 - - - Alias for "Active Directory Managed Identity" authentication method. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. - 8 - - - The authentication method uses Active Directory Default. Use this mode to connect to a SQL Database using multiple non-interactive authentication methods tried sequentially to acquire an access token. This method does not fallback to the "Active Directory Interactive" authentication method. - 9 - - + + + Describes the different SQL authentication methods that can be used by a client connecting to Azure SQL Database. For details, see Use Microsoft Entra Authentication. + + + The authentication method is not specified. + 0 + + + The authentication method uses Sql Password. Use Sql Password to connect to a SQL Database using SQL Server authentication. + 1 + + + The authentication method uses Active Directory Password. Use Active Directory Password to connect to a SQL Database using a Microsoft Entra principal name and password. + 2 + + + The authentication method uses Active Directory Integrated. Use Active Directory Integrated to connect to a SQL Database using integrated Windows authentication. + 3 + + + The authentication method uses Active Directory Interactive. Use Active Directory Interactive to connect to a SQL Database with an interactive authentication flow. + 4 + + + The authentication method uses Active Directory Service Principal. Use Active Directory Service Principal to connect to a SQL Database using the client ID and secret of a service principal identity. + 5 + + + The authentication method uses Active Directory Device Code Flow. Use Active Directory Device Code Flow to connect to a SQL Database from devices and operating systems that do not provide a Web browser, using another device to perform interactive authentication. + 6 + + + The authentication method uses Active Directory Managed Identity. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. + 7 + + + Alias for "Active Directory Managed Identity" authentication method. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. + 8 + + + The authentication method uses Active Directory Default. Use this mode to connect to a SQL Database using multiple non-interactive authentication methods tried sequentially to acquire an access token. This method does not fallback to the "Active Directory Interactive" authentication method. + 9 + + + The authentication method uses Active Directory Workload Identity. Use a federated User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Workload Identity. The 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. + 10 + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml index 51fec0ae1f..7c409cdc5c 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml @@ -1,55 +1,59 @@ - - - - Represents AD authentication parameters passed by a driver to authentication providers. - - - One of the enumeration values that specifies the authentication method. - The server name. - The database name. - The resource URI. - The authority URI. - The user login name/ID. - The user password. - The connection ID. - The connection timeout value in seconds. - Initializes a new instance of the class using the specified authentication method, server name, database name, resource URI, authority URI, user login name/ID, user password, connection ID and connection timeout value. - - - Gets the authentication method. - The authentication method. - - - The resource URIs. - The resource URI. - - - Gets the authority URI. - The authority URI. - - - Gets the user login name/ID. - The user login name/ID. - - - Gets the user password. - The user password. - - - Gets the connection ID. - The connection ID. - - - Gets the server name. - The server name. - - - Gets the database name. - The database name. - - - Gets the connection timeout value. - The connection timeout value to be passed to Cancellation Token Source. - - + + + + + Represents AD authentication parameters passed by a driver to authentication providers. + + + + One of the enumeration values that specifies the authentication method. + The server name. + The database name. + The resource URI. + The authority URI. + The user login name/ID. + The user password. + The connection ID. + The connection timeout value in seconds. + + Initializes a new instance of the class using the specified authentication method, server name, database name, resource URI, authority URI, user login name/ID, user password, connection ID and connection timeout value. + + + + Gets the authentication method. + The authentication method. + + + The resource URIs. + The resource URI. + + + Gets the authority URI. + The authority URI. + + + Gets the user login name/ID. + The user login name/ID. + + + Gets the user password. + The user password. + + + Gets the connection ID. + The connection ID. + + + Gets the server name. + The server name. + + + Gets the database name. + The database name. + + + Gets the connection timeout value. + The connection timeout value to be passed to Cancellation Token Source. + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml index 4f21b9626f..75cc752d76 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml @@ -1,22 +1,93 @@ - + - Defines the core behavior of authentication providers and provides a base class for derived classes. + Defines the core behavior of authentication providers and provides a base class for derived classes. - - - + Derived classes must provide a parameterless constructor if they can be instantiated from the app.config file. + + The following example demonstrates implementing a custom SqlAuthenticationProvider and providing the same to SqlClient for overriding Device Code Flow authentication mode: + + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Data.SqlClient; + using Microsoft.Identity.Client; + + namespace CustomAuthenticationProviderExamples + { + /// <summary> + /// Example demonstrating creating a custom device code flow authentication provider and attaching it to the driver. + /// This is helpful for applications that wish to override the Callback for the Device Code Result implemented by the SqlClient driver. + /// </summary> + public class CustomDeviceCodeFlowAzureAuthenticationProvider : SqlAuthenticationProvider + { + private const string ClientId = "my-client-id"; + private const string ClientName = "My Application Name"; + private const string DefaultScopeSuffix = "/.default"; + + // Maintain a copy of the PublicClientApplication object to cache the underlying access tokens it provides + private static IPublicClientApplication pcApplication; + + public override async Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters) + { + string[] scopes = [ parameters.Resource.EndsWith(DefaultScopeSuffix) ? parameters.Resource : parameters.Resource + DefaultScopeSuffix ]; + + IPublicClientApplication app = pcApplication; + if (app == null) + { + pcApplication = app = PublicClientApplicationBuilder.Create(ClientId) + .WithAuthority(parameters.Authority) + .WithClientName(ClientName) + .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") + .Build(); + } + + AuthenticationResult result; + using CancellationTokenSource connectionTimeoutCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(parameters.ConnectionTimeout)); + + try + { + IEnumerable<IAccount> accounts = await app.GetAccountsAsync(); + result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) + .ExecuteAsync(connectionTimeoutCancellation.Token); + } + catch (MsalUiRequiredException) + { + result = await app.AcquireTokenWithDeviceCode(scopes, deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)) + .ExecuteAsync(connectionTimeoutCancellation.Token); + } + + return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); + } + + public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) => + authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow); + + private Task CustomDeviceFlowCallback(DeviceCodeResult result) + { + Console.WriteLine(result.Message); + return Task.CompletedTask; + } + } + + public class Program + { + public static void Main() + { + // Register our custom authentication provider class to override Active Directory Device Code Flow + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, new CustomDeviceCodeFlowAzureAuthenticationProvider()); + using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Device Code Flow;Database=<db>;")) + { + sqlConnection.Open(); + Console.WriteLine("Connected successfully!"); + } + } + } + } + + @@ -26,10 +97,7 @@ The authentication method. Gets an authentication provider by method. - - The authentication provider or if not found. - - To be added. + The authentication provider or if not found. The authentication method. @@ -38,17 +106,20 @@ if the operation succeeded; otherwise, (for example, the existing provider disallows overriding). - To be added. The authentication method. - This method is called immediately before the provider is added to SQL drivers registry. - Avoid performing long-waiting tasks in this method, since it can block other threads from accessing the provider registry. + This method is called immediately before the provider is added to the SQL authentication provider registry. + + Avoid performing long-waiting tasks in this method, since it can block other threads from accessing the provider registry. + The authentication method. - This method is called immediately before the provider is removed from the SQL drivers registry. - For example, this method is called when a different provider with the same authentication method overrides this provider in the SQL drivers registry. Avoid performing long-waiting task in this method, since it can block other threads from accessing the provider registry. + This method is called immediately before the provider is removed from the SQL authentication provider registry. + + For example, this method is called when a different provider with the same authentication method overrides this provider in the SQL authentication provider registry. Avoid performing long-waiting task in this method, since it can block other threads from accessing the provider registry. + The authentication method. @@ -56,13 +127,11 @@ if the specified authentication method is supported; otherwise, . - To be added. The Active Directory authentication parameters passed by the driver to authentication providers. Acquires a security token from the authority. Represents an asynchronous operation that returns the AD authentication token. - To be added. diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationToken.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationToken.xml index 21818f4f5b..52f79dd535 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationToken.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationToken.xml @@ -1,21 +1,25 @@ - - - - Represents an AD authentication token. - - - The access token. - The token expiration time. - Initializes a new instance of the class. - The parameter is or empty. - - - Gets the token expiration time. - The token expiration time. - - - Gets the token string. - The token string. - - + + + + Represents an authentication token. + + + The access token. + The token expiration time. + + Initializes a new instance of the class. + + + The parameter is or empty. + + + + Gets the token expiration time. + The token expiration time. + + + Gets the token string. + The token string. + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBatch.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBatch.xml new file mode 100644 index 0000000000..a961ce136c --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBatch.xml @@ -0,0 +1,429 @@ + + + + + + The following example creates a and a , then adds multiple objects to the batch. It then executes the batch, creating a . The example reads through the results of the batch commands, writing them to the console. Finally, the example closes the and then the as the using blocks fall out of scope. + + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + using var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + var results = new List<int>(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue<int>(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } + } + + + + + Initializes a new . + + + The following example creates a and a , then adds multiple objects to the batch. It then executes the batch, creating a . The example reads through the results of the batch commands, writing them to the console. Finally, the example closes the and then the as the using blocks fall out of scope. + + + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + using var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + var results = new List<lint>(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue<int>(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } + } + + + + + Initializes a new . + + A that represents the connection to an instance of SQL Server. + + + The in which the executes. + + + + + Gets or sets the used by this instance of the . + + + + + Gets or sets the within which the commands execute. + + + + + The list of commands contained in the batch in a . + + + + The following example creates a and a , then adds multiple objects to the batch. It then executes the batch, creating a . The example reads through the results of the batch commands, writing them to the console. Finally, the example closes the and then the as the using blocks fall out of scope. + + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + using var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + var results = new List<int>(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue<int>(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } + } + + + + + + The list of commands contained in the batch in a . + + + + + Sends the to the and builds a . + + + + The following example creates a and a , then adds multiple objects to the batch. It then executes the batch, creating a . The example reads through the results of the batch commands, writing them to the console. Finally, the example closes the and then the as the using blocks fall out of scope. + + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + using var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + var results = new List<int>(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue<int>(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } + } + + + + + A token to cancel the asynchronous operation. + + An asynchronous version of , which sends the to the and builds a . + Exceptions will be reported via the returned Task object. + + A task representing the asynchronous operation. + + An error occurred while executing the batch. + + + The value is invalid. + + + The cancellation token was canceled. This exception is stored into the returned task. + + + + Gets the collection of objects. + The commands contained within the batch. + + + + Gets or sets the used by this . + + The connection to the data source. + + + + Gets or sets the within which this object executes. + + + The transaction within which a batch of a ADO.NET data provider executes. The default value is a null reference ( in Visual Basic). + + + + + Gets or sets the wait time (in seconds) before terminating the attempt to execute the batch and generating an error. + + + The time in seconds to wait for the batch to execute, which is in contract with the underlying + + + + An is generated if the assigned property value is less than 0. + + + Note to implementers: it's recommended that 0 mean no timeout. + + + + + + Attempts to cancel the execution of a . + + + If there is nothing to cancel, nothing happens. However, if there is a batch in process, and the attempt to cancel fails, no exception is generated. + + + + Creates a new instance of a object. + A object. + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + An instance of , specifying options for batch execution and data retrieval. + + + Executes the batch against its connection, returning a which can be used to access the results. + + A object. + + When the batch returns multiple result sets from different commands, can be used to advance the reader to the next result set. + + This method benefits from , and all the expected exceptions of that method also apply here. + + + + An error occurred while executing the batch. + + + The value is invalid. + + + + One of the enumeration values that specifies options for batch execution and data retrieval. + A token to cancel the asynchronous operation. + + This implementation invokes the method and returns a completed task. The default implementation will return a cancelled task if passed an already cancelled cancellation token. This method accepts a cancellation token that can be used to request the operation to be cancelled early. + + A task representing the asynchronous operation. + + + For more information about asynchronous programming, see Asynchronous Programming. + + + This method stores in the task it returns all non-usage exceptions that the method's synchronous counterpart can throw. If an exception is stored into the returned task, that exception will be thrown when the task is awaited. Usage exceptions, such as , are still thrown synchronously. For the stored exceptions, see the exceptions thrown by . + + + This method benefits from , and all the expected exceptions of that method also apply here. + + + + The cancellation token was canceled. This exception is stored into the returned task. + + + + + Executes the batch against its connection object, returning the total number of rows affected across all the batch commands. + + The total number of rows affected across all the batch commands. + + You can use to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database by executing UPDATE, INSERT, or DELETE statements. Although does not return any rows, any output parameters or return values mapped to parameters are populated with data. For UPDATE, INSERT, and DELETE statements, the return value is the total number of rows affected by the batch. If no UPDATE, INSERT, or DELETE statements are included in the batch, the return value is -1. + + This method benefits from , and all the expected exceptions of that method also apply here. + + + + + A token to cancel the asynchronous operation. + + This is the asynchronous version of . + The implementation invokes the method and returns a completed task. The default implementation will return a cancelled task if passed an already cancelled cancellation token. + Do not invoke other methods and properties of the object until the returned Task is complete. + + A task representing the asynchronous operation. + + + For more information about asynchronous programming, see Asynchronous Programming. + + + If an exception is stored into the returned task, that exception will be thrown when the task is awaited. Usage exceptions, such as , are still thrown synchronously. + + + This method benefits from , and all the expected exceptions of that method also apply here. + + + An error occurred while executing the batch. + ADO.NET Overview + + The cancellation token was canceled. This exception is stored into the returned task. + + + + + Executes the batch and returns the first column of the first row in the first returned result set. All other columns, rows and resultsets are ignored. + + The first column of the first row in the first result set. + + An error occurred while executing the batch. + + + + A token to cancel the asynchronous operation. + + An asynchronous version of , which executes the batch and returns the first column of the first row in the first returned result set. All other columns, rows and result sets are ignored. + + The first column of the first row in the first result set. + + This method benefits from , and all the expected exceptions of that method also apply here. If an exception is stored into the returned task, that exception will be thrown when the task is awaited. Usage exceptions, such as , are still thrown synchronously. + + + An error occurred while executing the batch. + + + The cancellation token was canceled. This exception is stored into the returned task. + + + + + Creates a prepared (or compiled) version of the batch, or of each of its commands, on the data source. + + + + + An optional token to cancel the asynchronous operation. The default value is . + + + Asynchronously creates a prepared (or compiled) version of the batch, or of each of its commands, on the data source. + + A representing the asynchronous operation. + + This method stores in the task it returns all non-usage exceptions that the method's synchronous counterpart can throw. If an exception is stored into the returned task, that exception will be thrown when the task is awaited. Usage exceptions, such as , are still thrown synchronously. For the stored exceptions, see the exceptions thrown by . + + + The cancellation token was canceled. This exception is stored into the returned task. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommand.xml new file mode 100644 index 0000000000..cfce5cfce9 --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommand.xml @@ -0,0 +1,142 @@ + + + + + SqlBatchCommand allows for the execution of multiple SQL commands in a SqlBatch. + + + + + Initializes a new . + + + The following example creates a and a SqlBatch, then adds multiple objects to the batch. It then executes the batch, creating a . The example reads through the results of the batch commands, writing them to the console. Finally, the example closes the and then the as the using blocks fall out of scope. + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + // Optionally Prepare + batch.Prepare(); + + var results = new List<int>(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue<int>(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } + } + + + + + + + Initializes a new . + + + The text of the . + + + Indicates how the property is to be interpreted. + + + A collection of objects is used to create the . + + + The encryption setting. For more information, see Always Encrypted. + + + + + Gets the . + + + The parameters of the Transact-SQL statement or stored procedure. The default is an empty collection. + + + + + One of the values, indicating options for statement execution and data retrieval. + + + + + Not currently implemented. + The encryption setting. For more information, see Always Encrypted. + + + + + Creates a new instance of a object. + + + + + Returns whether the method is implemented. + + + + + Gets or sets the text command to run against the data source. + + + The text command to execute. The default value is an empty string (""). + + + + + Gets or sets how the property is interpreted. + + + One of the enumeration values that specifies how a command string is interpreted. The default is . + + + + + Gets the collection of objects. + + + The parameters of the SQL statement or stored procedure. + + + + + Gets the number of rows changed, inserted, or deleted by execution of this specific . + + + The number of rows changed, inserted, or deleted. -1 for SELECT statements; 0 if no rows were affected or the statement failed. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommandCollection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommandCollection.xml new file mode 100644 index 0000000000..3fd55b6a24 --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBatchCommandCollection.xml @@ -0,0 +1,183 @@ + + + + + A collection of instances of , contained within a . + + + + + Add a to the end of the . + + + + + The object to add to the . + + + Adds the specified object to the . + + + + + Determines whether a is in the . + + + + + The object to locate in the . + + + Indicates whether a is contained in the collection. + + + if the is in the collection; otherwise . + + + + + Copies the entire to a one dimensional array, starting at the target index of the target array. + + + + + The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. + + + The zero-based index in at which copying begins. + + + Copies the elements of the to an , starting at a particular index. + + + + + Searches for the specified within the and returns the zero-based index of the first occurrence within the entire . + + + Returns the zero-based index of the first occurrence within the entire . + + + + + The object to locate in the . + + + Returns the index of the specified object. + + + The index of the specified object. + + + + + Inserts an item into the at the specified index. + + + + + The index at which to insert the object. + + + The object to insert into the . + + + Inserts the specified index of the object with the specified name into the collection at the specified index. + + + + + Removes the first occurrence of a specific object from the collection. + + + Returns if an item is successfully removed. Returns false if an item could not be removed or no item was not found. + + + + + The object to remove from the . + + + Removes the specified object from the collection. + + + if was successfully removed; otherwise, . This method also returns if was not found in the . + + + + + Gets or Sets the element at the specified index. + + + The element at the specified index. + + + + + Gets or Sets the element at the specified index. + + + The element at the specified index. + + + + + The index where the object is located. + + + Returns the object at the specified index in the list. + + + The object at the specified index in the list. + + + + + The index where the object should be located. + + + The object to add to the collection. + + + Sets the object at the specified index to a new value. + + + + + Gets the number of elements contained in the . + + + The number of elements contained in the . + + + + + Specifies whether the collection is read-only. + + + if the collection is read-only; otherwise . + + + + + Returns the object at the specified index in the collection. + + + The object at the specified index in the collection. + + + + + Removes all values from the . + + + + + The index where the object is located. + + + Removes the object at the specified index from the collection. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml index 06fdf1b5b6..2e75dbbd62 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopy.xml @@ -1,520 +1,1247 @@ - - - - - Lets you efficiently bulk load a SQL Server table with data from another source. - - - class lets you write managed code solutions that provide similar functionality. There are other ways to load data into a SQL Server table (INSERT statements, for example), but offers a significant performance advantage over them. The class can be used to write data only to SQL Server tables. However, the data source is not limited to SQL Server; any data source can be used, as long as the data can be loaded to a instance or read with a instance. will fail when bulk loading a column of type into a SQL Server column whose type is one of the date/time types added in SQL Server 2008. - -## Examples -The following console application demonstrates how to load data using the class. -In this example, a is used to copy data from the **Production.Product** table in the SQL Server **AdventureWorks** database to a similar table in the same database. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[BulkCopy.Single#1](~/../sqlclient/doc/samples/SqlBulkCopy_Single.cs#1)] -]]> - - - - - The already open - - instance that will be used to perform the bulk copy operation. If your connection string does not use - - , you can use - - to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - - - Initializes a new instance of the - - class using the specified open instance of - - . - - - instance is initialized, the connection remains open after the instance is closed. -If the `connection` argument is null, an is thrown. - -## Examples -The following console application demonstrates how to bulk load data using a connection that is already open. In this example, a -is used to copy data from the **Production.Product** table in the SQL Server **AdventureWorks** database to a similar table in the same database. This example is for demonstration -purposes only. You would not use `SqlBulkCopy` to move data from one table to another in the same database in a production application. -Note that the source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a -. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[BulkCopy.Single#1](~/../sqlclient/doc/samples/SqlBulkCopy_Single.cs#1)] -]]> - - - - - The already open - - instance that will be used to perform the bulk copy. If your connection string does not use - - , you can use - - to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - - - A combination of values from the - - enumeration that determines which data source rows are copied to the destination table. - - - An existing - - instance under which the bulk copy will occur. - - - Initializes a new instance of the - - class using the supplied existing open instance of - - . The - - instance behaves according to options supplied in the - - parameter. If a non-null - - is supplied, the copy operations will be performed within that transaction. - - - - - - Performing Bulk Copy Operations - - - Overview of the SqlClient driver - - - - - The string defining the connection that will be opened for use by the - - instance. - If your connection string does not use - - , you can use - - or - - and - - to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - - - Initializes and opens a new instance of - - based on the supplied - - . The constructor uses the - - to initialize a new instance of the - - class. - - - is thrown. If `connectionString` is an empty string, an is thrown. - -## Examples -The following console application demonstrates how to bulk load data by using a connection specified as a string. The connection is automatically -closed when the instance is closed. -In this example, the source data is first read from a SQL Server table to a instance. -The source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ConnectionString#1](~/../sqlclient/doc/samples/SqlBulkCopy_ConnectionString.cs#1)] -]]> - - - If `connectionString` is an empty string, an - - is thrown. - - - - - The string defining the connection that will be opened for use by the - - instance. If your connection string does not use - - , you can use - - or - - and - - to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - - - A combination of values from the - - enumeration that determines which data source rows are copied to the destination table. - - - Initializes and opens a new instance of - - based on the supplied - - . The constructor uses that - - to initialize a new instance of the - - class. The - - instance behaves according to options supplied in the - - parameter. - - - topic. - -## Examples -The following console application demonstrates how to perform a bulk load by using a connection specified as a string. -An option is set to use the value in the identity column of the source table when you load the destination table. In this example, -the source data is first read from a SQL Server table to a instance. -The source table and destination table each include an Identity column. By default, a new value for the **Identity** column is generated in the destination table for each row added. -In this example, an option is set when the connection is opened that forces the bulk load process to use the **Identity** values from the source table instead. -To see how the option changes the way the bulk load works, run the sample with the **dbo.BulkCopyDemoMatchingColumns** table empty. All rows load from the source. -Then run the sample again without emptying the table. An exception is thrown and the code writes a message to the console notifying you that rows weren't -added because of primary key constraint violations. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided to -demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement -to copy the data. - -[!code-csharp[SqlBulkCopy.KeepIdentity#1](~/../sqlclient/doc/samples/SqlBulkCopy_KeepIdentity.cs#1)] -]]> - - - - - Number of rows in each batch. At the end of each batch, the rows in the batch are sent to the server. - - - The integer value of the - - property, or zero if no value has been set. - - - rows have been processed or there are no more rows to send to the destination data source. - -Zero (the default) indicates that each operation is a single batch. - -If the instance has been declared without the option in effect, -rows are sent to the server rows at a time, but no transaction-related action is taken. -If is in effect, each batch of rows is inserted as a separate transaction. - -The property can be set at any time. If a bulk copy is already in progress, the current batch is sized according to the previous batch size. -Subsequent batches use the new size. If the is initially zero and changed while a -operation is already in progress, that operation loads the data as a single batch. Any subsequent -operations on the same instance use the new . - -## Examples -The following console application demonstrates how to bulk load data in batches of 50 rows. For an example illustrating how -works with a transaction, see [Transaction and Bulk Copy Operations](/sql/connect/ado-net/sql/transaction-bulk-copy-operations). - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.BatchSize#1](~/../sqlclient/doc/samples/SqlBulkCopy_BatchSize.cs#1)] -]]> - - - - - Number of seconds for the operation to complete before it times out. - - - The integer value of the - - property. The default is 30 seconds. A value of 0 indicates no limit; the bulk copy will wait indefinitely. - - - instance. -The source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.Timeout#1](~/../sqlclient/doc/samples/SqlBulkCopy_Timeout.cs#1)] -]]> - - - - - Closes the instance. - - - on the object, no other operation will succeed. Calls to the method will throw an . Calling the method from the event causes an to be thrown. -Note that open instances are closed implicitly at the end of a `using` block. - -## Examples -The following example uses the same instance to add sales orders and their associated details to two destination tables. Because the **AdventureWorks** sales order tables are large, the sample reads only orders placed by a certain account number and bulk copies those orders and details to the destination tables. The method is used only after both bulk copy operations are complete. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.OrdersDetails#1](~/../sqlclient/doc/samples/SqlBulkCopy_OrdersDetails.cs#1)] -]]> - - - - - Enables or disables a - - object to stream data from an - - object - - - - if a - - object can stream data from an - - object; otherwise, false. The default is - - . - - - is `true`, reads from an object using , -optimizing memory usage by using the streaming capabilities. Streaming is only applicable to max data types (i.e. -VARBINARY(MAX), VARCHAR(MAX), NVARCHAR(MAX), and XML). When is set to false, -the class loads all the data returned by the object into memory before sending it to the server. - -> [!NOTE] -> The main advantage of enabling streaming is reducing memory usage during bulk copy of max data types. -]]> - - - - - Returns a collection of - - items. Column mappings define the relationships between columns in the data source and columns in the destination. - - - A collection of column mappings. By default, it is an empty collection. - - - collection is unnecessary. However, if the column counts differ, -or the ordinal positions are not consistent, you must use to make sure that data is copied into the correct columns. - -During the execution of a bulk copy operation, this collection can be accessed, but it cannot be changed. Any attempt to change it will throw an . -]]> - - - - - Returns a collection of - - items. Column order hints describe the sort order of columns in the clustered index of the destination table. - - - A collection of column order hints. By default, it is an empty collection. - - - + + + + Lets you efficiently bulk load a SQL Server table with data from another source. + + + Microsoft SQL Server includes a popular command-prompt utility named bcp for moving data from one table to another, whether on a single server or between servers. The class lets you write managed code solutions that provide similar functionality. There are other ways to load data into a SQL Server table (INSERT statements, for example), but offers a significant performance advantage over them. The class can be used to write data only to SQL Server tables. However, the data source is not limited to SQL Server; any data source can be used, as long as the data can be loaded to a instance or read with a instance. will fail when bulk loading a column of type into a SQL Server column whose type is one of the date/time types added in SQL Server 2008. + + + The following console application demonstrates how to load data using the class. In this example, a is used to copy data from the Production.Product table in the SQL Server AdventureWorks database to a similar table in the same database. + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Open the destination connection. In the real world you would + // not use SqlBulkCopy to move data from one table to the other + // in the same database. This is for demonstration purposes only. + using (SqlConnection destinationConnection = new SqlConnection(connectionString)) + { + destinationConnection.Open(); + + // Set up the bulk copy object. + // Note that the column positions in the source + // data reader match the column positions in + // the destination table so there is no need to + // map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The already open instance that will be used to perform the bulk copy operation. If your connection string does not use , you can use to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + Initializes a new instance of the class using the specified open instance of . + + + Because the connection is already open when the instance is initialized, the connection remains open after the instance is closed. If the connection argument is null, an is thrown. + + + + The following console application demonstrates how to bulk load data using a connection that is already open. In this example, a is used to copy data from the Production.Product table in the SQL Server AdventureWorks database to a similar table in the same database. This example is for demonstration purposes only. You would not use SqlBulkCopy to move data from one table to another in the same database in a production application. Note that the source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Open the destination connection. In the real world you would + // not use SqlBulkCopy to move data from one table to the other + // in the same database. This is for demonstration purposes only. + using (SqlConnection destinationConnection = new SqlConnection(connectionString)) + { + destinationConnection.Open(); + + // Set up the bulk copy object. + // Note that the column positions in the source + // data reader match the column positions in + // the destination table so there is no need to + // map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The already open instance that will be used to perform the bulk copy. If your connection string does not use , you can use to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + A combination of values from the enumeration that determines which data source rows are copied to the destination table. + + + An existing instance under which the bulk copy will occur. + + + Initializes a new instance of the class using the supplied existing open instance of . The instance behaves according to options supplied in the parameter. If a non-null is supplied, the copy operations will be performed within that transaction. + + + If options include and the argument is not , an InvalidArgumentException is thrown. + + + For examples demonstrating how to use SqlBulkCopy in a transaction, see Transaction and Bulk Copy Operations. + + + Performing Bulk Copy Operations + + + Overview of the SqlClient driver + + + + + + The string defining the connection that will be opened for use by the instance. + + + If your connection string does not use , you can use or and to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + + Initializes and opens a new instance of based on the supplied . The constructor uses the to initialize a new instance of the class. + + + The connection is automatically closed at the end of the bulk copy operation. If is , an is thrown. If is an empty string, an is thrown. + + + + The following console application demonstrates how to bulk load data by using a connection specified as a string. The connection is automatically closed when the instance is closed. In this example, the source data is first read from a SQL Server table to a instance. The source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Set up the bulk copy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + If is an empty string, an is thrown. + + + + + The string defining the connection that will be opened for use by the instance. If your connection string does not use , you can use or and to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + A combination of values from the enumeration that determines which data source rows are copied to the destination table. + + + Initializes and opens a new instance of based on the supplied . The constructor uses that to initialize a new instance of the class. The instance behaves according to options supplied in the parameter. + + + You can obtain detailed information about all the bulk copy options in the topic. + + + + The following console application demonstrates how to perform a bulk load by using a connection specified as a string. An option is set to use the value in the identity column of the source table when you load the destination table. In this example, the source data is first read from a SQL Server table to a instance. The source table and destination table each include an Identity column. By default, a new value for the Identity column is generated in the destination table for each row added. In this example, an option is set when the connection is opened that forces the bulk load process to use the Identity values from the source table instead. To see how the option changes the way the bulk load works, run the sample with the dbo.BulkCopyDemoMatchingColumns table empty. All rows load from the source. Then run the sample again without emptying the table. An exception is thrown and the code writes a message to the console notifying you that rows weren't added because of primary key constraint violations. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); -## Remarks -SqlBulkCopy's performance is improved if the data being imported is sorted according to the clustered index on the table, if any. -If the data is sorted in an order that differs from the order of a clustered index key or if there is no clustered index on the table, the order hint is ignored. -]]> - - - - - Name of the destination table on the server. - - - The string value of the - - property, or null if none as been supplied. - - - has not been set when is called, an -is thrown. If is modified while a operation is running, -the change does not affect the current operation. The new value is used the next time a method is called. - - is a three-part name (`..`). You can qualify the table name with its database and owning schema if you choose. -However, if the table name uses an underscore ("_") or any other special characters, you must escape the name using surrounding brackets as in (`[..]`). - -You can bulk-copy data to a temporary table by using a value such as `tempdb..#table` or `tempdb..#table` for the property. - -## Examples -The following console application demonstrates how to bulk load data using a connection that is already open. The destination table is a table in the **AdventureWorks** database. - -In this example, the connection is first used to read data from a SQL Server table to a instance. The source data does not have to -be located on SQL Server; you can use any data source that can be read to an or loaded to a . - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. -[!code-csharp[SqlBulkCopy.Single#1](~/../sqlclient/doc/samples/SqlBulkCopy_Single.cs#1)] -]]> - - - - - Defines the number of rows to be processed before generating a notification event. - - - The integer value of the - - property, or zero if the property has not been set. - - - property can be set at any time, even while a bulk copy operation is underway. Changes made during a bulk copy operation take effect after -the next notification. The new setting applies to all subsequent operations on the same instance. - -If is set to a number less than zero, an is thrown. - - -## Examples -The following console application demonstrates how to bulk load data using a connection that is already open. The property is set so that -the event handler is called after every 50 rows copied to the table. - -In this example, the connection is first used to read data from a SQL Server table to a instance. Then a second connection is opened to bulk copy the data. -Note that the source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided to -demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` -statement to copy the data. - -[!code-csharp[SqlBulkCopy.NotifyAfter#1](~/../sqlclient/doc/samples/SqlBulkCopy_NotifyAfter.cs#1)] -]]> - - - - - Occurs every time that the number of rows specified by the - - property have been processed. - - - and are independent. Receipt of a - event does not imply that any rows have been sent to the server or committed. - -You cannot call SqlBulkCopy.Close () or SqlConnection.Close () from this event. -Doing this will cause an being thrown, and the object state will not change. If the user wants to cancel the -operation from the event, the property of the can be used. -(See [Transaction and Bulk Copy Operations](/sql/connect/ado-net/sql/transaction-bulk-copy-operations) for examples that use the - property.) - -No action, such as transaction activity, is supported in the connection during the execution of the bulk copy operation, and it is recommended that you not use the same connection used -during the event. However, you can open a different connection. - - -## Examples -The following console application demonstrates how to bulk load data using a connection that is already open. The property is set so that -the event handler is called after every 50 rows copied to the table. - -In this example, the connection is first used to read data from a SQL Server table to a instance. Note that the source data does not have to be located on -SQL Server; you can use any data source that can be read to an or loaded to a . - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier -and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.NotifyAfter#1](~/../sqlclient/doc/samples/SqlBulkCopy_NotifyAfter.cs#1)] -]]> - - - - - The number of rows processed in the ongoing bulk copy operation. - - - The integer value of the - - property. - - - - event and does not imply that this number of rows has been sent to the server or committed. - -This value can be accessed during or after the execution of a bulk copy operation. - -This value will wrap around and become negative if the number of rows exceeds int.MaxValue. Consider using the property. -]]> - - + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string + // and the KeepIdentity option. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Number of rows in each batch. At the end of each batch, the rows in the batch are sent to the server. + + + The integer value of the property, or zero if no value has been set. + + + + A batch is complete when rows have been processed or there are no more rows to send to the destination data source. + + + Zero (the default) indicates that each operation is a single batch. + + + If the instance has been declared without the option in effect, rows are sent to the server rows at a time, but no transaction-related action is taken. If is in effect, each batch of rows is inserted as a separate transaction. + + + The property can be set at any time. If a bulk copy is already in progress, the current batch is sized according to the previous batch size. Subsequent batches use the new size. If the is initially zero and changed while a operation is already in progress, that operation loads the data as a single batch. Any subsequent operations on the same instance use the new . + + + + + The following console application demonstrates how to bulk load data in batches of 50 rows. For an example illustrating how works with a transaction, see Transaction and Bulk Copy Operations. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + // Set the BatchSize. + bulkCopy.BatchSize = 50; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Number of seconds for the operation to complete before it times out. + + + The integer value of the property. The default is 30 seconds. A value of 0 indicates no limit; the bulk copy will wait indefinitely. + + + If the operation does time out, the transaction is not committed and all copied rows are removed from the destination table. + + + + The following console application demonstrates how to modify the time-out to 60 seconds when bulk loading data. In this example, the source data is first read from a SQL Server table to a instance. The source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = + new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Set the timeout. + bulkCopy.BulkCopyTimeout = 60; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Closes the instance. + + + After you call on the object, no other operation will succeed. Calls to the method will throw an . Calling the method from the event causes an to be thrown. Note that open instances are closed implicitly at the end of a using block. + + + + The following example uses the same instance to add sales orders and their associated details to two destination tables. Because the AdventureWorks sales order tables are large, the sample reads only orders placed by a certain account number and bulk copies those orders and details to the destination tables. The method is used only after both bulk copy operations are complete. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", + connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderHeader"; + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up a different destination and + // map columns. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Enables or disables a object to stream data from an object + + + if a object can stream data from an object; otherwise, false. The default is . + + + + When is , reads from an object using , optimizing memory usage by using the streaming capabilities. Streaming is only applicable to max data types (i.e. VARBINARY(MAX), VARCHAR(MAX), NVARCHAR(MAX), and XML). When is set to , the class loads all the data returned by the object into memory before sending it to the server. + + + The main advantage of enabling streaming is reducing memory usage during bulk copy of max data types. + + + + + + Returns a collection of items. Column mappings define the relationships between columns in the data source and columns in the destination. + + + A collection of column mappings. By default, it is an empty collection. + + + + If the data source and the destination table have the same number of columns, and the ordinal position of each source column within the data source matches the ordinal position of the corresponding destination column, the collection is unnecessary. However, if the column counts differ, or the ordinal positions are not consistent, you must use to make sure that data is copied into the correct columns. + + + During the execution of a bulk copy operation, this collection can be accessed, but it cannot be changed. Any attempt to change it will throw an . + + + + + + Returns a collection of items. Column order hints describe the sort order of columns in the clustered index of the destination table. + + + A collection of column order hints. By default, it is an empty collection. + + + SqlBulkCopy's performance is improved if the data being imported is sorted according to the clustered index on the table, if any. If the data is sorted in an order that differs from the order of a clustered index key or if there is no clustered index on the table, the order hint is ignored. + + + + + Name of the destination table on the server. + + + The string value of the property, or null if none as been supplied. + + + + If has not been set when is called, an is thrown. If is modified while a operation is running, the change does not affect the current operation. The new value is used the next time a method is called. + + + is a three-part name (<database>.<owningschema>.<name>). You can qualify the table name with its database and owning schema if you choose. However, if the table name uses an underscore ("_") or any other special characters, you must escape the name using surrounding brackets as in ([<database>.<owningschema>.<name_01>]). + + + You can bulk-copy data to a temporary table by using a value such as tempdb..#table or tempdb.<owner>.#table for the property. + + + + + The following console application demonstrates how to bulk load data using a connection that is already open. The destination table is a table in the AdventureWorks database. + + + In this example, the connection is first used to read data from a SQL Server table to a instance. The source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Open the destination connection. In the real world you would + // not use SqlBulkCopy to move data from one table to the other + // in the same database. This is for demonstration purposes only. + using (SqlConnection destinationConnection = new SqlConnection(connectionString)) + { + destinationConnection.Open(); + + // Set up the bulk copy object. + // Note that the column positions in the source + // data reader match the column positions in + // the destination table so there is no need to + // map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Defines the number of rows to be processed before generating a notification event. + + + The integer value of the property, or zero if the property has not been set. + + + + This property is designed for user interface components that illustrate the progress of a bulk copy operation. It indicates the number of rows to be processed before generating a notification event. The property can be set at any time, even while a bulk copy operation is underway. Changes made during a bulk copy operation take effect after the next notification. The new setting applies to all subsequent operations on the same instance. + + + If is set to a number less than zero, an is thrown. + + + + + The following console application demonstrates how to bulk load data using a connection that is already open. The property is set so that the event handler is called after every 50 rows copied to the table. + + + In this example, the connection is first used to read data from a SQL Server table to a instance. Then a second connection is opened to bulk copy the data. Note that the source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("NotifyAfter Sample"); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + // Set up the event handler to notify after 50 rows. + bulkCopy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied); + bulkCopy.NotifyAfter = 50; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) + { + Console.WriteLine("Copied {0} so far...", e.RowsCopied); + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Occurs every time that the number of rows specified by the property have been processed. + + + + Note that the settings of and are independent. Receipt of a event does not imply that any rows have been sent to the server or committed. + + + You cannot call or from this event. Doing this will cause an being thrown, and the object state will not change. If the user wants to cancel the operation from the event, the property of the can be used. (See Transaction and Bulk Copy Operations for examples that use the property.) + + + No action, such as transaction activity, is supported in the connection during the execution of the bulk copy operation, and it is recommended that you not use the same connection used during the event. However, you can open a different connection. + + + + + The following console application demonstrates how to bulk load data using a connection that is already open. The property is set so that the event handler is called after every 50 rows copied to the table. + + + In this example, the connection is first used to read data from a SQL Server table to a instance. Note that the source data does not have to be located on SQL Server; you can use any data source that can be read to an or loaded to a . + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("NotifyAfter Sample"); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + // Set up the event handler to notify after 50 rows. + bulkCopy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied); + bulkCopy.NotifyAfter = 50; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) + { + Console.WriteLine("Copied {0} so far...", e.RowsCopied); + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The number of rows processed in the ongoing bulk copy operation. + + + The integer value of the property. + + + + This value is incremented during the event and does not imply that this number of rows has been sent to the server or committed. + + + This value can be accessed during or after the execution of a bulk copy operation. + + + This value will wrap around and become negative if the number of rows exceeds int.MaxValue. Consider using the property. + + + The number of rows processed in the ongoing bulk copy operation. @@ -523,872 +1250,915 @@ This value will wrap around and become negative if the number of rows exceeds in The long value of the property. - - event and does not imply that this number of rows has been sent to the server or committed. - -This value can be accessed during or after the execution of a bulk copy operation. -]]> - + + This value is incremented during the event and does not imply that this number of rows has been sent to the server or committed. + + + This value can be accessed during or after the execution of a bulk copy operation. + - - - Releases all resources used by the current instance of the - - class. - - - . The `Dispose` method leaves the in an unusable state. -After calling `Dispose`, you must release all references to the so the garbage collector can reclaim the memory that the - was occupying. - -For more information, see [Cleaning Up Unmanaged Resources](/dotnet/standard/garbage-collection/unmanaged) and -[Implementing a Dispose Method](/dotnet/standard/garbage-collection/implementing-dispose). - -> [!NOTE] -> Always call `Dispose` before you release your last reference to the . Otherwise, the resources it is using will not be freed until the garbage collector calls -the object's `Finalize` method. -]]> - - - - - A - - whose rows will be copied to the destination table. - - - Copies all rows from the supplied - - array to a destination table specified by the - - property of the - - object. - - - To be added. - - - A - - did not specify a valid destination column name. - - - - - A - - whose rows will be copied to the destination table. - - - Copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - - or a similar call, -so the next available row is the first row. To process multiple results, call on the data reader and call - again. - -Note that using modifies the state of the reader. The method will call -until it returns false, the operation is aborted, or an error occurs. This means that the data reader will be in a different state, probably at the end of the result set, -when the operation is complete. - -While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. - -The collection maps from the data reader columns to the destination database table. - -## Examples -The following console application demonstrates how to bulk load data from a . The destination table is a table in the **AdventureWorks** database. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided -to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ConnectionString#1](~/../sqlclient/doc/samples/SqlBulkCopy_ConnectionString.cs#1)] -]]> - - - A - - did not specify a valid destination column name. - - - - - A - - whose rows will be copied to the destination table. - - - Copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - - are copied to the destination table except those that have been deleted. - -While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. - -The collection maps from the columns to the destination database table. - -## Examples -The following Console application demonstrates how to bulk load data from a . The destination table is a table in the **AdventureWorks** database. - -In this example, a is created at run time and is the source of the `SqlBulkCopy` operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.DataTable#1](~/../sqlclient/doc/samples/SqlBulkCopy_DataTable.cs#1)] -]]> - - - A - - did not specify a valid destination column name. - - - Performing Bulk Copy Operations - - - Overview of the SqlClient driver - - - - - A - - whose rows will be copied to the destination table. - - - A value from the - - enumeration. Only rows matching the row state are copied to the destination. - - - Copies only rows that match the supplied row state in the supplied - - to a destination table specified by the - - property of the - - object. - - - that are in the states indicated in the `rowState` argument and have not been deleted are copied to the destination table. - -> [!NOTE] -> If is specified, any , , and -rows will also be copied to the server. No exception will be raised. - -While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. - -The collection maps from the columns to the destination database table. - - -## Examples -The following Console application demonstrates how to bulk load only the rows in a that match a specified state. In this case, only unchanged rows are added. The destination table is a table in the **AdventureWorks** database. - -In this example, a is created at run time and three rows are added to it. Before the method is executed, one of the rows is edited. -The method is called with a `DataRowState.Unchanged` `rowState` argument, so only the two unchanged rows are bulk copied to the destination. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.DataRowState#1](~/../sqlclient/doc/samples/SqlBulkCopy_DataRowState.cs#1)] -]]> - - - A - - did not specify a valid destination column name. - - - - An array of objects that will be copied to the destination table. - Copies all rows from the supplied array to a destination table specified by the property of the object. - - is busy serving it, and no other operations can be performed on the connection. - -The collection maps from the columns to the destination database table. - -## Examples -The following console application demonstrates how to bulk load data from a array. The destination table is a table in the **AdventureWorks** database. - -In this example, a is created at run time. A single row is selected from the to copy to the destination table. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.RowArray#1](~/../sqlclient/doc/samples/SqlBulkCopy_RowArray.cs#1)] - -]]> - - - A - - did not specify a valid destination column name. - - - - - An array of - - objects that will be copied to the destination table. - - - The asynchronous version of - , - which copies all rows from the supplied - - array to a destination table specified by the - - property of the - - object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - An array of - - objects that will be copied to the destination table. - - - The cancellation instruction. A - - value in this parameter makes this method equivalent to - . - - - The asynchronous version of - , - which copies all rows from the supplied - - array to a destination table specified by the - - property of the - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - The asynchronous version of - , - which copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - The - - was closed before the completed - - returned. - - The - 's associated connection was closed before the completed - - returned. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - The cancellation instruction. A - - value in this parameter makes this method equivalent to - . - - - The asynchronous version of - , - which copies all rows from the supplied - - array to a destination table specified by the - - property of the - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - To be added. - - - - - A - - whose rows will be copied to the destination table. - - - The asynchronous version of - , - which copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same - instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - The - - was closed before the completed - - returned. - - The - 's associated connection was closed before the completed - - returned. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - The cancellation instruction. A - - value in this parameter makes this method equivalent to - . - - - The asynchronous version of - , - which copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - The - - was closed before the completed - - returned. - - The - 's associated connection was closed before the completed - - returned. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - The asynchronous version of - , - which copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - The cancellation instruction. A - - value in this parameter makes this method equivalent to - . - - - The asynchronous version of - , - which copies all rows in the supplied - - to a destination table specified by the - - property of the - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - A value from the - - enumeration. Only rows matching the row state are copied to the destination. - - - The asynchronous version of - , - which copies only rows that match the supplied row state in the supplied - to a destination table specified by the - property of the object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - - - A - - whose rows will be copied to the destination table. - - - A value from the - - enumeration. Only rows matching the row state are copied to the destination. - - - The cancellation instruction. A - - value in this parameter makes this method equivalent to - . - - - The asynchronous version of - , - which copies only rows that match the supplied row state in the supplied - - to a destination table specified by the - - property of the - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - Calling - - multiple times for the same instance before task completion. - - Calling - - and - - for the same instance before task completion. - - The connection drops or is closed during - - execution. - - Returned in the task object, the - - object was closed during the method execution. - - Returned in the task object, there was a connection pool timeout. - - Returned in the task object, the - - object is closed before method execution. - - A - - did not specify a valid destination column name. - - - Returned in the task object, any error returned by SQL Server that occurred while opening the connection. - - - + + + Releases all resources used by the current instance of the class. + + + + Call Dispose when you are finished using the . The Dispose method leaves the in an unusable state. After calling Dispose, you must release all references to the so the garbage collector can reclaim the memory that the was occupying. + + + For more information, see Cleaning Up Unmanaged Resources and Implementing a Dispose Method. + + + Always call Dispose before you release your last reference to the . Otherwise, the resources it is using will not be freed until the garbage collector calls the object's Finalize method. + + + + + + A whose rows will be copied to the destination table. + + + Copies all rows from the supplied array to a destination table specified by the property of the object. + + + A did not specify a valid destination column name. + + + + + A whose rows will be copied to the destination table. + + + Copies all rows in the supplied to a destination table specified by the property of the object. + + + + The copy operation starts at the next available row in the reader. Most of the time, the reader was just returned by or a similar call, so the next available row is the first row. To process multiple results, call on the data reader and call again. + + + Note that using modifies the state of the reader. The method will call until it returns false, the operation is aborted, or an error occurs. This means that the data reader will be in a different state, probably at the end of the result set, when the operation is complete. + + + While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. + + + The collection maps from the data reader columns to the destination database table. + + + + + The following console application demonstrates how to bulk load data from a . The destination table is a table in the AdventureWorks database. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Set up the bulk copy object using a connection string. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + A did not specify a valid destination column name. + + + + + A whose rows will be copied to the destination table. + + + Copies all rows in the supplied to a destination table specified by the property of the object. + + + + All rows in the are copied to the destination table except those that have been deleted. + + + While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. + + + The collection maps from the columns to the destination database table. + + + + + The following Console application demonstrates how to bulk load data from a . The destination table is a table in the AdventureWorks database. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + In this example, a is created at run time and is the source of the SqlBulkCopy operation. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + connection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Create a table with some rows. + DataTable newProducts = MakeTable(); + + // Create the SqlBulkCopy object. + // Note that the column positions in the source DataTable + // match the column positions in the destination table so + // there is no need to map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(newProducts); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static DataTable MakeTable() + { + // Create a new DataTable named NewProducts. + DataTable newProducts = new DataTable("NewProducts"); + + // Add three column objects to the table. + DataColumn productID = new DataColumn(); + productID.DataType = System.Type.GetType("System.Int32"); + productID.ColumnName = "ProductID"; + productID.AutoIncrement = true; + newProducts.Columns.Add(productID); + + DataColumn productName = new DataColumn(); + productName.DataType = System.Type.GetType("System.String"); + productName.ColumnName = "Name"; + newProducts.Columns.Add(productName); + + DataColumn productNumber = new DataColumn(); + productNumber.DataType = System.Type.GetType("System.String"); + productNumber.ColumnName = "ProductNumber"; + newProducts.Columns.Add(productNumber); + + // Create an array for DataColumn objects. + DataColumn[] keys = new DataColumn[1]; + keys[0] = productID; + newProducts.PrimaryKey = keys; + + // Add some new rows to the collection. + DataRow row = newProducts.NewRow(); + row["Name"] = "CC-101-WH"; + row["ProductNumber"] = "Cyclocomputer - White"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-BK"; + row["ProductNumber"] = "Cyclocomputer - Black"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-ST"; + row["ProductNumber"] = "Cyclocomputer - Stainless"; + newProducts.Rows.Add(row); + newProducts.AcceptChanges(); + + // Return the new DataTable. + return newProducts; + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + A did not specify a valid destination column name. + + + Performing Bulk Copy Operations + + + Overview of the SqlClient driver + + + + + A whose rows will be copied to the destination table. + + + A value from the enumeration. Only rows matching the row state are copied to the destination. + + + Copies only rows that match the supplied row state in the supplied to a destination table specified by the property of the object. + + + + Only rows in the that are in the states indicated in the argument and have not been deleted are copied to the destination table. + + + If is specified, any , , and rows will also be copied to the server. No exception will be raised. + + + While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. + + + The collection maps from the columns to the destination database table. + + + + + The following Console application demonstrates how to bulk load only the rows in a that match a specified state. In this case, only unchanged rows are added. The destination table is a table in the AdventureWorks database. + + + In this example, a is created at run time and three rows are added to it. Before the method is executed, one of the rows is edited. The method is called with a argument, so only the two unchanged rows are bulk copied to the destination. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + connection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Create a table with some rows. + DataTable newProducts = MakeTable(); + + // Make a change to one of the rows in the DataTable. + DataRow row = newProducts.Rows[0]; + row.BeginEdit(); + row["Name"] = "AAA"; + row.EndEdit(); + + // Create the SqlBulkCopy object. + // Note that the column positions in the source DataTable + // match the column positions in the destination table so + // there is no need to map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write unchanged rows from the source to the destination. + bulkCopy.WriteToServer(newProducts, DataRowState.Unchanged); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static DataTable MakeTable() + { + // Create a new DataTable named NewProducts. + DataTable newProducts = new DataTable("NewProducts"); + + // Add three column objects to the table. + DataColumn productID = new DataColumn(); + productID.DataType = System.Type.GetType("System.Int32"); + productID.ColumnName = "ProductID"; + productID.AutoIncrement = true; + newProducts.Columns.Add(productID); + + DataColumn productName = new DataColumn(); + productName.DataType = System.Type.GetType("System.String"); + productName.ColumnName = "Name"; + newProducts.Columns.Add(productName); + + DataColumn productNumber = new DataColumn(); + productNumber.DataType = System.Type.GetType("System.String"); + productNumber.ColumnName = "ProductNumber"; + newProducts.Columns.Add(productNumber); + + // Create an array for DataColumn objects. + DataColumn[] keys = new DataColumn[1]; + keys[0] = productID; + newProducts.PrimaryKey = keys; + + // Add some new rows to the collection. + DataRow row = newProducts.NewRow(); + row["Name"] = "CC-101-WH"; + row["ProductNumber"] = "Cyclocomputer - White"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-BK"; + row["ProductNumber"] = "Cyclocomputer - Black"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-ST"; + row["ProductNumber"] = "Cyclocomputer - Stainless"; + newProducts.Rows.Add(row); + newProducts.AcceptChanges(); + + // Return the new DataTable. + return newProducts; + } + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + A did not specify a valid destination column name. + + + + + An array of objects that will be copied to the destination table. + + + Copies all rows from the supplied array to a destination table specified by the property of the object. + + + + While the bulk copy operation is in progress, the associated destination is busy serving it, and no other operations can be performed on the connection. + + + The collection maps from the columns to the destination database table. + + + + + The following console application demonstrates how to bulk load data from a array. The destination table is a table in the AdventureWorks database. + + + In this example, a is created at run time. A single row is selected from the to copy to the destination table. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", + connection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Create a table with some rows. + DataTable newProducts = MakeTable(); + + // Get a reference to a single row in the table. + DataRow[] rowArray = newProducts.Select("Name='CC-101-BK'"); + + // Create the SqlBulkCopy object. + // Note that the column positions in the source DataTable + // match the column positions in the destination table so + // there is no need to map columns. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write the array of rows to the destination. + bulkCopy.WriteToServer(rowArray); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static DataTable MakeTable() + { + // Create a new DataTable named NewProducts. + DataTable newProducts = new DataTable("NewProducts"); + + // Add three column objects to the table. + DataColumn productID = new DataColumn(); + productID.DataType = System.Type.GetType("System.Int32"); + productID.ColumnName = "ProductID"; + productID.AutoIncrement = true; + newProducts.Columns.Add(productID); + + DataColumn productName = new DataColumn(); + productName.DataType = System.Type.GetType("System.String"); + productName.ColumnName = "Name"; + newProducts.Columns.Add(productName); + + DataColumn productNumber = new DataColumn(); + productNumber.DataType = System.Type.GetType("System.String"); + productNumber.ColumnName = "ProductNumber"; + newProducts.Columns.Add(productNumber); + + // Create an array for DataColumn objects. + DataColumn[] keys = new DataColumn[1]; + keys[0] = productID; + newProducts.PrimaryKey = keys; + + // Add some new rows to the collection. + DataRow row = newProducts.NewRow(); + row["Name"] = "CC-101-WH"; + row["ProductNumber"] = "Cyclocomputer - White"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-BK"; + row["ProductNumber"] = "Cyclocomputer - Black"; + + newProducts.Rows.Add(row); + row = newProducts.NewRow(); + row["Name"] = "CC-101-ST"; + row["ProductNumber"] = "Cyclocomputer - Stainless"; + newProducts.Rows.Add(row); + newProducts.AcceptChanges(); + + // Return the new DataTable. + return newProducts; + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + A did not specify a valid destination column name. + + + + + An array of objects that will be copied to the destination table. + + + The asynchronous version of , + which copies all rows from the supplied array to a destination table specified by the property of the object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + An array of objects that will be copied to the destination table. + + + The cancellation instruction. A value in this parameter makes this method equivalent to . + + + The asynchronous version of , + which copies all rows from the supplied array to a destination table specified by the property of the object. + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + The asynchronous version of , + which copies all rows in the supplied to a destination table specified by the property of the object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + The was closed before the completed returned. + The 's associated connection was closed before the completed returned. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + The cancellation instruction. A value in this parameter makes this method equivalent to . + + + The asynchronous version of , + which copies all rows from the supplied array to a destination table specified by the property of the object. + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + + + A whose rows will be copied to the destination table. + + + The asynchronous version of , + which copies all rows in the supplied to a destination table specified by the property of the object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + The was closed before the completed returned. + The 's associated connection was closed before the completed returned. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + The cancellation instruction. A value in this parameter makes this method equivalent to . + + + The asynchronous version of , + which copies all rows in the supplied to a destination table specified by the property of the object. + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + The was closed before the completed returned. + The 's associated connection was closed before the completed returned. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + The asynchronous version of , + which copies all rows in the supplied to a destination table specified by the property of the object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + The cancellation instruction. A value in this parameter makes this method equivalent to . + + + The asynchronous version of , + which copies all rows in the supplied to a destination table specified by the property of the object. + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + A value from the enumeration. Only rows matching the row state are copied to the destination. + + + The asynchronous version of , + which copies only rows that match the supplied row state in the supplied to a destination table specified by the property of the object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + + + A whose rows will be copied to the destination table. + + + A value from the enumeration. Only rows matching the row state are copied to the destination. + + + The cancellation instruction. A value in this parameter makes this method equivalent to . + + + The asynchronous version of , + which copies only rows that match the supplied row state in the supplied to a destination table specified by the property of the object. + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + Calling multiple times for the same instance before task completion. + Calling and for the same instance before task completion. + The connection drops or is closed during execution. + Returned in the task object, the object was closed during the method execution. + Returned in the task object, there was a connection pool timeout. + Returned in the task object, the object is closed before method execution. + A did not specify a valid destination column name. + + + + Returned in the task object, any error returned by SQL Server that occurred while opening the connection. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMapping.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMapping.xml index f8d258ff32..edef794199 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMapping.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMapping.xml @@ -1,294 +1,1142 @@ - - - - - Defines the mapping between a column in a - - instance's data source and a column in the instance's destination table. - - - collection is empty - the columns are mapped implicitly based on ordinal position. -For this to work, source and target schemas must match. If they do not, an will be thrown. - -If the collection is not empty, not every column present in the data source has to be specified. Those not mapped by the collection -are ignored. - -You can refer to source and target columns by either name or ordinal. You can also mix by-name and by-ordinal column references in the same mappings collection. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. Although the number of columns in the -destination matches the number of columns in the source, and each destination column is in the same ordinal position as its corresponding source column, the column names do not match. - objects are used to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMapping#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMapping.cs#1)] -]]> - - - - - Parameterless constructor that initializes a new - - object. - - - -property or the property, and define the destination for the mapping using the - property or the property. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. - objects are used to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMapping#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMapping.cs#1)] -]]> - - - - - The ordinal position of the source column within the data source. - - - The ordinal position of the destination column within the destination table. - - - Creates a new column mapping, using column ordinals to refer to source and destination columns. - - - objects are used to create a column map for the bulk copy based on the ordinal positions of the columns. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier -and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingOrdinal#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingOrdinal.cs#1)] -]]> - - - - - The ordinal position of the source column within the data source. - - - The name of the destination column within the destination table. - - - Creates a new column mapping, using a column ordinal to refer to the source column and a column name for the target column. - - - objects are used to create a -column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and -faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingOrdinalName#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingOrdinalName.cs#1)] -]]> - - - - - The name of the source column within the data source. - - - The ordinal position of the destination column within the destination table. - - - Creates a new column mapping, using a column name to refer to the source column and a column ordinal for the target column. - - - objects are used to create -a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). This code is -provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to -use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingNameOrdinal#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingNameOrdinal.cs#1)] -]]> - - - - - The name of the source column within the data source. - - - The name of the destination column within the destination table. - - - Creates a new column mapping, using column names to refer to source and destination columns. - - - objects are used to create a -column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMapping#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMapping.cs#1)] -]]> - - - - - Name of the column being mapped in the destination database table. - - - The string value of the - - property. - - - and properties are mutually exclusive. -The last value set takes precedence. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. - objects are used to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingDestinationColumn#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingDestinationColumn.cs#1)] -]]> - - - - - Ordinal value of the destination column within the destination table. - - - The integer value of the - - property, or -1 if the property has not been set. - - - and properties are mutually exclusive. -The last value set takes precedence. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. Although the number of columns in the -destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a -column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingDestinationOrdinal#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingDestinationOrdinal.cs#1)] -]]> - - - - - Name of the column being mapped in the data source. - - - The string value of the - - property. - - - and properties are mutually exclusive. -The last value set takes precedence. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. Although the number of columns in the -destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a -column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingDestinationColumn#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingDestinationColumn.cs#1)] -]]> - - - - - The ordinal position of the source column within the data source. - - - The integer value of the - - property. - - - and properties are mutually exclusive. -The last value set takes precedence. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. Although the number of columns in the destination -matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the -bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingDestinationOrdinal#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingDestinationOrdinal.cs#1)] -]]> - - - + + + + + Defines the mapping between a column in a instance's data source and a column in the instance's destination table. + + + + Column mappings define the mapping between data source and the target table. + + + If mappings are not defined - that is, the collection is empty - the columns are mapped implicitly based on ordinal position. For this to work, source and target schemas must match. If they do not, an will be thrown. + + + If the collection is not empty, not every column present in the data source has to be specified. Those not mapped by the collection are ignored. + + + You can refer to source and target columns by either name or ordinal. You can also mix by-name and by-ordinal column references in the same mappings collection. + + + + + The following example bulk copies data from a source table in the AdventureWorks + sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, and each destination column is in the same ordinal position as its corresponding source column, the column names do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for usingSqlBulkCopyonly. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by name. + SqlBulkCopyColumnMapping mapID = + new SqlBulkCopyColumnMapping("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = + new SqlBulkCopyColumnMapping("Name", "ProdName"); + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = + new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum"); + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Parameterless constructor that initializes a new object. + + + If you use this constructor, you must then define the source for the mapping using the property or the property, and define the destination for the mapping using the property or the property. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by name. + SqlBulkCopyColumnMapping mapID = + new SqlBulkCopyColumnMapping("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = + new SqlBulkCopyColumnMapping("Name", "ProdName"); + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = + new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum"); + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The ordinal position of the source column within the data source. + + + The ordinal position of the destination column within the destination table. + + + Creates a new column mapping, using column ordinals to refer to source and destination columns. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy based on the ordinal positions of the columns. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = + new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = + new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by ordinal. + SqlBulkCopyColumnMapping columnMapID = + new SqlBulkCopyColumnMapping(0, 0); + bulkCopy.ColumnMappings.Add(columnMapID); + + SqlBulkCopyColumnMapping columnMapName = + new SqlBulkCopyColumnMapping(1, 2); + bulkCopy.ColumnMappings.Add(columnMapName); + + SqlBulkCopyColumnMapping columnMapNumber = + new SqlBulkCopyColumnMapping(2, 1); + bulkCopy.ColumnMappings.Add(columnMapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The ordinal position of the source column within the data source. + + + The name of the destination column within the destination table. + + + Creates a new column mapping, using a column ordinal to refer to the source column and a column name for the target column. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by ordinal and name. + SqlBulkCopyColumnMapping columnMapID = + new SqlBulkCopyColumnMapping(0, "ProdID"); + bulkCopy.ColumnMappings.Add(columnMapID); + + SqlBulkCopyColumnMapping columnMapName = + new SqlBulkCopyColumnMapping(1, "ProdName"); + bulkCopy.ColumnMappings.Add(columnMapName); + + SqlBulkCopyColumnMapping columnMapNumber = + new SqlBulkCopyColumnMapping(2, "ProdNum"); + bulkCopy.ColumnMappings.Add(columnMapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The name of the source column within the data source. + + + The ordinal position of the destination column within the destination table. + + + Creates a new column mapping, using a column name to refer to the source column and a column ordinal for the target column. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by name and ordinal. + SqlBulkCopyColumnMapping columnMapID = + new SqlBulkCopyColumnMapping("ProductID", 0); + bulkCopy.ColumnMappings.Add(columnMapID); + + SqlBulkCopyColumnMapping columnMapName = + new SqlBulkCopyColumnMapping("Name", 2); + bulkCopy.ColumnMappings.Add(columnMapName); + + SqlBulkCopyColumnMapping columnMapNumber = + new SqlBulkCopyColumnMapping("ProductNumber", 1); + bulkCopy.ColumnMappings.Add(columnMapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The name of the source column within the data source. + + + The name of the destination column within the destination table. + + + Creates a new column mapping, using column names to refer to source and destination columns. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, ProductNumber FROM Production.Product;", + sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by name. + SqlBulkCopyColumnMapping mapID = + new SqlBulkCopyColumnMapping("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = + new SqlBulkCopyColumnMapping("Name", "ProdName"); + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = + new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum"); + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32(commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Name of the column being mapped in the destination database table. + + + The string value of the property. + + + The and properties are mutually exclusive. The last value set takes precedence. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings source and destination. + SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(); + mapID.SourceColumn = "ProductID"; + mapID.DestinationColumn = "ProdID"; + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = new SqlBulkCopyColumnMapping(); + mapName.SourceColumn = "Name"; + mapName.DestinationColumn = "ProdName"; + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = new SqlBulkCopyColumnMapping(); + mapNumber.SourceColumn = "ProductNumber"; + mapNumber.DestinationColumn = "ProdNum"; + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Ordinal value of the destination column within the destination table. + + + The integer value of the property, or -1 if the property has not been set. + + + The and properties are mutually exclusive. The last value set takes precedence. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings source and destination. + SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(); + mapID.SourceOrdinal = 0; + mapID.DestinationOrdinal = 0; + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = new SqlBulkCopyColumnMapping(); + mapName.SourceOrdinal = 1; + mapName.DestinationOrdinal = 2; + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = new SqlBulkCopyColumnMapping(); + mapNumber.SourceOrdinal = 2; + mapNumber.DestinationOrdinal = 1; + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Name of the column being mapped in the data source. + + + The string value of the property. + + + The and properties are mutually exclusive. The last value set takes precedence. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings source and destination. + SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(); + mapID.SourceColumn = "ProductID"; + mapID.DestinationColumn = "ProdID"; + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = new SqlBulkCopyColumnMapping(); + mapName.SourceColumn = "Name"; + mapName.DestinationColumn = "ProdName"; + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = new SqlBulkCopyColumnMapping(); + mapNumber.SourceColumn = "ProductNumber"; + mapNumber.DestinationColumn = "ProdNum"; + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The ordinal position of the source column within the data source. + + + The integer value of the property. + + + The and properties are mutually exclusive. The last value set takes precedence. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings source and destination. + SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(); + mapID.SourceOrdinal = 0; + mapID.DestinationOrdinal = 0; + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = new SqlBulkCopyColumnMapping(); + mapName.SourceOrdinal = 1; + mapName.DestinationOrdinal = 2; + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = new SqlBulkCopyColumnMapping(); + mapNumber.SourceOrdinal = 2; + mapNumber.DestinationOrdinal = 1; + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMappingCollection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMappingCollection.xml index 5c8ddd2ef3..3d867f3a24 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMappingCollection.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnMappingCollection.xml @@ -1,298 +1,1319 @@ - - - - Collection of objects that inherits from . - - collection is empty - the columns are mapped implicitly based on ordinal position. -For this to work, source and target schemas must match. If they do not, an is thrown. - -If the collection is not empty, not every column present in the data source has to be specified. Those not mapped by the collection are -ignored. - -You can refer to source and target columns by either name or ordinal. You can mix by-name and by-ordinal column references in the same mappings collection. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. - are added to the for the - object to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to -use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingCollection#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingCollection.cs#1)] - -]]> - - - - The object that describes the mapping to be added to the collection. - Adds the specified mapping to the . - A object. - - objects are used to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMapping#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMapping.cs)] - -]]> - - - - - The ordinal position of the source column within the data source. - The ordinal position of the destination column within the destination table. - Creates a new and adds it to the collection, using ordinals to specify both source and destination columns. - A column mapping. - - is thrown. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. - objects are used to create a column map for the bulk copy using the ordinal position of the source and destination columns. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingCollectionOrdinal#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingCollectionOrdinal.cs#1)] - -]]> - - - - The ordinal position of the source column within the data source. - The name of the destination column within the destination table. - Creates a new and adds it to the collection, using an ordinal for the source column and a string for the destination column. - A column mapping. - - is thrown. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. Although the number of columns in the -destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a -column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy_ColumnMappingIndexColName#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingIndexColName.cs#1)] - -]]> - - - - The name of the source column within the data source. - The ordinal position of the destination column within the destination table. - Creates a new and adds it to the collection, using a column name to describe the source column and an ordinal to specify the destination column. - A column mapping. - - is thrown. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. - objects are used to create a column map for the bulk copy. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingColNameIndex#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingColNameIndex.cs#1)] - -]]> - - - - The name of the source column within the data source. - The name of the destination column within the destination table. - Creates a new and adds it to the collection, using column names to specify both source and destination columns. - A column mapping. - - is thrown. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. The code creates a - object by specifying the column names. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingCollection#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingCollection.cs#1)] - -]]> - - - - Clears the contents of the collection. - - method is most commonly used when you use a single -instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must clear the - after the method and before processing the next bulk copy. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. -The method must be used after the first bulk copy is performed and before the next bulk copy's column mappings are defined. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingOrdersDetails#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingOrdersDetails.cs#1)] - -]]> - - - - A valid object. - Gets a value indicating whether a specified object exists in the collection. - - if the specified mapping exists in the collection; otherwise . - - - The one-dimensional array that is the destination of the elements copied from - . The array must have zero-based indexing. - The zero-based index in at which copying begins. - Copies the elements of the to an array of - items, starting at a particular index. - - - - The object for which to search. - Gets the index of the specified object. - The zero-based index of the column mapping, or -1 if the column mapping is not found in the collection. - To be added. - - - Integer value of the location within the at which to insert the new - . - - object to be inserted in the collection. - Insert a new at the index specified. - To be added. - - - The zero-based index of the to find. - Gets the object at the specified index. - A object. - To be added. - - - - object to be removed from the collection. - Removes the specified element from the . - - method is most commonly used when you use a single -instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must remove mappings that no longer apply after the - method is called and before defining mapping for the next bulk copy. You can clear the entire collection by using the - method, or remove mappings individually using the -method or the method. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. -Both bulk copies include a mapping for the **SalesOrderID**, so rather than clearing the entire collection between bulk copy operations, the example removes all mappings except for the **SalesOrderID** -mapping and then adds the appropriate mappings for the second bulk copy operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingRemove#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingRemove.cs#1)] - -]]> - - - - The zero-based index of the object to be removed from the collection. - Removes the mapping at the specified index from the collection. - - method is most commonly used when you use a single -instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must remove mappings that no longer apply after the - method is called and before defining mapping for the next bulk copy. You can clear the entire collection by using the - method, or remove mappings individually using the -method or the method. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. -Both bulk copies include a mapping for the **SalesOrderID**, so rather than clearing the entire collection between bulk copy operations, the example removes all mappings except for the -**SalesOrderID** mapping and then adds the appropriate mappings for the second bulk copy operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnMappingRemoveAt#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnMappingRemoveAt.cs#1)] - -]]> - - - - Gets a value indicating whether access to the is synchronized (thread safe). - `true` if access to the is synchronized (thread safe); otherwise, `false`. - - + + + + + Collection of objects that inherits from . + + + + Column mappings define the mapping between data source and the target table. + + + If mappings are not defined - that is, the collection is empty - the columns are mapped implicitly based on ordinal position. For this to work, source and target schemas must match. If they do not, an is thrown. + + + If the collection is not empty, not every column present in the data source has to be specified. Those not mapped by the collection are ignored. + + + You can refer to source and target columns by either name or ordinal. You can mix by-name and by-ordinal column references in the same mappings collection. + + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. are added to the for the object to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // The column order in the source doesn't match the order + // in the destination, so ColumnMappings must be defined. + bulkCopy.ColumnMappings.Add("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add("Name", "ProdName"); + bulkCopy.ColumnMappings.Add("ProductNumber", "ProdNum"); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The object that describes the mapping to be added to the collection. + + + Adds the specified mapping to the . + + + A object. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // Set up the column mappings by name. + SqlBulkCopyColumnMapping mapID = + new SqlBulkCopyColumnMapping("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add(mapID); + + SqlBulkCopyColumnMapping mapName = + new SqlBulkCopyColumnMapping("Name", "ProdName"); + bulkCopy.ColumnMappings.Add(mapName); + + SqlBulkCopyColumnMapping mapNumber = + new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum"); + bulkCopy.ColumnMappings.Add(mapNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The ordinal position of the source column within the data source. + + + The ordinal position of the destination column within the destination table. + + + Creates a new and adds it to the collection, using ordinals to specify both source and destination columns. + + + A column mapping. + + + Mappings in a collection must be uniform: either all integer/integer pairs, all string/string pairs, all integer/string pairs, or all string/integer pairs. If you try to add a mapping that is different from others already in the collection, an is thrown. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy using the ordinal position of the source and destination columns. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // The column order in the source doesn't match the order + // in the destination, so ColumnMappings must be defined. + bulkCopy.ColumnMappings.Add(0, 0); + bulkCopy.ColumnMappings.Add(1, 2); + bulkCopy.ColumnMappings.Add(2, 1); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The ordinal position of the source column within the data source. + + + The name of the destination column within the destination table. + + + Creates a new and adds it to the collection, using an ordinal for the source column and a string for the destination column. + + + A column mapping. + + + Mappings in a collection must be uniform: either all integer/integer pairs, all string/string pairs, all integer/string pairs, or all string/integer pairs. If you try to add a mapping that is different from others already in the collection, an is thrown. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // The column order in the source doesn't match the order + // in the destination, so ColumnMappings must be defined. + bulkCopy.ColumnMappings.Add(0, 0); + bulkCopy.ColumnMappings.Add(1, 2); + bulkCopy.ColumnMappings.Add(2, 1); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The name of the source column within the data source. + + + The ordinal position of the destination column within the destination table. + + + Creates a new and adds it to the collection, using a column name to describe the source column and an ordinal to specify the destination column. + + + A column mapping. + + + Mappings in a collection must be uniform: either all integer/integer pairs, all string/string pairs, all integer/string pairs, or all string/integer pairs. If you try to add a mapping that is different from others already in the collection, an is thrown. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. objects are used to create a column map for the bulk copy. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // The column order in the source doesn't match the order + // in the destination, so ColumnMappings must be defined. + bulkCopy.ColumnMappings.Add(0, 0); + bulkCopy.ColumnMappings.Add(1, 2); + bulkCopy.ColumnMappings.Add(2, 1); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The name of the source column within the data source. + + + The name of the destination column within the destination table. + + + Creates a new and adds it to the collection, using column names to specify both source and destination columns. + + + A column mapping. + + + Mappings in a collection must be uniform: either all integer/integer pairs, all string/string pairs, all integer/string pairs, or all string/integer pairs. If you try to add a mapping that is different from others already in the collection, an is thrown. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. Although the number of columns in the destination matches the number of columns in the source, the column names and ordinal positions do not match. The code creates a object by specifying the column names. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoDifferentColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoDifferentColumns"; + + // The column order in the source doesn't match the order + // in the destination, so ColumnMappings must be defined. + bulkCopy.ColumnMappings.Add("ProductID", "ProdID"); + bulkCopy.ColumnMappings.Add("Name", "ProdName"); + bulkCopy.ColumnMappings.Add("ProductNumber", "ProdNum"); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Clears the contents of the collection. + + + + The method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must clear the after the method and before processing the next bulk copy. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. The method must be used after the first bulk copy is performed and before the next bulk copy's column mappings are defined. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Clear the ColumnMappingCollection. + bulkCopy.ColumnMappings.Clear(); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + A valid object. + + + Gets a value indicating whether a specified object exists in the collection. + + if the specified mapping exists in the collection; otherwise . + + + + The one-dimensional array that is the destination of the elements copied from . The array must have zero-based indexing. + + + The zero-based index in at which copying begins. + + + Copies the elements of the to an array of items, starting at a particular index. + + + + + The object for which to search. + + + Gets the index of the specified object. + + + The zero-based index of the column mapping, or -1 if the column mapping is not found in the collection. + + + + + Integer value of the location within the at which to insert the new . + + object to be inserted in the collection. + + Insert a new at the index specified. + + + + + The zero-based index of the to find. + + + Gets the object at the specified index. + + + A object. + + + + object to be removed from the collection. + + Removes the specified element from the . + + + + The method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must remove mappings that no longer apply after the method is called and before defining mapping for the next bulk copy. You can clear the entire collection by using the method, or remove mappings individually using the method or the method. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. Both bulk copies include a mapping for the SalesOrderID, so rather than clearing the entire collection between bulk copy operations, the example removes all mappings except for the SalesOrderID mapping and then adds the appropriate mappings for the second bulk copy operation. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = + new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Clear the ColumnMappingCollection. + bulkCopy.ColumnMappings.Clear(); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The zero-based index of the object to be removed from the collection. + + + Removes the mapping at the specified index from the collection. + + + + The method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column mappings for one bulk copy operation, you must remove mappings that no longer apply after the method is called and before defining mapping for the next bulk copy. You can clear the entire collection by using the method, or remove mappings individually using the method or the method. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. Although not strictly necessary in this example (because the ordinal positions of the source and destination columns do match), the example defines column mappings for each bulk copy operation. Both bulk copies include a mapping for the SalesOrderID, so rather than clearing the entire collection between bulk copy operations, the example removes all mappings except for the SalesOrderID mapping and then adds the appropriate mappings for the second bulk copy operation. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Rather than clearing mappings that are not necessary + // for the next bulk copy operation, the unneeded mappings + // are removed with the RemoveAt method. + bulkCopy.ColumnMappings.RemoveAt(2); + bulkCopy.ColumnMappings.RemoveAt(1); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + bulkCopy.WriteToServer(readerDetail); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Gets a value indicating whether access to the is synchronized (thread safe). + + + if access to the is synchronized (thread safe); otherwise, . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHint.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHint.xml index d3e846546c..3b205e171d 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHint.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHint.xml @@ -1,131 +1,447 @@ - - - - - Defines the sort order for a column in a - - instance's destination table, according to the clustered index on the table. - - - collection is not empty, order hints can only be provided for valid -destination columns which have been mapped. - -If a of Unspecified is given, an will be thrown. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHint#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHint.cs#1)] -]]> - - - - - - The name of the destination column within the destination table. - - - The sort order of the corresponding destination column. - - - Creates a new column order hint for the specified destination column. - - - [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHint#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHint.cs#1)] -]]> - - - - - - Name of the destination column in the destination table for which the hint is being provided. - - - The string value of the - - property. - - - will be thrown if a null or empty string is given. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintColumn#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintColumn.cs#1)] -]]> - - The value is null or empty. - - - - - The sort order of the destination column in the destination table. - - - The SortOrder value of the - - property. - - - will be thrown if a of Unspecified is given. - -## Examples -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintSortOrder#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintSortOrder.cs#1)] -]]> - - The sort order cannot be unspecified for a column order hint. - - + + + + + Defines the sort order for a column in a instance's destination table, according to the clustered index on the table. + + + + Column order hints define the sort order of the column in the destination table. + + + SqlBulkCopy's performance is improved if the data being imported is sorted according to the clustered index on the table, if any. If the data is sorted in an order that differs from the order of a clustered index key or if there is no clustered index on the table, the order hint is ignored. + + + Order hints can be specified for any number of columns in the destination table. By default, the bulk insert operation assumes the data is unordered if no hints are provided. + + + The column names supplied must be valid column names in the destination table. The order in which hints can be specified is arbitrary. A single column name cannot be specified more than once. + + + If the collection is not empty, order hints can only be provided for valid destination columns which have been mapped. + + + If a of Unspecified is given, an will be thrown. + + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Setup an order hint for the ProductNumber column. + SqlBulkCopyColumnOrderHint hintNumber = + new SqlBulkCopyColumnOrderHint("ProductNumber", SortOrder.Ascending); + bulkCopy.ColumnOrderHints.Add(hintNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The name of the destination column within the destination table. + + + The sort order of the corresponding destination column. + + + Creates a new column order hint for the specified destination column. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Setup an order hint for the ProductNumber column. + SqlBulkCopyColumnOrderHint hintNumber = + new SqlBulkCopyColumnOrderHint("ProductNumber", SortOrder.Ascending); + bulkCopy.ColumnOrderHints.Add(hintNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Name of the destination column in the destination table for which the hint is being provided. + + + The string value of the property. + + + An will be thrown if a null or empty string is given. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Setup an order hint for the ProductNumber column. + SqlBulkCopyColumnOrderHint hintNumber = + new SqlBulkCopyColumnOrderHint("number", SortOrder.Ascending); + hintNumber.Column = "ProductNumber"; + bulkCopy.ColumnOrderHints.Add(hintNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + The value is null or empty. + + + + + The sort order of the destination column in the destination table. + + + The SortOrder value of the property. + + + An will be thrown if a of Unspecified is given. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Setup an order hint for the ProductNumber column. + SqlBulkCopyColumnOrderHint hintNumber = + new SqlBulkCopyColumnOrderHint("ProductNumber", SortOrder.Ascending); + hintNumber.SortOrder = SortOrder.Descending; + bulkCopy.ColumnOrderHints.Add(hintNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + The sort order cannot be unspecified for a column order hint. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHintCollection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHintCollection.xml index 1f6912efa5..528a6a6065 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHintCollection.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHintCollection.xml @@ -1,226 +1,1028 @@ - - - - Collection of objects that inherits from . - - + + + + Collection of objects that inherits from . + + + + Column order hints define the sort order of the column in the destination table. + + + SqlBulkCopy's performance is improved if the data being imported is sorted according to the clustered index on the table, if any. If the data is sorted in an order that differs from the order of a clustered index key or if there is no clustered index on the table, the order hint is ignored. + + + Order hints can be specified for any number of columns in the destination table. By default, the bulk insert operation assumes the data is unordered if no hints are provided. + + + The column names supplied must be valid column names in the destination table. The order in which hints can be specified is arbitrary. A single column name cannot be specified more than once. + + + If the collection is not empty, order hints can only be provided for valid destination columns which have been mapped. + + + If a of Unspecified is given, an will be thrown. + + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. s are added to the of the object to specify order hints for the bulk copy operation. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Specify the sort order for the ProductNumber column in + // the destination table. + bulkCopy.ColumnOrderHints.Add("ProductNumber", SortOrder.Ascending); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + The object that describes the order hint to be added to the collection. + + + Adds the specified order hint to the . + + + A object. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is used to define the sort order for the ProductNumber destination column. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Specify the sort order for the ProductNumber column in + // the destination table. + // Setup an order hint for the ProductNumber column. + SqlBulkCopyColumnOrderHint hintNumber = + new SqlBulkCopyColumnOrderHint("ProductNumber", SortOrder.Ascending); + bulkCopy.ColumnOrderHints.Add(hintNumber); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + The value is null. + + + + + The name of the destination column within the destination table. + + + The sort order of the corresponding destination column. + + + Creates a new and adds it to the collection. + + + A column column order hint. + + + + The following example bulk copies data from a source table in the AdventureWorks sample database to a destination table in the same database. A SqlBulkCopyColumnOrderHint object is added to the by providing the destination column name and its sort order. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = + commandSourceData.ExecuteReader(); + + // Set up the bulk copy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + // Specify the sort order for the ProductNumber column in + // the destination table. + bulkCopy.ColumnOrderHints.Add("ProductNumber", SortOrder.Ascending); + + // Write from the source to the destination. + try + { + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + Clears the contents of the collection. + + + + The method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the after the method and before processing the next bulk copy. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. The example defines a column order hint for each bulk copy operation. The method must be used after the first bulk copy is performed and before the next bulk copy's order hint is defined. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Add order hint for OrderDate column. + bulkCopy.ColumnOrderHints.Add("OrderDate", SortOrder.Ascending); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Clear the ColumnMappingCollection. + bulkCopy.ColumnMappings.Clear(); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + + // Clear the ColumnOrderHintCollection. + bulkCopy.ColumnOrderHints.Clear(); + + // Add order hint for SalesOrderID column. + bulkCopy.ColumnOrderHints.Add("SalesOrderID", SortOrder.Ascending); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + A valid object. + + + Gets a value indicating whether a specified object exists in the collection. + + + if the specified column order hint exists in the collection; otherwise . + + + + + The one-dimensional array that is the destination of the elements copied from . The array must have zero-based indexing. + + + The zero-based index in at which copying begins. + + + Copies the elements of the to an array of items, starting at a particular index. + + + + + The object for which to search. + + + Gets the index of the specified object. + + + The zero-based index of the column order hint, or -1 if the column order hint is not found in the collection. + + + + + Integer value of the location within the at which to insert the new . + + + object to be inserted in the collection. + + + Insert a new at the index specified. + + + The order in which column order hints can be added is arbitrary. + + + The index is less than zero or greater than the size of the collection. + + + A null column order hint cannot be added to the collection. + + + + + The zero-based index of the to find. + + + Gets the object at the specified index. + + + A object. + + + The index must be non-negative and less than the size of the collection. + + + + object to be removed from the collection. + + Removes the specified element from the . + + + + The Remove method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the after the method and before processing the next bulk copy. + + + You can clear the entire collection by using the method, or remove hints individually using the Remove method or the method. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. The example defines a column order hint for the OrderDate column in the first bulk copy operation. The hint is removed before the second bulk copy operation. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); -## Remarks -Column order hints define the sort order of the column in the destination table. - -SqlBulkCopy's performance is improved if the data being imported is sorted according to the clustered index on the table, if any. -If the data is sorted in an order that differs from the order of a clustered index key or if there is no clustered index on the table, the order hint is ignored. - -Order hints can be specified for any number of columns in the destination table. By default, the bulk insert operation assumes the data is -unordered if no hints are provided. - -The column names supplied must be valid column names in the destination table. The order in which hints can be specified is arbitrary. -A single column name cannot be specified more than once. - -If the collection is not empty, order hints can only be provided for valid -destination columns which have been mapped. - -If a of Unspecified is given, an will be thrown. - -## Examples - -The following example bulk copies data from a source table in the **AdventureWorks** sample database to a destination table in the same database. -s are added to the of the - object to specify order hints for the bulk copy operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to -use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollection#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollection.cs#1)] - -]]> - - - - - The object that describes the order hint to be added to the collection. - Adds the specified order hint to the . - A object. - - [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollectionAdd#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollectionAdd.cs)] - -]]> - - - The value is null. - - - - The name of the destination column within the destination table. - The sort order of the corresponding destination column. - Creates a new and adds it to the collection. - A column column order hint. - - by providing the destination column name and its sort order. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollectionAdd2#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollectionAdd2.cs#1)] - -]]> - - - - - Clears the contents of the collection. - - method is most commonly used when you use a single -instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the - after the method and before processing the next bulk copy. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -The example defines a column order hint for each bulk copy operation. -The method must be used after the first bulk copy is performed and before the next bulk copy's order hint is defined. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollectionClear#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollectionClear.cs#1)] - -]]> - - - - A valid object. - Gets a value indicating whether a specified object exists in the collection. - - if the specified column order hint exists in the collection; otherwise . - - - The one-dimensional array that is the destination of the elements copied from - . The array must have zero-based indexing. - The zero-based index in at which copying begins. - Copies the elements of the to an array of - items, starting at a particular index. - - - - The object for which to search. - Gets the index of the specified object. - The zero-based index of the column order hint, or -1 if the column order hint is not found in the collection. - To be added. - - - Integer value of the location within the at which to insert the new - . - - object to be inserted in the collection. - Insert a new at the index specified. - The order in which column order hints can be added is arbitrary. - The index is less than zero or greater than the size of the collection. - A null column order hint cannot be added to the collection. - - - The zero-based index of the to find. - Gets the object at the specified index. - A object. - To be added. - The index must be non-negative and less than the size of the collection. - - - - object to be removed from the collection. - Removes the specified element from the . - - -instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the - after the method and before processing the next bulk copy. - -You can clear the entire collection by using the - method, or remove hints individually using the Remove method or the method. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -The example defines a column order hint for the **OrderDate** column in the first bulk copy operation. The hint is removed before the second bulk copy operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollectionRemove#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollectionRemove.cs#1)] - -]]> - - The value is null. - - - The zero-based index of the object to be removed from the collection. - Removes the column order hint at the specified index from the collection. - - method is most commonly used when you use a single -instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the - after the method and before processing the next bulk copy. -You can clear the entire collection by using the - method, or remove hints individually using the -method or the method. - -Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate - for each operation. - -## Examples -The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. -The example defines a column order hint for the **OrderDate** column in the first bulk copy operation. The hint is removed before the second bulk copy operation. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a -Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.ColumnOrderHintCollectionRemoveAt#1](~/../sqlclient/doc/samples/SqlBulkCopy_ColumnOrderHintCollectionRemoveAt.cs#1)] - -]]> - - The index must be non-negative and less than the size of the collection. - - - Gets a value indicating whether access to the is synchronized (thread safe). - `true` if access to the is synchronized (thread safe); otherwise, `false`. - - + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Add the order hint for the OrderDate column. + SqlBulkCopyColumnOrderHint hintDate = + new SqlBulkCopyColumnOrderHint("OrderDate", SortOrder.Ascending); + bulkCopy.ColumnOrderHints.Add(hintDate); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Clear the ColumnMappingCollection. + bulkCopy.ColumnMappings.Clear(); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + + // Remove the order hint for the OrderDate column. + bulkCopy.ColumnOrderHints.Remove(hintDate); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + The value is null. + + + + + The zero-based index of the object to be removed from the collection. + + + Removes the column order hint at the specified index from the collection. + + + + The method is most commonly used when you use a single instance to process more than one bulk copy operation. If you create column order hints for one bulk copy operation, you must clear the after the method and before processing the next bulk copy. You can clear the entire collection by using the method, or remove hints individually using the method or the method. + + + Performing several bulk copies using the same instance will usually be more efficient from a performance point of view than using a separate for each operation. + + + + + The following example performs two bulk copy operations. The first operation copies sales order header information, and the second copies sales order details. The example defines a column order hint for the OrderDate column in the first bulk copy operation. The hint is removed before the second bulk copy operation. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + + // Open a connection to the AdventureWorks database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + // Empty the destination tables. + SqlCommand deleteHeader = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderHeader;", + connection); + deleteHeader.ExecuteNonQuery(); + SqlCommand deleteDetail = new SqlCommand( + "DELETE FROM dbo.BulkCopyDemoOrderDetail;", + connection); + deleteDetail.ExecuteNonQuery(); + + // Perform an initial count on the destination + // table with matching columns. + SqlCommand countRowHeader = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", + connection); + long countStartHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Header table = {0}", + countStartHeader); + + // Perform an initial count on the destination + // table with different column positions. + SqlCommand countRowDetail = new SqlCommand( + "SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", + connection); + long countStartDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine( + "Starting row count for Detail table = {0}", + countStartDetail); + + // Get data from the source table as a SqlDataReader. + // The Sales.SalesOrderHeader and Sales.SalesOrderDetail + // tables are quite large and could easily cause a timeout + // if all data from the tables is added to the destination. + // To keep the example simple and quick, a parameter is + // used to select only orders for a particular account + // as the source for the bulk insert. + SqlCommand headerData = new SqlCommand( + "SELECT [SalesOrderID], [OrderDate], " + + "[AccountNumber] FROM [Sales].[SalesOrderHeader] " + + "WHERE [AccountNumber] = @accountNumber;", + connection); + SqlParameter parameterAccount = new SqlParameter(); + parameterAccount.ParameterName = "@accountNumber"; + parameterAccount.SqlDbType = SqlDbType.NVarChar; + parameterAccount.Direction = ParameterDirection.Input; + parameterAccount.Value = "10-4020-000034"; + headerData.Parameters.Add(parameterAccount); + SqlDataReader readerHeader = headerData.ExecuteReader(); + + // Get the Detail data in a separate connection. + using (SqlConnection connection2 = new SqlConnection(connectionString)) + { + connection2.Open(); + SqlCommand sourceDetailData = new SqlCommand( + "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " + + "[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " + + "INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." + + "[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " + + "WHERE [AccountNumber] = @accountNumber;", connection2); + + SqlParameter accountDetail = new SqlParameter(); + accountDetail.ParameterName = "@accountNumber"; + accountDetail.SqlDbType = SqlDbType.NVarChar; + accountDetail.Direction = ParameterDirection.Input; + accountDetail.Value = "10-4020-000034"; + sourceDetailData.Parameters.Add(accountDetail); + SqlDataReader readerDetail = sourceDetailData.ExecuteReader(); + + // Create the SqlBulkCopy object. + using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoOrderHeader"; + + // Guarantee that columns are mapped correctly by + // defining the column mappings for the order. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("OrderDate", "OrderDate"); + bulkCopy.ColumnMappings.Add("AccountNumber", "AccountNumber"); + + // Add the order hint for the OrderDate column. + SqlBulkCopyColumnOrderHint hintDate = + new SqlBulkCopyColumnOrderHint("OrderDate", SortOrder.Ascending); + bulkCopy.ColumnOrderHints.Add(hintDate); + + // Write readerHeader to the destination. + try + { + bulkCopy.WriteToServer(readerHeader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerHeader.Close(); + } + + // Set up the order details destination. + bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"; + + // Clear the ColumnMappingCollection. + bulkCopy.ColumnMappings.Clear(); + + // Add order detail column mappings. + bulkCopy.ColumnMappings.Add("SalesOrderID", "SalesOrderID"); + bulkCopy.ColumnMappings.Add("SalesOrderDetailID", "SalesOrderDetailID"); + bulkCopy.ColumnMappings.Add("OrderQty", "OrderQty"); + bulkCopy.ColumnMappings.Add("ProductID", "ProductID"); + bulkCopy.ColumnMappings.Add("UnitPrice", "UnitPrice"); + + // Remove the order hint for the OrderDate column. + bulkCopy.ColumnOrderHints.RemoveAt(0); + + // Write readerDetail to the destination. + try + { + bulkCopy.WriteToServer(readerDetail); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + readerDetail.Close(); + } + } + + // Perform a final count on the destination + // tables to see how many rows were added. + long countEndHeader = System.Convert.ToInt32( + countRowHeader.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Header table.", + countEndHeader - countStartHeader); + long countEndDetail = System.Convert.ToInt32( + countRowDetail.ExecuteScalar()); + Console.WriteLine("{0} rows were added to the Detail table.", + countEndDetail - countStartDetail); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + The index must be non-negative and less than the size of the collection. + + + + + Gets a value indicating whether access to the is synchronized (thread safe). + + + if access to the is synchronized (thread safe); otherwise, . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyOptions.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyOptions.xml index 152fcbde42..50f149ee01 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyOptions.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyOptions.xml @@ -1,67 +1,154 @@ - - - - Bitwise flag that specifies one or more options to use with an instance of . - - enumeration when you construct a instance to change how the - methods for that instance behave. - -## Examples -The following console application demonstrates how to perform a bulk load that copies the value in the identity column of the source table to the corresponding column in the destination table, -instead of generating a new value for each row's identity column. - -To see how the option changes the way the bulk load works, run the sample with the **dbo.BulkCopyDemoMatchingColumns** table empty. All rows load from the source. -Next, run the sample again without emptying the table. An exception is thrown, and the code writes a message to the console window notifying you that rows were not added because of -primary key violations. - -> [!IMPORTANT] -> This sample will not run unless you have created the work tables as described in [Bulk Copy Example Setup](/sql/connect/ado-net/sql/bulk-copy-example-setup). -This code is provided to demonstrate the syntax for using **SqlBulkCopy** only. If the source and destination tables are in the same SQL Server instance, -it is easier and faster to use a Transact-SQL `INSERT … SELECT` statement to copy the data. - -[!code-csharp[SqlBulkCopy.KeepIdentity#1](~/../sqlclient/doc/samples/SqlBulkCopy_KeepIdentity.cs)] - -]]> - - - - - - - - - Check constraints while data is being inserted. By default, constraints are not checked. - - - Use the default values for all options. - - - When specified, cause the server to fire the insert triggers for the rows being inserted into the database. - - - Preserve source identity values. When not specified, identity values are assigned by the destination. - - - Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable. - - - Obtain a bulk update lock for the duration of the bulk copy operation. When not specified, row locks are used. - - - When specified, each batch of the bulk-copy operation will occur within a transaction. If you indicate this option and also provide a - object to the constructor, an occurs. - - - + + + + + Bitwise flag that specifies one or more options to use with an instance of . + + + + You can use the enumeration when you construct a instance to change how the methods for that instance behave. + + + + + The following console application demonstrates how to perform a bulk load that copies the value in the identity column of the source table to the corresponding column in the destination table, instead of generating a new value for each row's identity column. + + + To see how the option changes the way the bulk load works, run the sample with the dbo.BulkCopyDemoMatchingColumns table empty. All rows load from the source. Next, run the sample again without emptying the table. An exception is thrown, and the code writes a message to the console window notifying you that rows were not added because of primary key violations. + + + This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. + + + This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT … SELECT statement to copy the data. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + // Open a sourceConnection to the AdventureWorks database. + using (SqlConnection sourceConnection = new SqlConnection(connectionString)) + { + sourceConnection.Open(); + + // Perform an initial count on the destination table. + SqlCommand commandRowCount = new SqlCommand( + "SELECT COUNT(*) FROM " + + "dbo.BulkCopyDemoMatchingColumns;", + sourceConnection); + long countStart = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Starting row count = {0}", countStart); + + // Get data from the source table as a SqlDataReader. + SqlCommand commandSourceData = new SqlCommand( + "SELECT ProductID, Name, " + + "ProductNumber " + + "FROM Production.Product;", sourceConnection); + SqlDataReader reader = commandSourceData.ExecuteReader(); + + // Create the SqlBulkCopy object using a connection string + // and the KeepIdentity option. + // In the real world you would not use SqlBulkCopy to move + // data from one table to the other in the same database. + using (SqlBulkCopy bulkCopy = + new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)) + { + bulkCopy.DestinationTableName = + "dbo.BulkCopyDemoMatchingColumns"; + + try + { + // Write from the source to the destination. + bulkCopy.WriteToServer(reader); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Close the SqlDataReader. The SqlBulkCopy + // object is automatically closed at the end + // of the using block. + reader.Close(); + } + } + + // Perform a final count on the destination + // table to see how many rows were added. + long countEnd = System.Convert.ToInt32( + commandRowCount.ExecuteScalar()); + Console.WriteLine("Ending row count = {0}", countEnd); + Console.WriteLine("{0} rows were added.", countEnd - countStart); + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the sourceConnection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local); " + + " Integrated Security=true;" + + "Initial Catalog=AdventureWorks;"; + } + } + + + + + + + When specified, AllowEncryptedValueModifications enables bulk copying of encrypted data between tables or databases, without decrypting the data. Typically, an application would select data from encrypted columns from one table without decrypting the data (the app would connect to the database with the column encryption setting keyword set to disabled) and then would use this option to bulk insert the data, which is still encrypted. + + + Use caution when specifying AllowEncryptedValueModifications as this may lead to corrupting the database because the driver does not check if the data is indeed encrypted, or if it is correctly encrypted using the same encryption type, algorithm and key as the target column. + + + + + + Check constraints while data is being inserted. By default, constraints are not checked. + + + + + Use the default values for all options. + + + + + When specified, cause the server to fire the insert triggers for the rows being inserted into the database. + + + + + Preserve source identity values. When not specified, identity values are assigned by the destination. + + + + + Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable. + + + + + Obtain a bulk update lock for the duration of the bulk copy operation. When not specified, row locks are used. + + + + + When specified, each batch of the bulk-copy operation will occur within a transaction. If you indicate this option and also provide a object to the constructor, an occurs. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml new file mode 100644 index 0000000000..6306c624f4 --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml @@ -0,0 +1,525 @@ + + + + Class that provides strongly-typed collection of key-value pairs for SqlClient diagnostic objects. + + + Constructs a new instance of the class. + Guid that identifies the operation for correlation of events. + Operation being performed that caused the diagnostic event. + Timestamp of when the diagnostic event occurred. + + + + A guid value used to correlate before, after and error events. + + + + + The name of the operation. + + + + + The timestamp of the event. + + + + + Gets the element at the specified index in the read-only list. + + + The zero-based index of the element to get. + + + The element at the specified index in the read-only list. + + + + + + Gets the number of elements in the collection. + + + The number of elements in the collection. + + + + The number of common properties. + + + + Returns an enumerator that iterates through the collection. + + + An enumerator that can be used to iterate through the collection. + + + + Gets the number of properties in derived instances of that are not common to all diagnostic objects. + + + Gets a property from a derived instance of . + + + Attempts to retrieve the key-value pair diagnostic property. + Index to attempt to retrieve. + + If a key-value pair with the provided was found, this out parameter will be populated with the retrieved diagnostic property. If nothing was found, this parameter will be set to . + + + is returned if the property is found. is returned in all other situations. + + + + + + + Contains diagnostic information emitted before a command is executed. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + A nullable guid uniquely identifying the connection that the command is being executed on. + + + + + A nullable long uniquely identifying the transaction that the command enrolled in if it is enrolled in one. + + + + + The command object that is executing. + + + + + + + Contains diagnostic information emitted after a command is successfully executed. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + A nullable guid uniquely identifying the connection that the command is being executed on. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + The command object that is executing. + + + + + An IDictionary of statistic information about the event that has completed. + + + + + + + Contains diagnostic information emitted after a command execution fails with an exception. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + A nullable guid uniquely identifying the connection that the command is being executed on. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + The command object that is executing. + + + + + The exception object that caused the command execution to fail. + + + + + + + Contains diagnostic information emitted before a connection is opened. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that is being opened. + + + + + The version of the SqlClient library. + + + + + + + Contains diagnostic information emitted after a connection has been successfully opened. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that has been opened. + + + + + The version of the SqlClient library. + + + + + The unique guid assigned to the connection. + + + + + An IDictionary of statistic information about the event that has completed. + + + + + + + Contains diagnostic information emitted after a connection open fails with an exception. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that has been opened. + + + + + The version of the SqlClient library. + + + + + The unique guid assigned to the connection. + + + + + The exception object that caused the command execution to fail. + + + + + + + Contains diagnostic information emitted before a connection is closed. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that is being closed. + + + + + The unique guid assigned to the connection. + + + + + An IDictionary of statistic information about the connection. + + + + + + + Contains diagnostic information emitted after a connection has been successfully closed. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that has been closed. + + + + + The unique guid assigned to the connection. + + + + + An IDictionary of statistic information about the connection. + + + + + + + Contains diagnostic information emitted after a connection close fails with an exception. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that has been closed. + + + + + The unique guid assigned to the connection. + + + + + An IDictionary of statistic information about the connection. + + + + + The exception object that caused the command execution to fail. + + + + + + + Contains diagnostic information emitted before a transaction is opened. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + + + Contains diagnostic information emitted after a transaction is successfully committed. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + + + Contains diagnostic information emitted after a transaction commit fails with an exception. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + The exception object that caused the command execution to fail. + + + + + + + Contains diagnostic information emitted before a transaction rollback is rolled back. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction that the command is enrolled in if it is enrolled in one, or null. + + + + + The name of the transaction which is being rolled back. + + + + + + + Contains diagnostic information emitted after a transaction is rolled back successfully. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction, or null. + + + + + The name of the transaction which is being rolled back. + + + + + + + Contains diagnostic information emitted after a transaction roll back fails with an exception. + + + + + The name of the event that needs to be enabled for the event to be raised. + + + + + The connection object that the transaction belongs to. + + + + + The IsolationLevel of the transaction. + + + + + A nullable long uniquely identifying the transaction , or null. + + + + + The name of the transaction which is being rolled back. + + + + + The exception object that caused the command execution to fail. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientFactory.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientFactory.xml index 6408d55a11..ff41a4f383 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlClientFactory.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientFactory.xml @@ -1,252 +1,290 @@ - - - - - Represents a set of methods for creating instances of the - - provider's implementation of the data source classes. - - - To be added. - - - - - Gets a value that indicates whether a - - can be created. - - - - if a - - can be created; otherwise, - - . - - - class provides the property so that inheritors can indicate -whether they can provide a data source enumerator. The displays this property, but its value is always `true`. - -## Examples -The following example displays a list of all available SQL Server data sources, using code that could enumerate data sources for any provider. - -[!code-csharp[SqlClientFactory.DataSourceEnumerator#1](~/../sqlclient/doc/samples/SqlClientFactory_DataSourceEnumerator.cs#1)] -]]> - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbCommand cmd = newFactory.CreateCommand(); -``` -]]> - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbCommandBuilder cmd = newFactory.CreateCommandBuilder(); -``` -]]> - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbConnection cmd = newFactory.CreateConnection(); - -``` -]]> - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbConnectionStringBuilder cmd = -newFactory.CreateConnectionStringBuilder(); -``` -]]> - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbDataAdapter cmd = newFactory.CreateDataAdapter(); -``` -]]> - - - - - Returns a new - - . - - - A new data source enumerator. - - - - - - - - Returns a strongly typed - - instance. - - - A new strongly typed instance of - - . - - - instance: - - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbParameter cmd = newFactory.CreateParameter(); -``` -]]> - - - - - A member of the - - enumeration. - - - Returns a new - - . - - - A strongly typed instance of - - . - - - To be added. - - - - - Gets an instance of the - - . This can be used to retrieve strongly typed data objects. - - - property to retrieve a **SqlClientFactory** instance, and then return a strongly typed - instance: - - -```csharp -SqlClientFactory newFactory = SqlClientFactory.Instance; -DbCommand cmd = newFactory.CreateCommand(); -``` -]]> - - - + + + + + Represents a set of methods for creating instances of the provider's implementation of the data source classes. + + + + + Gets a value that indicates whether a can be created. + + + if a can be created; otherwise, . + + + The class provides the property so that inheritors can indicate whether they can provide a data source enumerator. The displays this property, but its value is always . + + + + The following example displays a list of all available SQL Server data sources, using code that could enumerate data sources for any provider. + + + + using System; + using System.Data; + using System.Data.Common; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + // List all SQL Server instances: + ListServers(SqlClientFactory.Instance); + + Console.WriteLine(); + Console.WriteLine("Press any key to continue..."); + Console.ReadKey(); + } + private static void ListServers(DbProviderFactory factory) + { + // This procedure is provider-agnostic, and can list + // instances of any provider's servers. Of course, + // not all providers can create a data source enumerator, + // so it's best to check the CanCreateDataSourceEnumerator + // property before attempting to list the data sources. + if (factory.CanCreateDataSourceEnumerator) + { + DbDataSourceEnumerator instance = + factory.CreateDataSourceEnumerator(); + DataTable table = instance.GetDataSources(); + + foreach (DataRow row in table.Rows) + { + Console.WriteLine("{0}\\{1}", + row["ServerName"], row["InstanceName"]); + } + } + } + } + + + + + + Gets a value that indicates whether a can be created. + + + if a can be created; otherwise, . + + + The class provides the property so that inheritors can indicate whether they can provide a DbBatch. The displays this property, but its value is always true. + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbCommand cmd = newFactory.CreateCommand(); + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbCommandBuilder cmd = newFactory.CreateCommandBuilder(); + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbConnection cmd = newFactory.CreateConnection(); + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbConnectionStringBuilder cmd = newFactory.CreateConnectionStringBuilder(); + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbDataAdapter cmd = newFactory.CreateDataAdapter(); + + + + + + Returns a new . + + + A new data source enumerator. + + + + The following example displays a list of all available SQL Server data sources, using code that could enumerate data sources for any provider. + + + + using System; + using System.Data; + using System.Data.Common; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + // List all SQL Server instances: + ListServers(SqlClientFactory.Instance); + + Console.WriteLine(); + Console.WriteLine("Press any key to continue..."); + Console.ReadKey(); + } + private static void ListServers(DbProviderFactory factory) + { + // This procedure is provider-agnostic, and can list + // instances of any provider's servers. Of course, + // not all providers can create a data source enumerator, + // so it's best to check the CanCreateDataSourceEnumerator + // property before attempting to list the data sources. + if (factory.CanCreateDataSourceEnumerator) + { + DbDataSourceEnumerator instance = + factory.CreateDataSourceEnumerator(); + DataTable table = instance.GetDataSources(); + + foreach (DataRow row in table.Rows) + { + Console.WriteLine("{0}\\{1}", + row["ServerName"], row["InstanceName"]); + } + } + } + } + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbParameter cmd = newFactory.CreateParameter(); + + + + + + A member of the enumeration. + + + Returns a new . + + + A strongly typed instance of . + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbParameter cmd = newFactory.CreateBatch(); + + + + + + Returns a strongly typed instance. + + + A new strongly typed instance of . + + + + The following code fragment returns a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbParameter cmd = newFactory.CreateBatchCommand(); + + + + + + Gets an instance of the . This can be used to retrieve strongly typed data objects. + + + + The following code fragment uses the property to retrieve a instance, and then return a strongly typed instance: + + + SqlClientFactory newFactory = SqlClientFactory.Instance; + DbCommand cmd = newFactory.CreateCommand(); + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientLogger.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientLogger.xml index c093bbd505..02748edca4 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlClientLogger.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientLogger.xml @@ -1,47 +1,84 @@ - - - Represents a SQL client logger. - To be added. - - - Initializes a new instance of the class. - To be added. - - - Gets a value that indicates whether bid tracing is enabled. - - if bid tracing is enabled; otherwise, . - To be added. - - - to log the message; otherwise, . - The type to be logged. - The logging method. - The message to be logged. - Logs the specified message if is . - if the message is not logged; otherwise, . - To be added. - - - The type to be logged. - The logging method. - The message to be logged. - Logs an error through a specified method of the current instance type. - To be added. - - - The type to be logged. - The logging method. - The message to be logged. - Logs information through a specified method of the current instance type. - To be added. - - - The type to be logged. - The logging method. - The message to be logged. - Logs warning through a specified method of the current instance type. - - + + + + Represents a SQL client logger. + + + + + Initializes a new instance of the class. + + + + + Gets a value that indicates whether bid tracing is enabled. + + + if bid tracing is enabled; otherwise, . + + + + + to log the message; otherwise, . + + + The type to be logged. + + + The logging method. + + + The message to be logged. + + + Logs the specified message if is . + + + if the message is not logged; otherwise, . + + + + + The type to be logged. + + + The logging method. + + + The message to be logged. + + + Logs an error through a specified method of the current instance type. + + + + + The type to be logged. + + + The logging method. + + + The message to be logged. + + + Logs information through a specified method of the current instance type. + + + + + The type to be logged. + + + The logging method. + + + The message to be logged. + + + Logs warning through a specified method of the current instance type. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientMetaDataCollectionNames.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientMetaDataCollectionNames.xml index 01d30ee8d3..74bf4f9195 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlClientMetaDataCollectionNames.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientMetaDataCollectionNames.xml @@ -1,68 +1,84 @@ - - - Provides a list of constants for use with the **GetSchema** method to retrieve metadata collections. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Columns** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Databases** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **ForeignKeys** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **IndexColumns** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Indexes** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **ProcedureParameters** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Procedures** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Tables** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **UserDefinedTypes** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Users** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **ViewColumns** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **Views** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **AllColumns** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **ColumnSetColumns** collection. - To be added. - - - A constant for use with the **GetSchema** method that represents the **StructuredTypeMembers** collection. - To be added. - - + + + + Provides a list of constants for use with the method to retrieve metadata collections. + + + + + A constant for use with the method that represents the Columns collection. + + + + + A constant for use with the method that represents the Databases collection. + + + + + A constant for use with the method that represents the ForeignKeys collection. + + + + + A constant for use with the method that represents the IndexColumns collection. + + + + + A constant for use with the method that represents the Indexes collection. + + + + + A constant for use with the method that represents the ProcedureParameters collection. + + + + + A constant for use with the method that represents the Procedures collection. + + + + + A constant for use with the method that represents the Tables collection. + + + + + A constant for use with the method that represents the UserDefinedTypes collection. + + + + + A constant for use with the method that represents the Users collection. + + + + + A constant for use with the method that represents the ViewColumns collection. + + + + + A constant for use with the method that represents the Views collection. + + + + + A constant for use with the method that represents the AllColumns collection. + + + + + A constant for use with the method that represents the ColumnSetColumns collection. + + + + + A constant for use with the method that represents the StructuredTypeMembers collection. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermission.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermission.xml index c9b4ff0c38..0c7ba2ff03 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermission.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermission.xml @@ -1,153 +1,166 @@ - - - Enables the .NET Framework Data Provider for SQL Server to help make sure that a user has a security level sufficient to access a data source. - - property takes precedence over the property. -Therefore, if you set to `false`, you must also set -to `false` to prevent a user from making a connection using a blank password. - -> [!NOTE] -> When using code access security permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that -are needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then denying a specific permission, -is not secure, because there are many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection -string "server=someserver", the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are -holes in the permission set. - -]]> - - - - Initializes a new instance of the class. - To be added. - - - One of the values. - Initializes a new instance of the class. - To be added. - - - One of the values. - Indicates whether a blank password is allowed. - Initializes a new instance of the class. - - enumeration takes precedence over the property. -Therefore, if you set to `false`, you must also set to `None` to -prevent a user from making a connection using a blank password. For an example demonstrating how to use security demands, see [Code Access Security and -ADO.NET](/dotnet/framework/data/adonet/code-access-security). - -]]> - - - - The connection string. - The key restrictions. - One of the enumerations. - Adds a new connection string and a set of restricted keywords to the object. - - [!NOTE] -> When using code access security permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that are -needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then trying to deny a specific permission, is not secure, because there are -many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection string "server=someserver", -the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are holes in the permission set. - - ]]> - - - - Returns the as an . - A copy of the current permission object. - To be added. - - - Creates an XML encoding of the security object and its current state. - An XML encoding of the security object, including any state information. - - and methods to make the objects security encodable. - -]]> - - - - The XML encoding to use to reconstruct the security object. - Reconstructs a security object with a specified state from an XML encoding. - - - - - - A permission object to combine with the current permission object. It must be of the same type as the current permission object. - Returns a new permission object that is the union of the current and specified permission objects. - A new permission object that represents the union of the current permission object and the specified permission object. - - is a permission that represents all the operations permitted by both the current permission object and the specified permission object. Any demand that passes either permission passes their union. - -]]> - - The object is not the same type as the current permission object. - - - A permission object that is to be tested for the subset relationship. This object must be of the same type as the current permission object. - Returns a value indicating whether the current permission object is a subset of the specified permission object. - - if the current permission object is a subset of the specified permission object, otherwise . - - - - The parameter is an object that is not of the same type as the current permission object. - - - A permission object to intersect with the current permission object. It must be of the same type as the current permission object. - Returns a new permission object representing the intersection of the current permission object and the specified permission object. - A new permission object that represents the intersection of the current permission object and the specified permission object. This new permission object is a null reference ( in Visual Basic) if the intersection is empty. - - - - The parameter is not a null reference ( in Visual Basic) and is not an instance of the same class as the current permission object. - - + + + + Enables the .NET Framework Data Provider for SQL Server to help make sure that a user has a security level sufficient to access a data source. + + + + The property takes precedence over the property. Therefore, if you set to , you must also set to to prevent a user from making a connection using a blank password. + + + When using code access security permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that are needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then denying a specific permission, is not secure, because there are many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection string "server=someserver", the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are holes in the permission set. + + + + + + Initializes a new instance of the class. + + + + + One of the values. + + + Initializes a new instance of the class. + + + + + One of the values. + + + Indicates whether a blank password is allowed. + + + Initializes a new instance of the class. + + + The enumeration takes precedence over the property. Therefore, if you set to , you must also set to None to prevent a user from making a connection using a blank password. For an example demonstrating how to use security demands, see Code Access Security and ADO.NET. + + + + + The connection string. + + + The key restrictions. + + + One of the enumerations. + + + Adds a new connection string and a set of restricted keywords to the object. + + + + Use this method to configure which connection strings are allowed by a particular permission object. For example, use the following code fragment if you want to only allow a specific connection string and nothing else: + + + permission.Add("server=MyServer; database=MyDatabase; Integrated Security=true", "", KeyRestrictionBehavior.AllowOnly) + + + When using code access security permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that are needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then trying to deny a specific permission, is not secure, because there are many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection string "server=someserver", the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are holes in the permission set. + + + + + The following example allows connection strings that use any database, but only on the server named MyServer, with any user and password combination and containing no other connection string keywords: + + + permission.Add("server=MyServer;", "database=; user id=; password=;", KeyRestrictionBehavior.AllowOnly) + + + + + The following example uses the same scenario as above but allows for a failover partner that can be used when connecting to servers configured for mirroring: + + + permission.Add("server=MyServer; failover partner=MyMirrorServer", "database=; user id=; password=;", KeyRestrictionBehavior.AllowOnly) + + + + + + Returns the as an . + + + A copy of the current permission object. + + + + + Creates an XML encoding of the security object and its current state. + + + An XML encoding of the security object, including any state information. + + + Custom code that extends security objects must implement the and methods to make the objects security encodable. + + + + + The XML encoding to use to reconstruct the security object. + + + Reconstructs a security object with a specified state from an XML encoding. + + + Custom code that extends security objects needs to implement the and methods to make the objects security encodable. + + + + + A permission object to combine with the current permission object. It must be of the same type as the current permission object. + + + Returns a new permission object that is the union of the current and specified permission objects. + + + A new permission object that represents the union of the current permission object and the specified permission object. + + + The result of a call to is a permission that represents all the operations permitted by both the current permission object and the specified permission object. Any demand that passes either permission passes their union. + + + The object is not the same type as the current permission object. + + + + + A permission object that is to be tested for the subset relationship. This object must be of the same type as the current permission object. + + + Returns a value indicating whether the current permission object is a subset of the specified permission object. + + + if the current permission object is a subset of the specified permission object, otherwise . + + + The current permission object is a subset of the specified permission object if the current permission object specifies a set of operations that is wholly contained by the specified permission object. For example, a permission that represents access to C:\example.txt is a subset of a permission that represents access to C:\. If this method returns , the current permission object represents no more access to the protected resource than does the specified permission object. + + + The parameter is an object that is not of the same type as the current permission object. + + + + + A permission object to intersect with the current permission object. It must be of the same type as the current permission object. + + + Returns a new permission object representing the intersection of the current permission object and the specified permission object. + + + A new permission object that represents the intersection of the current permission object and the specified permission object. This new permission object is a null reference ( in Visual Basic) if the intersection is empty. + + + The intersection of two permissions is a permission that describes the set of operations they both describe. Only a demand that passes both original permissions will pass the intersection. + + + The parameter is not a null reference ( in Visual Basic) and is not an instance of the same class as the current permission object. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermissionAttribute.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermissionAttribute.xml index 3c52bb4303..2d90c4867e 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermissionAttribute.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlClientPermissionAttribute.xml @@ -1,18 +1,25 @@ - - - Associates a security action with a custom security attribute. - To be added. - - - One of the values representing an action that can be performed by using declarative security. - Initializes a new instance of the class. - To be added. - - - Returns a object that is configured according to the attribute properties. - A object. - To be added. - - + + + + Associates a security action with a custom security attribute. + + + + + One of the values representing an action that can be performed by using declarative security. + + + Initializes a new instance of the class. + + + + + Returns a object that is configured according to the attribute properties. + + + A object. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCertificateStoreProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCertificateStoreProvider.xml index 697e9b8539..c7529fc744 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCertificateStoreProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCertificateStoreProvider.xml @@ -1,61 +1,84 @@ - - - The implementation of the key store provider for Windows Certificate Store. This class enables using certificates stored in the Windows Certificate Store as column master keys. - For details, see Always Encrypted. - - To be added. - - - Key store provider for Windows Certificate Store. - To be added. - - - The master key path. - The encryption algorithm. Currently, the only valid value is: RSA_OAEP - - The encrypted column encryption key. - Decrypts the specified encrypted value of a column encryption key. The encrypted value is expected to be encrypted using the certificate with the specified key path and using the specified - algorithm. The format of the key path should be "Local Machine/My/<certificate_thumbprint>" or "Current User/My/<certificate_thumbprint>". - - Returns -. The decrypted column encryption key. - To be added. - - - The master key path. - The encryption algorithm. Currently, the only valid value is: RSA_OAEP - - The plaintext column encryption key. - Encrypts a column encryption key using the certificate with the specified key path and using the specified algorithm. The format of the key path should be - "Local Machine/My/<certificate_thumbprint>" or "Current User/My/<certificate_thumbprint>". - - Returns -. The encrypted column encryption key. - To be added. - - - The provider name. - To be added. - - - The column master key path. - - -to indicate that the column master key supports enclave computations; otherwise, -. - Digitally signs the column master key metadata with the column master key referenced by the -parameter. - The signature of the column master key metadata. - To be added. - - - The complete path of an asymmetric key. The path format is specific to a key store provider. - A Boolean that indicates if this key can be sent to the trusted enclave. - The master key metadata siognature. - This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and verify the masterkey metadata consisting of (masterKeyPath, allowEnclaveComputations, providerName). - A Boolean value that indicates if the master key metadata can be verified based on the provided signature. - To be added. - - - \ No newline at end of file + + + + The implementation of the key store provider for Windows Certificate Store. This class enables using certificates stored in the Windows Certificate Store as column master keys. For details, see Always Encrypted. + + + + + Key store provider for Windows Certificate Store. + + + + + The master key path. + + + The encryption algorithm. Currently, the only valid value is: RSA_OAEP + + + The encrypted column encryption key. + + + Decrypts the specified encrypted value of a column encryption key. The encrypted value is expected to be encrypted using the certificate with the specified key path and using the specified algorithm. The format of the key path should be "Local Machine/My/<certificate_thumbprint>" or "Current User/My/<certificate_thumbprint>". + + + Returns . The decrypted column encryption key. + + + + + The master key path. + + + The encryption algorithm. Currently, the only valid value is: RSA_OAEP + + + The plaintext column encryption key. + + + Encrypts a column encryption key using the certificate with the specified key path and using the specified algorithm. The format of the key path should be "Local Machine/My/<certificate_thumbprint>" or "Current User/My/<certificate_thumbprint>". + + + Returns . The encrypted column encryption key. + + + + + The provider name. + + + + + The column master key path. + + + to indicate that the column master key supports enclave computations; otherwise, . + + + Digitally signs the column master key metadata with the column master key referenced by the parameter. + + + The signature of the column master key metadata. + + + + + The complete path of an asymmetric key. The path format is specific to a key store provider. + + + A Boolean that indicates if this key can be sent to the trusted enclave. + + + The master key metadata signature. + + + This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and verify the masterkey metadata consisting of (masterKeyPath, allowEnclaveComputations, providerName). + + + A Boolean value that indicates if the master key metadata can be verified based on the provided signature. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCngProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCngProvider.xml index 30d0640781..d4db77f1a3 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCngProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCngProvider.xml @@ -1,67 +1,90 @@ - - - The CMK Store provider implementation for using the Microsoft Cryptography API: Next Generation (CNG) with - Always Encrypted. - - - - - - - Initializes a new instance of the class. - To be added. - - - The master key path. - The encryption algorithm. - The encrypted column encryption key. - Decrypts the given encrypted value using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier - and should be an asymmetric key stored in the specified CNG key store provider. The valid algorithm used to encrypt/decrypt the CEK is 'RSA_OAEP'. - - The decrypted column encryption key. - To be added. - - - The master key path. - The encryption algorithm. - The plaintext column encryption key. - Encrypts the given plain text column encryption key using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CNG key store provider. The valid algorithm used to encrypt/decrypt the CEK is 'RSA_OAEP'. - The encrypted column encryption key. - To be added. - - - A constant string for the provider name 'MSSQL_CNG_STORE'. - To be added. - - - The column master key path. The path format is specific to a key store provider. - to indicate that the column master key supports enclave computations; otherwise, . - Throws a exception in all cases. - The signature of the column master key metadata. - - method must be implemented by the corresponding key store providers. - should use an asymmetric key identified by a key path and sign the masterkey metadata consisting - of `masterKeyPath`, `allowEnclaveComputations`, and providerName. - - ]]> - - - - The complete path of an asymmetric key. The path format is specific to a key store provider. - A Boolean that indicates if this key can be sent to the trusted enclave. - The master key metadata signature. - This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and verify the masterkey metadata consisting of (masterKeyPath, allowEnclaveComputations, providerName). - A Boolean that indicates if the master key metadata can be verified based on the provided signature. - To be added. - - + + + + The CMK Store provider implementation for using the Microsoft Cryptography API: Next Generation (CNG) with Always Encrypted. + + + Enables storing Always Encrypted column master key keys in a store, such as a hardware security module (HSM), that supports the Microsoft Cryptography API: Next Generation (CNG). + + + + + Initializes a new instance of the class. + + + + + The master key path. + + + The encryption algorithm. + + + The encrypted column encryption key. + + + Decrypts the given encrypted value using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CNG key store provider. The valid algorithm used to encrypt/decrypt the CEK is RSA_OAEP. + + + The decrypted column encryption key. + + + + + The master key path. + + + The encryption algorithm. + + + The plaintext column encryption key. + + + Encrypts the given plain text column encryption key using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CNG key store provider. The valid algorithm used to encrypt/decrypt the CEK is RSA_OAEP. + + + The encrypted column encryption key. + + + + + A constant string for the provider name MSSQL_CNG_STORE>. + + + + + The column master key path. The path format is specific to a key store provider. + + + to indicate that the column master key supports enclave computations; otherwise, . + + + Throws a exception in all cases. + + + The signature of the column master key metadata. + + + The method must be implemented by the corresponding key store providers. should use an asymmetric key identified by a key path and sign the master key metadata consisting of , , and . + + + + + The complete path of an asymmetric key. The path format is specific to a key store provider. + + + A Boolean that indicates if this key can be sent to the trusted enclave. + + + The master key metadata signature. + + + This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and verify the master key metadata consisting of (masterKeyPath, allowEnclaveComputations, providerName). + + + A Boolean that indicates if the master key metadata can be verified based on the provided signature. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCspProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCspProvider.xml index 9e360781be..21bddf73b2 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCspProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCspProvider.xml @@ -1,65 +1,90 @@ - - - The CMK Store provider implementation for using Microsoft CAPI based Cryptographic Service Providers (CSP) with - Always Encrypted. - - - - - - - Initializes a new instance of the class. - To be added. - - - The master key path. - The encryption algorithm. - The encrypted column encryption key. - Decrypts the given encrypted value using an asymmetric key specified by the key path and algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CSP provider. The valid algorithm used to encrypt/decrypt the CEK is 'RSA_OAEP'. - The decrypted column encryption key. - To be added. - - - The master key path. - The encryption algorithm. - The plaintext column encryption key. - Encrypts the given plain text column encryption key using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CSP provider. The valid algorithm used to encrypt/decrypt the CEK is 'RSA_OAEP'. - The encrypted column encryption key. - To be added. - - - A constant string for the provider name 'MSSQL_CSP_PROVIDER'. - To be added. - - - The column master key path. The path format is specific to a key store provider. - to indicate that the column master key supports enclave computations; otherwise, . - Throws a exception in all cases. - The signature of the column master key metadata. - - method must be implemented by the corresponding key store providers. - should use an asymmetric key identified by a key path and sign the masterkey metadata -consisting of `masterKeyPath`, `allowEnclaveComputations`, and providerName. - -]]> - - - - The complete path of an asymmetric key. The path format is specific to a key store provider. - A boolean that indicates if this key can be sent to the trusted enclave. - Master key metadata signature. - This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and sign the masterkey metadata consisting of (masterKeyPath, allowEnclaveComputations, providerName). - A Boolean that indicates if the master key metadata can be verified based on the provided signature. - To be added. - - + + + + The CMK Store provider implementation for using Microsoft CAPI based Cryptographic Service Providers (CSP) with Always Encrypted. + + + Enables storing Always Encrypted column master key keys in a store, such as a hardware security module (HSM), that supports the Microsoft CAPI based Cryptographic Service Providers (CSP). + + + + + Initializes a new instance of the class. + + + + + The master key path. + + + The encryption algorithm. + + + The encrypted column encryption key. + + + Decrypts the given encrypted value using an asymmetric key specified by the key path and algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CSP provider. The valid algorithm used to encrypt/decrypt the CEK is RSA_OAEP'. + + + The decrypted column encryption key. + + + + + The master key path. + + + The encryption algorithm. + + + The plaintext column encryption key. + + + Encrypts the given plain text column encryption key using an asymmetric key specified by the key path and the specified algorithm. The key path will be in the format of [ProviderName]/KeyIdentifier and should be an asymmetric key stored in the specified CSP provider. The valid algorithm used to encrypt/decrypt the CEK is RSA_OAEP. + + + The encrypted column encryption key. + + + + + A constant string for the provider name MSSQL_CSP_PROVIDER. + + + + + The column master key path. The path format is specific to a key store provider. + + + to indicate that the column master key supports enclave computations; otherwise, . + + + Throws a exception in all cases. + + + The signature of the column master key metadata. + + + The method must be implemented by the corresponding key store providers. should use an asymmetric key identified by a key path and sign the master key metadata consisting of , , and . + + + + + The complete path of an asymmetric key. The path format is specific to a key store provider. + + + A boolean that indicates if this key can be sent to the trusted enclave. + + + Master key metadata signature. + + + This function must be implemented by the corresponding Key Store providers. This function should use an asymmetric key identified by a key path and sign the masterkey metadata consisting of (, , ). + + + A Boolean that indicates if the master key metadata can be verified based on the provided signature. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionEnclaveProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionEnclaveProvider.xml index dfbdbe8782..4276c98b9f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionEnclaveProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionEnclaveProvider.xml @@ -1,57 +1,97 @@ - - - The base class that defines the interface for enclave providers for Always Encrypted. - - - - - - Initializes a new instance of the class - To be added. - - - The information the provider uses to attest the enclave and generate a symmetric key for the session. The format of this information is specific to the enclave attestation protocol. - A Diffie-Hellman algorithm object that encapsulates a client-side key pair. - The set of parameters required for an enclave session. - The set of extra data needed for attesting the enclave. - The length of the extra data needed for attesting the enclave. - The requested enclave session or if the provider doesn't implement session caching. - A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. - When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. - To be added. - - - The endpoint of an attestation service for attesting the enclave. - A set of extra data needed for attesting the enclave. - The length of the extra data needed for attesting the enclave. - Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. - The information SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. - To be added. - - - The set of parameters required for enclave session. - to indicate that a set of extra data needs to be generated for attestation; otherwise, . - Indicates if this is a retry from a failed call. - When this method returns, the requested enclave session or if the provider doesn't implement session caching. This parameter is treated as uninitialized. - A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. - A set of extra data needed for attesting the enclave. - The length of the extra data needed for attesting the enclave. - When overridden in a derived class, looks up an existing enclave session information in the enclave session cache. If the enclave provider doesn't implement enclave session caching, this method is expected to return in the parameter. - - To be added. - - - The set of parameters required for enclave session. - The session to be invalidated. - When overridden in a derived class, looks up and evicts an enclave session from the enclave session cache, if the provider implements session caching. - To be added. - - + + + + The base class that defines the interface for enclave providers for Always Encrypted. + + + An enclave is a protected region of memory inside SQL Server, used for computations on encrypted columns. An enclave provider encapsulates the client-side implementation details of the enclave attestation protocol as well as the logic for creating and caching enclave sessions. + + + + + Initializes a new instance of the class + + + + + The information the provider uses to attest the enclave and generate a symmetric key for the session. The format of this information is specific to the enclave attestation protocol. + + + A Diffie-Hellman algorithm object that encapsulates a client-side key pair. + + + The set of parameters required for an enclave session. + + + The set of extra data needed for attesting the enclave. + + + The length of the extra data needed for attesting the enclave. + + + The requested enclave session or if the provider doesn't implement session caching. + + + A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. + + + When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates an enclave session and stores the session information in the cache. + + + + + The endpoint of an attestation service for attesting the enclave. + + + A set of extra data needed for attesting the enclave. + + + The length of the extra data needed for attesting the enclave. + + + Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. + + + The information SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. + + + + + The set of parameters required for enclave session. + + + to indicate that a set of extra data needs to be generated for attestation; otherwise, . + + + Indicates if this is a retry from a failed call. + + + When this method returns, the requested enclave session or if the provider doesn't implement session caching. This parameter is treated as uninitialized. + + + A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. + + + A set of extra data needed for attesting the enclave. + + + The length of the extra data needed for attesting the enclave. + + + When overridden in a derived class, looks up an existing enclave session information in the enclave session cache. If the enclave provider doesn't implement enclave session caching, this method is expected to return in the parameter. + + + + + The set of parameters required for enclave session. + + + The session to be invalidated. + + + When overridden in a derived class, looks up and evicts an enclave session from the enclave session cache, if the provider implements session caching. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml index 7c2dc715fd..8d57587c77 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml @@ -1,74 +1,103 @@ - - - Base class for all key store providers. A custom provider must derive from this class and override its member functions and then register it using - , - or - . - For details see, Always Encrypted. - - - - Initializes a new instance of the SqlColumnEncryptionKeyStoreProviderClass. - To be added. - - - The master key path. - The encryption algorithm. - The encrypted column encryption key. - Decrypts the specified encrypted value of a column encryption key. The encrypted value is expected to be encrypted using the column master key with the specified key path and using the specified algorithm. - - Returns . The decrypted column encryption key. - To be added. - - - The master key path. - The encryption algorithm. - The plaintext column encryption key. - Encrypts a column encryption key using the column master key with the specified key path and using the specified algorithm. - Returns . The encrypted column encryption key. - To be added. - - - The column master key path. - to indicate that the column master key supports enclave computations; otherwise, . - When implemented in a derived class, digitally signs the column master key metadata with the column master key referenced by the parameter. The input values used to generate the signature should be the specified values of the and parameters. - - The signature of the column master key metadata. - - method doesn't break applications that rely on an old API, it throws a - exception by default. - -The method will be used by client tools that generate Column Master Keys (CMK) for customers. - must be implemented by the corresponding key store providers that wish to use enclaves with -[Always Encrypted](https://docs.microsoft.com/sql/relational-databases/security/encryption/always-encrypted-database-engine). - -]]> - - In all cases. - - - The column master key path. - Indicates whether the column master key supports enclave computations. - The signature of the column master key metadata. - When implemented in a derived class, this method is expected to verify the specified signature is valid for the column master key with the specified key path and the specified enclave behavior. The default implementation throws NotImplementedException. - When implemented in a derived class, the method is expected to return true if the specified signature is valid, or false if the specified signature is not valid. The default implementation throws NotImplementedException. - To be added. - - - Gets or sets the lifespan of the decrypted column encryption key in the cache. Once the timespan has elapsed, the decrypted column encryption key is discarded and must be revalidated. - - . Any caching implementation should reference the value of this property before caching a column encryption key and not cache it if the value is zero. This will avoid duplicate caching and possible user confusion when they are trying to configure key caching. - ]]> - - - + + + + Base class for all key store providers. A custom provider must derive from this class and override its member functions and then register it using , or . For details see, Always Encrypted. + + + + + Initializes a new instance of the . + + + + + The master key path. + + + The encryption algorithm. + + + The encrypted column encryption key. + + + Decrypts the specified encrypted value of a column encryption key. The encrypted value is expected to be encrypted using the column master key with the specified key path and using the specified algorithm. + + + Returns . The decrypted column encryption key. + + + + + The master key path. + + + The encryption algorithm. + + + The plaintext column encryption key. + + + Encrypts a column encryption key using the column master key with the specified key path and using the specified algorithm. + + + Returns . The encrypted column encryption key. + + + + + The column master key path. + + + to indicate that the column master key supports enclave computations; otherwise, . + + + When implemented in a derived class, digitally signs the column master key metadata with the column master key referenced by the parameter. The input values used to generate the signature should be the specified values of the and parameters. + + + The signature of the column master key metadata. + + + + To ensure that the method doesn't break applications that rely on an old API, it throws a exception by default. + + + The method will be used by client tools that generate Column Master Keys (CMK) for customers. must be implemented by the corresponding key store providers that wish to use enclaves with Always Encrypted. + + + + In all cases. + + + + + The column master key path. + + + Indicates whether the column master key supports enclave computations. + + + The signature of the column master key metadata. + + + When implemented in a derived class, this method is expected to verify the specified signature is valid for the column master key with the specified key path and the specified enclave behavior. The default implementation throws NotImplementedException. + + + When implemented in a derived class, the method is expected to return true if the specified signature is valid, or false if the specified signature is not valid. The default implementation throws NotImplementedException. + + + + + Gets or sets the lifespan of the decrypted column encryption key in the cache. Once the timespan has elapsed, the decrypted column encryption key is discarded and must be revalidated. + + + + Internally, there is a cache of column encryption keys (once they are decrypted). This is useful for rapidly decrypting multiple data values. The default value is 2 hours. Setting this value to zero disables caching. + + + The column encryption keys decrypted by custom key store providers registered on a connection or command instance will not be cached. Custom key store providers should implement their own caching mechanism. Caching implemented by custom key store providers will be disabled by the driver if the key store provider instance is registered using . Any caching implementation should reference the value of this property before caching a column encryption key and not cache it if the value is zero. This will avoid duplicate caching and possible user confusion when they are trying to configure key caching. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml index 8dea0674cc..5a319a119f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml @@ -1,3107 +1,4330 @@ - - - - Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database. This class cannot be inherited. - - - is created, the read/write properties are set to their initial values. For a list of these values, see the constructor. - - features the following methods for executing commands at a SQL Server database: - -|Item|Description| -|----------|-----------------| -||Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , generally executing commands such as INSERT, DELETE, UPDATE, and SET statements. Each call to must be paired with a call to which finishes the operation, typically on a separate thread.| -||Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and retrieves one or more results sets from the server. Each call to must be paired with a call to which finishes the operation, typically on a separate thread.| -||Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this . Each call to `BeginExecuteXmlReader` must be paired with a call to `EndExecuteXmlReader`, which finishes the operation, typically on a separate thread, and returns an object.| -||Executes commands that return rows. For increased performance, invokes commands using the Transact-SQL `sp_executesql` system stored procedure. Therefore, might not have the effect that you want if used to execute commands such as Transact-SQL SET statements.| -||Executes commands such as Transact-SQL INSERT, DELETE, UPDATE, and SET statements.| -||Retrieves a single value (for example, an aggregate value) from a database.| -||Sends the to the and builds an object.| - -You can reset the property and reuse the object. However, you must close the before you can execute a new or previous command. - -If a is generated by the method executing a , the remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. - -> [!NOTE] -> Nameless, also called ordinal, parameters are not supported by the .NET Framework Data Provider for SQL Server. - -## Examples -The following example creates a , a , and a . The example reads through the data, writing it to the console. Finally, the example closes the and then the as it exits the `Using` code blocks. - -[!code-csharp[SqlCommand Example#1](~/../sqlclient/doc/samples/SqlCommand.cs#1)] - -The following sample shows how to create and execute different types of SqlCommand objects. - -First you must create the sample database, by executing the following script: - -[!code-sql[Setup Database](~/../sqlclient/doc/samples/SqlCommand_Setup.sql#1)] - -Next, compile and execute the following: - -[!code-csharp[SqlCommand Example#2](~/../sqlclient/doc/samples/SqlCommand_Intro.cs#1)] -]]> - - - - - Initializes a new instance of the - - class. - - - . - -|Properties|Initial value| -|----------------|-------------------| -||empty string ("")| -||30| -||`CommandType.Text`| -||Null| - -You can change the value for any of these properties through a separate call to the property. - - - -## Examples -The following example creates a and sets the `CommandTimeout` property. - -[!code-csharp[Classic WebData IDbCommand_CommandTimeout.cs](~/../sqlclient/doc/samples/IDbCommand_CommandTimeout.cs)] -]]> - - - - - The text of the query. - - - Initializes a new instance of the - - class with the text of the query. - - - is created, the following read/write properties are set to initial values. - -|Properties|Initial value| -|----------------|-------------------| -||`cmdText`| -||30| -||`CommandType.Text`| -||null| - -You can change the value for any of these properties through a separate call to the property. - -## Examples -The following example creates a , passing in the connection string and command text. - -[!code-csharp[SqlCommand_SqlCommand1](~/../sqlclient/doc/samples/SqlCommand_SqlCommand1.cs#1)] -]]> - - - - - The text of the query. - - - A - - that represents the connection to an instance of SQL Server. - - - Initializes a new instance of the - - class with the text of the query and a - - . - - - . - -|Properties|Initial value| -|----------------|-------------------| -||`cmdText`| -||30| -||`CommandType.Text`| -||A new that is the value for the `connection` parameter.| - -You can change the value for any of these parameters by setting the related property. - -## Examples -The following example creates a and sets some of its properties. - -[!code-csharp[SqlCommand_SqlCommand2.cs](~/../sqlclient/doc/samples/SqlCommand_SqlCommand2.cs#1)] -]]> - - - - - The text of the query. - - - A - - that represents the connection to an instance of SQL Server. - - - The - - in which the - - executes. - - - Initializes a new instance of the - - class with the text of the query, a - - , and the - - . - - - . - -|Properties|Initial value| -|----------------|-------------------| -||`cmdText`| -||30| -||`CommandType.Text`| -||A new that is the value for the `connection` parameter.| - -You can change the value for any of these parameters by setting the related property. -]]> - - - - - The text of the query. - - - A - - that represents the connection to an instance of SQL Server. - - - The - - in which the - - executes. - - - The encryption setting. For more information, see [Always Encrypted](/sql/relational-databases/security/encryption/always-encrypted-database-engine). - - - Initializes a new instance of the - - class with specified command text, connection, transaction, and encryption setting. - - - To be added. - - - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - . - - - An - - that can be used to poll or wait for results, or both; this value is also needed when invoking - - , which returns the number of affected rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that does not return rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. - -Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . - -This method ignores the property. - - -## Examples -The following console application creates updates data within the **AdventureWorks** sample database, doing its work asynchronously. In order to emulate a long-running process, this example inserts a WAITFOR statement in the command text. Normally, you would not take efforts to make your commands run slower, but doing this in this case makes it easier to demonstrate the asynchronous behavior. - -[!code-csharp[SqlCommand_BeginExecuteNonQuery](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteNonQuery.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An - - delegate that is invoked when the command's execution has completed. Pass - - ( - - in Microsoft Visual Basic) to indicate that no callback is required. - - - A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the - - property. - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - , given a callback procedure and state information. - - - An - - that can be used to poll or wait for results, or both; this value is also needed when invoking - - , which returns the number of affected rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that does not return rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -The `callback` parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the `asyncStateObject` parameter, and your callback procedure can retrieve this information using the property. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. - -Because the callback procedure executes from within a background thread supplied by the Microsoft .NET common language runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure; should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. - -All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. - -This method ignores the property. - -## Examples -The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of several seconds (emulating a long-running command). - -This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. - -To set up this example, create a new Windows application. Put a control and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. - -[!code-csharp[DataWorks SqlCommand_BeginExecuteNonQueryForm#1](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteNonQueryForm.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - , and retrieves one or more result sets from the server. - - - An - - that can be used to poll or wait for results, or both; this value is also needed when invoking - - , which returns a - - instance that can be used to retrieve the returned rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. - -Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following console application starts the process of retrieving a data reader asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. As soon as the process has completed, the code retrieves the and displays its contents. - -[!code-csharp[SqlCommand_BeginExecuteReader#1](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteReader.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - One of the - - values, indicating options for statement execution and data retrieval. - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - using one of the - - values. - - - An - - that can be used to poll, wait for results, or both; this value is also needed when invoking - - , which returns a - - instance that can be used to retrieve the returned rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -The `behavior` parameter lets you specify options that control the behavior of the command and its connection. These values can be combined together (using the programming language's `OR` operator); generally, developers use the `CommandBehavior.CloseConnection` value to make sure that the connection is closed by the runtime when the is closed. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. - -Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . - -If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following console application starts the process of retrieving a data reader asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. Once the process has completed, the code retrieves the and displays its contents. - -This example also passes the `CommandBehavior.CloseConnection` and `CommandBehavior.SingleRow` values in the behavior parameter, causing the connection to be closed with the returned is closed, and to optimize for a single row result. - -[!code-csharp[SqlCommand_BeginExecuteReaderAsyncSimple](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteReaderAsyncSimple.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An - - delegate that is invoked when the command's execution has completed. Pass - - ( - - in Microsoft Visual Basic) to indicate that no callback is required. - - - A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the - - property. - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - and retrieves one or more result sets from the server, given a callback procedure and state information. - - - An - - that can be used to poll, wait for results, or both; this value is also needed when invoking - - , which returns a - - instance which can be used to retrieve the returned rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed cause the object to block until the execution is finished. - -The `callback` parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the `stateObject` parameter, and your callback procedure can retrieve this information using the property. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. - -Because the callback procedure executes from within a background thread supplied by the Microsoft .NET runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure; should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. - -All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. - -If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). Because the sample executes the command asynchronously, the form remains responsive while awaiting the results. This example passes the executing object as the `stateObject` parameter; doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . - -This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. - -To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. - -[!code-csharp[SqlCommand_BeginExecuteReaderAsync.cs](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteReaderAsync.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An - - delegate that is invoked when the command's execution has completed. Pass - - ( - - in Microsoft Visual Basic) to indicate that no callback is required. - - - A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the - - property. - - - One of the - - values, indicating options for statement execution and data retrieval. - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - , using one of the - - values, and retrieving one or more result sets from the server, given a callback procedure and state information. - - - An - - that can be used to poll or wait for results, or both; this value is also needed when invoking - - , which returns a - - instance which can be used to retrieve the returned rows. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -The `callback` parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the `stateObject` parameter, and your callback procedure can retrieve this information using the property. - -The `behavior` parameter lets you specify options that control the behavior of the command and its connection. These values can be combined together (using the programming language's `Or` operator); generally, developers use the `CloseConnection` value to make sure that the connection is closed by the runtime when the is closed. Developers can also optimize the behavior of the by specifying the `SingleRow` value when it is known in advance that the Transact-SQL statement or stored procedure only returns a single row. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. - -Because the callback procedure executes from within a background thread supplied by the Microsoft .NET common language runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure--should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. - -All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). Because the sample executes the command asynchronously, the form remains responsive while awaiting the results. This example passes the executing object as the `stateObject` parameter; doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . - -This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. - -To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. - -This example passes the `CommandBehavior.CloseConnection` value in the `behavior` parameter, causing the returned to automatically close its connection when it is closed. - -[!code-csharp[SqlCommand_BeginExecuteReaderAsyncBehavior](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteReaderAsyncBehavior.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - and returns results as an - - object. - - - An - - that can be used to poll or wait for results, or both; this value is also needed when invoking - - , which returns a single XML value. - - - method starts the process of asynchronously executing a Transact-SQL statement that returns rows as XML, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the `EndExecuteXmlReader` method to finish the operation and retrieve the XML returned by the command. The method returns immediately, but until the code executes the corresponding `EndExecuteXmlReader` method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the `EndExecuteXmlReader` before the command's execution is completed causes the object to block until the execution is finished. - -The property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, `CommandText` can also specify a statement that returns `ntext` data that contains valid XML. - -A typical query can be formatted as in the following C# example: - -```csharp -SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM dbo.Contact FOR XML AUTO, XMLDATA", SqlConn); -``` - -This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the `EndExecuteXmlReader` method attaches the to the value on the first row, and discards the rest of the result set. - -The multiple active result set (MARS) feature lets multiple actions use the same connection. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. - -Because this overload does not support a callback procedure, developers need to either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . - -If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following console application starts the process of retrieving XML data asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. Once the process has completed, the code retrieves the XML and displays its contents. - -[!code-csharp[SqlCommand_BeginExecuteXmlReader#1]((~/../sqlclient/doc/samples/SqlCommand_BeginExecuteXmlReader.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An - - delegate that is invoked when the command's execution has completed. Pass - - ( - - in Microsoft Visual Basic) to indicate that no callback is required. - - - A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the - - property. - - - Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this - - and returns results as an - - object, using a callback procedure. - - - An - - that can be used to poll, wait for results, or both; this value is also needed when the - - is called, which returns the results of the command as XML. - - - method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows as XML, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the requested XML data. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. - -The property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, `CommandText` can also specify a statement that returns data that contains valid XML. This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. - -A typical query can be formatted as in the following C# example: - -```csharp -SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM Contact FOR XML AUTO, XMLDATA", SqlConn); -``` - -This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. - -The multiple active result set (MARS) feature lets multiple actions use the same connection. - -The `callback` parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the `stateObject` parameter, and your callback procedure can retrieve this information using the property. - -Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters is sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. - -All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -This method ignores the property. - - -## Examples -The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). This example passes the executing object as the `stateObject` parameter--doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . - -This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. - -To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. - -[!code-csharp[SqlCommand_BeginExecuteXmlReaderAsync](~/../sqlclient/doc/samples/SqlCommand_BeginExecuteXmlReaderAsync.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Any error that occurred while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - or - - - - is set to true and a parameter with direction Output or InputOutput has been added to the collection. - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - - - Tries to cancel the execution of a - - . - - - , then call (implicitly or explicitly) before calling , and then call , the cancel command will not be sent to SQL Server and the result set can continue to stream after you call . To avoid this, make sure that you call before closing the reader or connection. - - -## Examples -The following example demonstrates the use of the method. - -[!code-csharp[SqlCommand_Cancel](~/../sqlclient/doc/samples/SqlCommand_Cancel.cs)] -]]> - - - - - Creates a new - - object that is a copy of the current instance. - - - A new - - object that is a copy of this instance. - - - To be added. - - - - - Gets the column encryption setting for this command. - - - The column encryption setting for this command. - - - - - Gets or sets the Transact-SQL statement, table name or stored procedure to execute at the data source. - - - The Transact-SQL statement or stored procedure to execute. The default is an empty string. - - - property is set to `StoredProcedure`, the property should be set to the name of the stored procedure. The user may be required to use escape character syntax if the stored procedure name contains any special characters. The command executes this stored procedure when you call one of the `Execute` methods. - -The Microsoft .NET Framework Data Provider for SQL Server does not support the question mark (?) placeholder for passing parameters to a Transact-SQL statement or a stored procedure called by a command of `CommandType.Text`. In this case, named parameters must be used. For example: - -```sql -SELECT * FROM dbo.Customers WHERE CustomerID = @CustomerID -``` - -For more information, see [Configuring parameters](/sql/connect/ado-net/configure-parameters). - -## Examples -The following example creates a and sets some of its properties. - -[!code-csharp[SqlCommand_CommandText](~/../sqlclient/doc/samples/SqlCommand_CommandText.cs)] -]]> - - - - - Gets or sets the wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. - - - The time in seconds to wait for the command to execute. The default is 30 seconds. - - - [!NOTE] -> The property will be ignored during old-style asynchronous method calls such as . It will be honored by the newer async methods such as . - -> [!NOTE] -> This property is the cumulative time-out (for all network packets that are read during the invocation of a method) for all network reads during command execution or processing of the results. A time-out can still occur after the first row is returned, and does not include user processing time, only network read time. - -For example, with a 30 second time out, if requires two network packets, then it has 30 seconds to read both network packets. If you call again, it will have another 30 seconds to read any data that it requires. - -[!code-csharp[SqlCommand CommandTimeout](~/../sqlclient/doc/samples/SqlCommand_CommandTimeout.cs)] -]]> - - The value set is less than 0. - - - - Gets or sets a value indicating how the - - property is to be interpreted. - - - One of the - - values. The default is - - . - - - property to `StoredProcedure`, you should set the property to the name of the stored procedure. The command executes this stored procedure when you call one of the Execute methods. - -The Microsoft .NET Framework Data Provider for SQL Server does not support the question mark (?) placeholder for passing parameters to a SQL Statement or a stored procedure called with a of . In this case, named parameters must be used. For example: - -SELECT * FROM Customers WHERE CustomerID = @CustomerID - -For more information, see [Configuring parameters](/sql/connect/ado-net/configure-parameters). - -## Examples -The following example creates a and sets some of its properties. - -[!code-csharp[IDbCommand_CommandTimeout](~/../sqlclient/doc/samples/IDbCommand_CommandTimeout.cs)] -]]> - - - - - Gets or sets the - - used by this instance of the - - . - - - The connection to a data source. The default value is - - . - - - . - -If the property is not null and the transaction has already been committed or rolled back, is set to null. - - - -## Examples -The following example creates a and sets some of its properties. - -[!code-csharp[SqlCommand_Connection](~/../sqlclient/doc/samples/SqlCommand_Connection.cs)] -]]> - - - The - - property was changed while the command was enlisted in a transaction. - - - - - To be added. - - - To be added. - - - To be added. - - - - - Creates a new instance of a - - object. - - - A - - object. - - - method is a strongly-typed version of . -]]> - - - - - To be added. - - - To be added. - - - To be added. - - - - - To be added. - - - To be added. - - - To be added. - - - - - To be added. - - - To be added. - - - To be added. - - - - - Gets or sets a value indicating whether the command object should be visible in a Windows Form Designer control. - - - A value indicating whether the command object should be visible in a control. The default is - - . - - - To be added. - - - - - To be added. - - - To be added. - - - To be added. - - + + + + Represents a Transact-SQL statement or stored procedure to execute against a SQL Server database. This class cannot be inherited. + + + + When an instance of is created, the read/write properties are set to their initial values. For a list of these values, see the constructor. + + + features the following methods for executing commands at a SQL Server database: + + + + Item + Description + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , generally executing commands such as INSERT, DELETE, UPDATE, and SET statements. Each call to must be paired with a call to which finishes the operation, typically on a separate thread. + + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and retrieves one or more results sets from the server. Each call to must be paired with a call to which finishes the operation, typically on a separate thread. + + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this . Each call to must be paired with a call to , which finishes the operation, typically on a separate thread, and returns an object. + + + + + + Executes commands that return rows. For increased performance, invokes commands using the Transact-SQL sp_executesql system stored procedure. Therefore, might not have the effect that you want if used to execute commands such as Transact-SQL SET statements. + + + + + Executes commands such as Transact-SQL INSERT, DELETE, UPDATE, and SET statements. + + + + Retrieves a single value (for example, an aggregate value) from a database. + + + + + Sends the to the and builds an object. + + + + + + You can reset the property and reuse the object. However, you must close the before you can execute a new or previous command. + + + If a is generated by the method executing a , the remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. + + + + Nameless, also called ordinal, parameters are not supported by the .NET Framework Data Provider for SQL Server. + + + + + + The following example creates a , a , and a . The example reads through the data, writing it to the console. Finally, the example closes the and then the as it exits the using code blocks. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlCommandCs + { + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + ReadOrderData(str); + } + + private static void ReadOrderData(string connectionString) + { + string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + connection.Open(); + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1])); + } + } + } + } + } + } + + + + The following sample shows how to create and execute different types of SqlCommand objects. + + + + USE [master] + GO + + CREATE DATABASE [MySchool] + GO + + USE [MySchool] + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + CREATE procedure [dbo].[CourseExtInfo] @CourseId int + as + select c.CourseID,c.Title,c.Credits,d.Name as DepartmentName + from Course as c left outer join Department as d on c.DepartmentID=d.DepartmentID + where c.CourseID=@CourseId + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + create procedure [dbo].[DepartmentInfo] @DepartmentId int,@CourseCount int output + as + select @CourseCount=Count(c.CourseID) + from course as c + where c.DepartmentID=@DepartmentId + + select d.DepartmentID,d.Name,d.Budget,d.StartDate,d.Administrator + from Department as d + where d.DepartmentID=@DepartmentId + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + Create PROCEDURE [dbo].[GetDepartmentsOfSpecifiedYear] + @Year int,@BudgetSum money output + AS + BEGIN + SELECT @BudgetSum=SUM([Budget]) + FROM [MySchool].[dbo].[Department] + Where YEAR([StartDate])=@Year + + SELECT [DepartmentID] + ,[Name] + ,[Budget] + ,[StartDate] + ,[Administrator] + FROM [MySchool].[dbo].[Department] + Where YEAR([StartDate])=@Year + + END + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + CREATE TABLE [dbo].[Course]([CourseID] [nvarchar](10) NOT NULL, + [Year] [smallint] NOT NULL, + [Title] [nvarchar](100) NOT NULL, + [Credits] [int] NOT NULL, + [DepartmentID] [int] NOT NULL, + CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED + ( + [CourseID] ASC, + [Year] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + CREATE TABLE [dbo].[Department]([DepartmentID] [int] IDENTITY(1,1) NOT NULL, + [Name] [nvarchar](50) NOT NULL, + [Budget] [money] NOT NULL, + [StartDate] [datetime] NOT NULL, + [Administrator] [int] NULL, + CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED + ( + [DepartmentID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + CREATE TABLE [dbo].[Person]([PersonID] [int] IDENTITY(1,1) NOT NULL, + [LastName] [nvarchar](50) NOT NULL, + [FirstName] [nvarchar](50) NOT NULL, + [HireDate] [datetime] NULL, + [EnrollmentDate] [datetime] NULL, + CONSTRAINT [PK_School.Student] PRIMARY KEY CLUSTERED + ( + [PersonID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + CREATE TABLE [dbo].[StudentGrade]([EnrollmentID] [int] IDENTITY(1,1) NOT NULL, + [CourseID] [nvarchar](10) NOT NULL, + [StudentID] [int] NOT NULL, + [Grade] [decimal](3, 2) NOT NULL, + CONSTRAINT [PK_StudentGrade] PRIMARY KEY CLUSTERED + ( + [EnrollmentID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] + + GO + + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO + create view [dbo].[EnglishCourse] + as + select c.CourseID,c.Title,c.Credits,c.DepartmentID + from Course as c join Department as d on c.DepartmentID=d.DepartmentID + where d.Name=N'English' + + GO + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C1045', 2012, N'Calculus', 4, 7) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C1061', 2012, N'Physics', 4, 1) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C2021', 2012, N'Composition', 3, 2) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C2042', 2012, N'Literature', 4, 2) + SET IDENTITY_INSERT [dbo].[Department] ON + + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (1, N'Engineering', 350000.0000, CAST(0x0000999C00000000 AS DateTime), 2) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (2, N'English', 120000.0000, CAST(0x0000999C00000000 AS DateTime), 6) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (4, N'Economics', 200000.0000, CAST(0x0000999C00000000 AS DateTime), 4) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (7, N'Mathematics', 250024.0000, CAST(0x0000999C00000000 AS DateTime), 3) + SET IDENTITY_INSERT [dbo].[Department] OFF + SET IDENTITY_INSERT [dbo].[Person] ON + + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (1, N'Hu', N'Nan', NULL, CAST(0x0000A0BF00000000 AS DateTime)) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (2, N'Norman', N'Laura', NULL, CAST(0x0000A0BF00000000 AS DateTime)) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (3, N'Olivotto', N'Nino', NULL, CAST(0x0000A0BF00000000 AS DateTime)) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (4, N'Anand', N'Arturo', NULL, CAST(0x0000A0BF00000000 AS DateTime)) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (5, N'Jai', N'Damien', NULL, CAST(0x0000A0BF00000000 AS DateTime)) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (6, N'Holt', N'Roger', CAST(0x000097F100000000 AS DateTime), NULL) + INSERT [dbo].[Person] ([PersonID], [LastName], [FirstName], [HireDate], [EnrollmentDate]) VALUES (7, N'Martin', N'Randall', CAST(0x00008B1A00000000 AS DateTime), NULL) + SET IDENTITY_INSERT [dbo].[Person] OFF + SET IDENTITY_INSERT [dbo].[StudentGrade] ON + + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (1, N'C1045', 1, CAST(3.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (2, N'C1045', 2, CAST(3.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (3, N'C1045', 3, CAST(2.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (4, N'C1045', 4, CAST(4.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (5, N'C1045', 5, CAST(3.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (6, N'C1061', 1, CAST(4.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (7, N'C1061', 3, CAST(3.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (8, N'C1061', 4, CAST(2.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (9, N'C1061', 5, CAST(1.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (10, N'C2021', 1, CAST(2.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (11, N'C2021', 2, CAST(3.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (12, N'C2021', 4, CAST(3.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (13, N'C2021', 5, CAST(3.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (14, N'C2042', 1, CAST(2.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (15, N'C2042', 2, CAST(3.50 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (16, N'C2042', 3, CAST(4.00 AS Decimal(3, 2))) + INSERT [dbo].[StudentGrade] ([EnrollmentID], [CourseID], [StudentID], [Grade]) VALUES (17, N'C2042', 5, CAST(3.00 AS Decimal(3, 2))) + SET IDENTITY_INSERT [dbo].[StudentGrade] OFF + ALTER TABLE [dbo].[Course] WITH CHECK ADD CONSTRAINT [FK_Course_Department] FOREIGN KEY([DepartmentID]) + REFERENCES [dbo].[Department] ([DepartmentID]) + GO + ALTER TABLE [dbo].[Course] CHECK CONSTRAINT [FK_Course_Department] + GO + ALTER TABLE [dbo].[StudentGrade] WITH CHECK ADD CONSTRAINT [FK_StudentGrade_Student] FOREIGN KEY([StudentID]) + REFERENCES [dbo].[Person] ([PersonID]) + GO + ALTER TABLE [dbo].[StudentGrade] CHECK CONSTRAINT [FK_StudentGrade_Student] + GO + + + Next, compile and execute the following: + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Threading.Tasks; + + class Program + { + static class SqlHelper + { + // Set the connection, command, and then execute the command with non query. + public static Int32 ExecuteNonQuery(String connectionString, String commandText, + CommandType commandType, params SqlParameter[] parameters) + { + using (SqlConnection conn = new SqlConnection(connectionString)) + { + using (SqlCommand cmd = new SqlCommand(commandText, conn)) + { + // There are three command types: StoredProcedure, Text, TableDirect. The TableDirect + // type is only for OLE DB. + cmd.CommandType = commandType; + cmd.Parameters.AddRange(parameters); + + conn.Open(); + return cmd.ExecuteNonQuery(); + } + } + } + + // Set the connection, command, and then execute the command and only return one value. + public static Object ExecuteScalar(String connectionString, String commandText, + CommandType commandType, params SqlParameter[] parameters) + { + using (SqlConnection conn = new SqlConnection(connectionString)) + { + using (SqlCommand cmd = new SqlCommand(commandText, conn)) + { + cmd.CommandType = commandType; + cmd.Parameters.AddRange(parameters); + + conn.Open(); + return cmd.ExecuteScalar(); + } + } + } + + // Set the connection, command, and then execute the command with query and return the reader. + public static SqlDataReader ExecuteReader(String connectionString, String commandText, + CommandType commandType, params SqlParameter[] parameters) + { + SqlConnection conn = new SqlConnection(connectionString); + + using (SqlCommand cmd = new SqlCommand(commandText, conn)) + { + cmd.CommandType = commandType; + cmd.Parameters.AddRange(parameters); + + conn.Open(); + // When using CommandBehavior.CloseConnection, the connection will be closed when the + // IDataReader is closed. + SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); + + return reader; + } + } + } + + static void Main(string[] args) + { + String connectionString = "Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;"; + + CountCourses(connectionString, 2012); + Console.WriteLine(); + + Console.WriteLine("Following result is the departments that started from 2007:"); + GetDepartments(connectionString, 2007); + Console.WriteLine(); + + Console.WriteLine("Add the credits when the credits of course are lower than 4."); + AddCredits(connectionString, 4); + Console.WriteLine(); + + Console.WriteLine("Please press any key to exit..."); + Console.ReadKey(); + } + + static void CountCourses(String connectionString, Int32 year) + { + String commandText = "Select Count([CourseID]) FROM [MySchool].[dbo].[Course] Where Year=@Year"; + SqlParameter parameterYear = new SqlParameter("@Year", SqlDbType.Int); + parameterYear.Value = year; + + Object oValue = SqlHelper.ExecuteScalar(connectionString, commandText, CommandType.Text, parameterYear); + Int32 count; + if (Int32.TryParse(oValue.ToString(), out count)) + { + Console.WriteLine("There {0} {1} course{2} in {3}.", count > 1 ? "are" : "is", count, count > 1 ? "s" : null, year); + } + } + + // Display the Departments that start from the specified year. + static void GetDepartments(String connectionString, Int32 year) + { + String commandText = "dbo.GetDepartmentsOfSpecifiedYear"; + + // Specify the year of StartDate + SqlParameter parameterYear = new SqlParameter("@Year", SqlDbType.Int); + parameterYear.Value = year; + + // When the direction of parameter is set as Output, you can get the value after + // executing the command. + SqlParameter parameterBudget = new SqlParameter("@BudgetSum", SqlDbType.Money); + parameterBudget.Direction = ParameterDirection.Output; + + using (SqlDataReader reader = SqlHelper.ExecuteReader(connectionString, commandText, + CommandType.StoredProcedure, parameterYear, parameterBudget)) + { + Console.WriteLine("{0,-20}{1,-20}{2,-20}{3,-20}", "Name", "Budget", "StartDate", + "Administrator"); + while (reader.Read()) + { + Console.WriteLine("{0,-20}{1,-20:C}{2,-20:d}{3,-20}", reader["Name"], + reader["Budget"], reader["StartDate"], reader["Administrator"]); + } + } + Console.WriteLine("{0,-20}{1,-20:C}", "Sum:", parameterBudget.Value); + } + + // If credits of course is lower than the certain value, the method will add the credits. + static void AddCredits(String connectionString, Int32 creditsLow) + { + String commandText = "Update [MySchool].[dbo].[Course] Set Credits=Credits+1 Where Credits<@Credits"; + + SqlParameter parameterCredits = new SqlParameter("@Credits", creditsLow); + + Int32 rows = SqlHelper.ExecuteNonQuery(connectionString, commandText, CommandType.Text, parameterCredits); + + Console.WriteLine("{0} row{1} {2} updated.", rows, rows > 1 ? "s" : null, rows > 1 ? "are" : "is"); + } + } + + + + + + Initializes a new instance of the class. + + + + The base constructor initializes all fields to their default values. The following table shows initial property values for an instance of . + + + + + Properties + Initial value + + + + empty string ("") + + + + 30 + + + + + + + + + + + + + You can change the value for any of these properties through a separate call to the property. + + + + + The following example creates a and sets the property. + + + + using System; + using System.Xml; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + + public void CreateSqlCommand() + { + SqlCommand command = new SqlCommand(); + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + } + } + + + + + + The text of the query. + + + Initializes a new instance of the class with the text of the query. + + + + When an instance of is created, the following read/write properties are set to initial values. + + + + + Properties + Initial value + + + + + + + + 30 + + + + + + + + + + + + + You can change the value for any of these properties through a separate call to the property. + + + + + The following example creates a , passing in the connection string and command text. + + + + using System; + using System.Xml; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + + public void CreateCommand() + { + string queryString = "SELECT * FROM Categories ORDER BY CategoryID"; + SqlCommand command = new SqlCommand(queryString); + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + } + } + + + + + + The text of the query. + + + A that represents the connection to an instance of SQL Server. + + + Initializes a new instance of the class with the text of the query and a . + + + + The following table shows initial property values for an instance of . + + + + + Properties + Initial value + + + + cmdText + + + + 30 + + + + + + + + + A new that is the value for the parameter. + + + + + + You can change the value for any of these parameters by setting the related property. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlCommandCS + { + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + + } + + private static void CreateCommand(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + connection.Open(); + SqlDataReader reader = command.ExecuteReader(); + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1])); + } + } + } + } + } + + + + + + The text of the query. + + + A that represents the connection to an instance of SQL Server. + + + The in which the executes. + + + Initializes a new instance of the class with the text of the query, a , and the . + + + + The following table shows initial property values for an instance of . + + + + + Properties + Initial value + + + + cmdText + + + + 30 + + + + + + + + + A new that is the value for the parameter. + + + + + + You can change the value for any of these parameters by setting the related property. + + + + + + The text of the query. + + + A that represents the connection to an instance of SQL Server. + + + The in which the executes. + + + The encryption setting. For more information, see Always Encrypted. + + + Initializes a new instance of the class with specified command text, connection, transaction, and encryption setting. + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this . + + + An that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns the number of affected rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that does not return rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server - that is, reads are asynchronous. + + + Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . + + + This method ignores the property. + + + + + The following console application creates updates data within the AdventureWorks sample database, doing its work asynchronously. In order to emulate a long-running process, this example inserts a WAITFOR statement in the command text. Normally, you would not take efforts to make your commands run slower, but doing this in this case makes it easier to demonstrate the asynchronous behavior. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Class1 + { + static void Main() + { + // This is a simple example that demonstrates the usage of the + // BeginExecuteNonQuery functionality. + // The WAITFOR statement simply adds enough time to prove the + // asynchronous nature of the command. + + string commandText = + "UPDATE Production.Product SET ReorderPoint = ReorderPoint + 1 " + + "WHERE ReorderPoint Is Not Null;" + + "WAITFOR DELAY '0:0:3';" + + "UPDATE Production.Product SET ReorderPoint = ReorderPoint - 1 " + + "WHERE ReorderPoint Is Not Null"; + + RunCommandAsynchronously(commandText, GetConnectionString()); + + Console.WriteLine("Press ENTER to continue."); + Console.ReadLine(); + } + + private static void RunCommandAsynchronously(string commandText, string connectionString) + { + // Given command text and connection string, asynchronously execute + // the specified command against the connection. For this example, + // the code displays an indicator as it is working, verifying the + // asynchronous behavior. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + try + { + int count = 0; + SqlCommand command = new SqlCommand(commandText, connection); + connection.Open(); + + IAsyncResult result = command.BeginExecuteNonQuery(); + while (!result.IsCompleted) + { + Console.WriteLine("Waiting ({0})", count++); + // Wait for 1/10 second, so the counter + // does not consume all available resources + // on the main thread. + System.Threading.Thread.Sleep(100); + } + + Console.WriteLine("Command complete. Affected {0} rows.", + command.EndExecuteNonQuery(result)); + } + catch (SqlException ex) + { + Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message); + } + catch (InvalidOperationException ex) + { + Console.WriteLine("Error: {0}", ex.Message); + } + catch (Exception ex) + { + // You might want to pass these errors + // back out to the caller. + Console.WriteLine("Error: {0}", ex.Message); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An delegate that is invoked when the command's execution has completed. Pass ( in Microsoft Visual Basic) to indicate that no callback is required. + + + A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the property. + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , given a callback procedure and state information. + + + An that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns the number of affected rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that does not return rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + The parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the parameter, and your callback procedure can retrieve this information using the property. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. + + + Because the callback procedure executes from within a background thread supplied by the Microsoft .NET common language runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure; should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. + + + All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. + + + This method ignores the property. + + + + + The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of several seconds (emulating a long-running command). + + + This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. + + + To set up this example, create a new Windows application. Put a control and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. + + + + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Text; + using System.Windows.Forms; + using Microsoft.Data.SqlClient; + + namespace Microsoft.AdoDotNet.CodeSamples + { + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + // Hook up the form's Load event handler (you can double-click on + // the form's design surface in Visual Studio), and then add + // this code to the form's class: + private void Form1_Load(object sender, EventArgs e) + { + this.button1.Click += new System.EventHandler(this.button1_Click); + this.FormClosing += new System.Windows.Forms. + FormClosingEventHandler(this.Form1_FormClosing); + } + + // You need this delegate in order to display text from a thread + // other than the form's thread. See the HandleCallback + // procedure for more information. + // This same delegate matches both the DisplayStatus + // and DisplayResults methods. + private delegate void DisplayInfoDelegate(string Text); + + // This flag ensures that the user does not attempt + // to restart the command or close the form while the + // asynchronous command is executing. + private bool isExecuting; + + // This example maintains the connection object + // externally, so that it is available for closing. + private SqlConnection connection; + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + + private void DisplayStatus(string Text) + { + this.label1.Text = Text; + } + + private void DisplayResults(string Text) + { + this.label1.Text = Text; + DisplayStatus("Ready"); + } + + private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, "Cannot close the form until " + + "the pending asynchronous command has completed. Please wait..."); + e.Cancel = true; + } + } + + private void button1_Click(object sender, System.EventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, + "Already executing. Please wait until the current query " + + "has completed."); + } + else + { + SqlCommand command = null; + try + { + DisplayResults(""); + DisplayStatus("Connecting..."); + connection = new SqlConnection(GetConnectionString()); + // To emulate a long-running query, wait for + // a few seconds before working with the data. + // This command does not do much, but that's the point-- + // it does not change your data, in the long run. + string commandText = + "WAITFOR DELAY '0:0:05';" + + "UPDATE Production.Product SET ReorderPoint = ReorderPoint + 1 " + + "WHERE ReorderPoint Is Not Null;" + + "UPDATE Production.Product SET ReorderPoint = ReorderPoint - 1 " + + "WHERE ReorderPoint Is Not Null"; + + command = new SqlCommand(commandText, connection); + connection.Open(); + + DisplayStatus("Executing..."); + isExecuting = true; + // Although it is not required that you pass the + // SqlCommand object as the second parameter in the + // BeginExecuteNonQuery call, doing so makes it easier + // to call EndExecuteNonQuery in the callback procedure. + AsyncCallback callback = new AsyncCallback(HandleCallback); + command.BeginExecuteNonQuery(callback, command); + + } + catch (Exception ex) + { + isExecuting = false; + DisplayStatus(string.Format("Ready (last error: {0})", ex.Message)); + if (connection != null) + { + connection.Close(); + } + } + } + } + + private void HandleCallback(IAsyncResult result) + { + try + { + // Retrieve the original command object, passed + // to this procedure in the AsyncState property + // of the IAsyncResult parameter. + SqlCommand command = (SqlCommand)result.AsyncState; + int rowCount = command.EndExecuteNonQuery(result); + string rowText = " rows affected."; + if (rowCount == 1) + { + rowText = " row affected."; + } + + rowText = rowCount + rowText; + + // You may not interact with the form and its contents + // from a different thread, and this callback procedure + // is all but guaranteed to be running from a different thread + // than the form. Therefore you cannot simply call code that + // displays the results, like this: + // DisplayResults(rowText) + + // Instead, you must call the procedure from the form's thread. + // One simple way to accomplish this is to call the Invoke + // method of the form, which calls the delegate you supply + // from the form's thread. + DisplayInfoDelegate del = new DisplayInfoDelegate(DisplayResults); + this.Invoke(del, rowText); + + } + catch (Exception ex) + { + // Because you are now running code in a separate thread, + // if you do not handle the exception here, none of your other + // code catches the exception. Because none of + // your code is on the call stack in this thread, there is nothing + // higher up the stack to catch the exception if you do not + // handle it here. You can either log the exception or + // invoke a delegate (as in the non-error case in this + // example) to display the error on the form. In no case + // can you simply display the error without executing a delegate + // as in the try block here. + + // You can create the delegate instance as you + // invoke it, like this: + this.Invoke(new DisplayInfoDelegate(DisplayStatus), + String.Format("Ready(last error: {0}", ex.Message)); + } + finally + { + isExecuting = false; + if (connection != null) + { + connection.Close(); + } + } + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , and retrieves one or more result sets from the server. + + + An that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns a instance that can be used to retrieve the returned rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server - that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. + + + Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following console application starts the process of retrieving a data reader asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. As soon as the process has completed, the code retrieves the and displays its contents. + + + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + One of the values, indicating options for statement execution and data retrieval. + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this using one of the values. + + + An that can be used to poll, wait for results, or both; this value is also needed when invoking , which returns a instance that can be used to retrieve the returned rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + The behavior parameter lets you specify options that control the behavior of the command and its connection. These values can be combined (using the programming language's OR operator); generally, developers use the CommandBehavior.CloseConnection value to make sure that the connection is closed by the runtime when the is closed. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server - that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. + + + Because this overload does not support a callback procedure, developers must either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . + + + If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following console application starts the process of retrieving a data reader asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. Once the process has completed, the code retrieves the and displays its contents. + + + This example also passes the and values in the behavior parameter, causing the connection to be closed with the returned is closed, and to optimize for a single row result. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Class1 + { + static void Main() + { + // This example is not terribly useful, but it proves a point. + // The WAITFOR statement simply adds enough time to prove the + // asynchronous nature of the command. + string commandText = "WAITFOR DELAY '00:00:03';" + + "SELECT ProductID, Name FROM Production.Product WHERE ListPrice < 100"; + + RunCommandAsynchronously(commandText, GetConnectionString()); + + Console.WriteLine("Press ENTER to continue."); + Console.ReadLine(); + } + + private static void RunCommandAsynchronously(string commandText, string connectionString) + { + // Given command text and connection string, asynchronously execute + // the specified command against the connection. For this example, + // the code displays an indicator as it is working, verifying the + // asynchronous behavior. + try + { + // The code does not need to handle closing the connection explicitly-- + // the use of the CommandBehavior.CloseConnection option takes care + // of that for you. + SqlConnection connection = new SqlConnection(connectionString); + SqlCommand command = new SqlCommand(commandText, connection); + + connection.Open(); + IAsyncResult result = command.BeginExecuteReader(CommandBehavior.CloseConnection); + + // Although it is not necessary, the following code + // displays a counter in the console window, indicating that + // the main thread is not blocked while awaiting the command + // results. + int count = 0; + while (!result.IsCompleted) + { + Console.WriteLine("Waiting ({0})", count++); + // Wait for 1/10 second, so the counter + // does not consume all available resources + // on the main thread. + System.Threading.Thread.Sleep(100); + } + + using (SqlDataReader reader = command.EndExecuteReader(result)) + { + DisplayResults(reader); + } + } + catch (SqlException ex) + { + Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message); + } + catch (InvalidOperationException ex) + { + Console.WriteLine("Error: {0}", ex.Message); + } + catch (Exception ex) + { + // You might want to pass these errors + // back out to the caller. + Console.WriteLine("Error: {0}", ex.Message); + } + } + + private static void DisplayResults(SqlDataReader reader) + { + // Display the data within the reader. + while (reader.Read()) + { + // Display all the columns. + for (int i = 0; i < reader.FieldCount; i++) + { + Console.Write("{0}\t", reader.GetValue(i)); + } + + Console.WriteLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An delegate that is invoked when the command's execution has completed. Pass ( in Microsoft Visual Basic) to indicate that no callback is required. + + + A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the property. + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and retrieves one or more result sets from the server, given a callback procedure and state information. + + + An that can be used to poll, wait for results, or both; this value is also needed when invoking , which returns a instance which can be used to retrieve the returned rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed cause the object to block until the execution is finished. + + + The parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the parameter, and your callback procedure can retrieve this information using the property. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. + + + Because the callback procedure executes from within a background thread supplied by the Microsoft .NET runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure; should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. + + + All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. + + + If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). Because the sample executes the command asynchronously, the form remains responsive while awaiting the results. This example passes the executing object as the parameter; doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . + + + This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. + + + To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Class1 + { + static void Main() + { + // This example is not terribly useful, but it proves a point. + // The WAITFOR statement simply adds enough time to prove the + // asynchronous nature of the command. + string commandText = "WAITFOR DELAY '00:00:03';" + + "SELECT ProductID, Name FROM Production.Product WHERE ListPrice < 100"; + + RunCommandAsynchronously(commandText, GetConnectionString()); + + Console.WriteLine("Press ENTER to continue."); + Console.ReadLine(); + } + + private static void RunCommandAsynchronously(string commandText, string connectionString) + { + // Given command text and connection string, asynchronously execute + // the specified command against the connection. For this example, + // the code displays an indicator as it is working, verifying the + // asynchronous behavior. + try + { + // The code does not need to handle closing the connection explicitly-- + // the use of the CommandBehavior.CloseConnection option takes care + // of that for you. + SqlConnection connection = new SqlConnection(connectionString); + SqlCommand command = new SqlCommand(commandText, connection); + + connection.Open(); + IAsyncResult result = command.BeginExecuteReader(CommandBehavior.CloseConnection); + + // Although it is not necessary, the following code + // displays a counter in the console window, indicating that + // the main thread is not blocked while awaiting the command + // results. + int count = 0; + while (!result.IsCompleted) + { + Console.WriteLine("Waiting ({0})", count++); + // Wait for 1/10 second, so the counter + // does not consume all available resources + // on the main thread. + System.Threading.Thread.Sleep(100); + } + + using (SqlDataReader reader = command.EndExecuteReader(result)) + { + DisplayResults(reader); + } + } + catch (SqlException ex) + { + Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message); + } + catch (InvalidOperationException ex) + { + Console.WriteLine("Error: {0}", ex.Message); + } + catch (Exception ex) + { + // You might want to pass these errors + // back out to the caller. + Console.WriteLine("Error: {0}", ex.Message); + } + } + + private static void DisplayResults(SqlDataReader reader) + { + // Display the data within the reader. + while (reader.Read()) + { + // Display all the columns. + for (int i = 0; i < reader.FieldCount; i++) + { + Console.Write("{0}\t", reader.GetValue(i)); + } + + Console.WriteLine(); + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + Any error that occurred while executing the command text. + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An delegate that is invoked when the command's execution has completed. Pass ( in Microsoft Visual Basic) to indicate that no callback is required. + + + A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the property. + + + One of the values, indicating options for statement execution and data retrieval. + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , using one of the values, and retrieving one or more result sets from the server, given a callback procedure and state information. + + + An that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns a instance which can be used to retrieve the returned rows. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + The parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the stateObject parameter, and your callback procedure can retrieve this information using the property. + + + The parameter lets you specify options that control the behavior of the command and its connection. These values can be combined together (using the programming language's Or operator); generally, developers use the CloseConnection value to make sure that the connection is closed by the runtime when the is closed. Developers can also optimize the behavior of the by specifying the SingleRow value when it is known in advance that the Transact-SQL statement or stored procedure only returns a single row. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. This means that calls to may block if more data is required and the underlying network's read operation blocks. + + + Because the callback procedure executes from within a background thread supplied by the Microsoft .NET common language runtime, it is very important that you take a rigorous approach to handling cross-thread interactions from within your applications. For example, you must not interact with a form's contents from within your callback procedure--should you have to update the form, you must switch back to the form's thread in order to do your work. The example in this topic demonstrates this behavior. + + + All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). Because the sample executes the command asynchronously, the form remains responsive while awaiting the results. This example passes the executing object as the stateObject parameter; doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . + + + This example demonstrates many important techniques. This includes calling a method that interacts with the form from a separate thread. In addition, this example demonstrates how you must block users from executing a command multiple times concurrently, and how you must make sure that the form does not close before the callback procedure is called. + + + To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. + + + This example passes the value in the parameter, causing the returned to automatically close its connection when it is closed. + + + + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Text; + using System.Windows.Forms; + using Microsoft.Data.SqlClient; + + namespace Microsoft.AdoDotNet.CodeSamples + { + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + // Hook up the form's Load event handler (you can double-click on + // the form's design surface in Visual Studio), and then add + // this code to the form's class: + // You need this delegate in order to fill the grid from + // a thread other than the form's thread. See the HandleCallback + // procedure for more information. + private delegate void FillGridDelegate(SqlDataReader reader); + + // You need this delegate to update the status bar. + private delegate void DisplayStatusDelegate(string Text); + + // This flag ensures that the user does not attempt + // to restart the command or close the form while the + // asynchronous command is executing. + private bool isExecuting; + + private void DisplayStatus(string Text) + { + this.label1.Text = Text; + } + + private void FillGrid(SqlDataReader reader) + { + try + { + DataTable table = new DataTable(); + table.Load(reader); + this.dataGridView1.DataSource = table; + DisplayStatus("Ready"); + } + catch (Exception ex) + { + // Because you are guaranteed this procedure + // is running from within the form's thread, + // it can directly interact with members of the form. + DisplayStatus(string.Format("Ready (last attempt failed: {0})", ex.Message)); + } + finally + { + // Closing the reader also closes the connection, + // because this reader was created using the + // CommandBehavior.CloseConnection value. + if (reader != null) + { + reader.Close(); + } + } + } + + private void HandleCallback(IAsyncResult result) + { + try + { + // Retrieve the original command object, passed + // to this procedure in the AsyncState property + // of the IAsyncResult parameter. + SqlCommand command = (SqlCommand)result.AsyncState; + SqlDataReader reader = command.EndExecuteReader(result); + + // You may not interact with the form and its contents + // from a different thread, and this callback procedure + // is all but guaranteed to be running from a different thread + // than the form. Therefore you cannot simply call code that + // fills the grid, like this: + // FillGrid(reader); + // Instead, you must call the procedure from the form's thread. + // One simple way to accomplish this is to call the Invoke + // method of the form, which calls the delegate you supply + // from the form's thread. + FillGridDelegate del = new FillGridDelegate(FillGrid); + this.Invoke(del, reader); + + // Do not close the reader here, because it is being used in + // a separate thread. Instead, have the procedure you have + // called close the reader once it is done with it. + } + catch (Exception ex) + { + // Because you are now running code in a separate thread, + // if you do not handle the exception here, none of your other + // code catches the exception. Because there is none of + // your code on the call stack in this thread, there is nothing + // higher up the stack to catch the exception if you do not + // handle it here. You can either log the exception or + // invoke a delegate (as in the non-error case in this + // example) to display the error on the form. In no case + // can you simply display the error without executing a delegate + // as in the try block here. + // You can create the delegate instance as you + // invoke it, like this: + this.Invoke(new DisplayStatusDelegate(DisplayStatus), "Error: " + ex.Message); + } + finally + { + isExecuting = false; + } + } + + private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + + private void button1_Click(object sender, System.EventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, + "Already executing. Please wait until the current query " + + "has completed."); + } + else + { + SqlCommand command = null; + SqlConnection connection = null; + try + { + DisplayStatus("Connecting..."); + connection = new SqlConnection(GetConnectionString()); + // To emulate a long-running query, wait for + // a few seconds before retrieving the real data. + command = new SqlCommand("WAITFOR DELAY '0:0:5';" + + "SELECT ProductID, Name, ListPrice, Weight FROM Production.Product", + connection); + connection.Open(); + + DisplayStatus("Executing..."); + isExecuting = true; + // Although it is not required that you pass the + // SqlCommand object as the second parameter in the + // BeginExecuteReader call, doing so makes it easier + // to call EndExecuteReader in the callback procedure. + AsyncCallback callback = new AsyncCallback(HandleCallback); + command.BeginExecuteReader(callback, command, + CommandBehavior.CloseConnection); + } + catch (Exception ex) + { + DisplayStatus("Error: " + ex.Message); + if (connection != null) + { + connection.Close(); + } + } + } + } + + private void Form1_Load(object sender, System.EventArgs e) + { + this.button1.Click += new System.EventHandler(this.button1_Click); + this.FormClosing += new FormClosingEventHandler(Form1_FormClosing); + } + + void Form1_FormClosing(object sender, FormClosingEventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, "Cannot close the form until " + + "the pending asynchronous command has completed. Please wait..."); + e.Cancel = true; + } + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and returns results as an object. + + + An that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns a single XML value. + + + + The method starts the process of asynchronously executing a Transact-SQL statement that returns rows as XML, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the XML returned by the command. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the EndExecuteXmlReader before the command's execution is completed causes the object to block until the execution is finished. + + + The property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, CommandText can also specify a statement that returns ntext data that contains valid XML. + + + A typical query can be formatted as in the following C# example: + + + + SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM dbo.Contact FOR XML AUTO, XMLDATA", SqlConn); + + + + This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. + + + The multiple active result set (MARS) feature lets multiple actions use the same connection. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters are sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. Although command execution is asynchronous, value fetching is still synchronous. + + + Because this overload does not support a callback procedure, developers need to either poll to determine whether the command has completed, using the property of the returned by the method; or wait for the completion of one or more commands using the property of the returned . + + + If you use or to access XML data, SQL Server returns any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following console application starts the process of retrieving XML data asynchronously. While waiting for the results, this simple application sits in a loop, investigating the property value. Once the process has completed, the code retrieves the XML and displays its contents. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Xml; + + class Class1 + { + static void Main() + { + // This example is not terribly effective, but it proves a point. + // The WAITFOR statement simply adds enough time to prove the + // asynchronous nature of the command. + string commandText = + "WAITFOR DELAY '00:00:03';" + + "SELECT Name, ListPrice FROM Production.Product " + + "WHERE ListPrice < 100 " + + "FOR XML AUTO, XMLDATA"; + + RunCommandAsynchronously(commandText, GetConnectionString()); + + Console.WriteLine("Press ENTER to continue."); + Console.ReadLine(); + } + + private static void RunCommandAsynchronously(string commandText, string connectionString) + { + // Given command text and connection string, asynchronously execute + // the specified command against the connection. For this example, + // the code displays an indicator as it is working, verifying the + // asynchronous behavior. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(commandText, connection); + + connection.Open(); + IAsyncResult result = command.BeginExecuteXmlReader(); + + // Although it is not necessary, the following procedure + // displays a counter in the console window, indicating that + // the main thread is not blocked while awaiting the command + // results. + int count = 0; + while (!result.IsCompleted) + { + Console.WriteLine("Waiting ({0})", count++); + // Wait for 1/10 second, so the counter + // does not consume all available resources + // on the main thread. + System.Threading.Thread.Sleep(100); + } + + XmlReader reader = command.EndExecuteXmlReader(result); + DisplayProductInfo(reader); + } + } + + private static void DisplayProductInfo(XmlReader reader) + { + // Display the data within the reader. + while (reader.Read()) + { + // Skip past items that are not from the correct table. + if (reader.LocalName.ToString() == "Production.Product") + { + Console.WriteLine("{0}: {1:C}", + reader["Name"], Convert.ToSingle(reader["ListPrice"])); + } + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An delegate that is invoked when the command's execution has completed. Pass ( in Microsoft Visual Basic) to indicate that no callback is required. + + + A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback procedure using the property. + + + Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and returns results as an object, using a callback procedure. + + + An that can be used to poll, wait for results, or both; this value is also needed when the is called, which returns the results of the command as XML. + + + + The method starts the process of asynchronously executing a Transact-SQL statement or stored procedure that returns rows as XML, so that other tasks can run concurrently while the statement is executing. When the statement has completed, developers must call the method to finish the operation and retrieve the requested XML data. The method returns immediately, but until the code executes the corresponding method call, it must not execute any other calls that start a synchronous or asynchronous execution against the same object. Calling the before the command's execution is completed causes the object to block until the execution is finished. + + + The property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, can also specify a statement that returns data that contains valid XML. This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. + + + A typical query can be formatted as in the following C# example: + + + + SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM Contact FOR XML AUTO, XMLDATA", SqlConn); + + + + This method can also be used to retrieve a single-row, single-column result set. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. + + + The multiple active result set (MARS) feature lets multiple actions use the same connection. + + + The parameter lets you specify an delegate that is called when the statement has completed. You can call the method from within this delegate procedure, or from any other location within your application. In addition, you can pass any object in the stateObject parameter, and your callback procedure can retrieve this information using the property. + + + Note that the command text and parameters are sent to the server synchronously. If a large command or many parameters is sent, this method may block during writes. After the command is sent, the method returns immediately without waiting for an answer from the server--that is, reads are asynchronous. + + + All errors that occur during the execution of the operation are thrown as exceptions in the callback procedure. You must handle the exception in the callback procedure, not in the main application. See the example in this topic for additional information on handling exceptions in the callback procedure. + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + This method ignores the property. + + + + + The following Windows application demonstrates the use of the method, executing a Transact-SQL statement that includes a delay of a few seconds (emulating a long-running command). This example passes the executing object as the parameter--doing so makes it simple to retrieve the object from within the callback procedure, so that the code can call the method corresponding to the initial call to . + + + To set up this example, create a new Windows application. Put a control, a control, and a control on the form (accepting the default name for each control). Add the following code to the form's class, modifying the connection string as needed for your environment. + + + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Text; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + namespace Microsoft.AdoDotNet.CodeSamples + { + public partial class Form1 : Form + { + // Hook up the form's Load event handler and then add + // this code to the form's class: + // You need these delegates in order to display text from a thread + // other than the form's thread. See the HandleCallback + // procedure for more information. + private delegate void DisplayInfoDelegate(string Text); + private delegate void DisplayReaderDelegate(XmlReader reader); + + private bool isExecuting; + + // This example maintains the connection object + // externally, so that it is available for closing. + private SqlConnection connection; + + public Form1() + { + InitializeComponent(); + } + + private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=true;" + + "Initial Catalog=AdventureWorks"; + } + + private void DisplayStatus(string Text) + { + this.label1.Text = Text; + } + + private void ClearProductInfo() + { + // Clear the list box. + this.listBox1.Items.Clear(); + } + + private void DisplayProductInfo(XmlReader reader) + { + // Display the data within the reader. + while (reader.Read()) + { + // Skip past items that are not from the correct table. + if (reader.LocalName.ToString() == "Production.Product") + { + this.listBox1.Items.Add(String.Format("{0}: {1:C}", + reader["Name"], Convert.ToDecimal(reader["ListPrice"]))); + } + } + DisplayStatus("Ready"); + } + + private void Form1_FormClosing(object sender, + System.Windows.Forms.FormClosingEventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, "Cannot close the form until " + + "the pending asynchronous command has completed. Please wait..."); + e.Cancel = true; + } + } + + private void button1_Click(object sender, System.EventArgs e) + { + if (isExecuting) + { + MessageBox.Show(this, + "Already executing. Please wait until the current query " + + "has completed."); + } + else + { + SqlCommand command = null; + try + { + ClearProductInfo(); + DisplayStatus("Connecting..."); + connection = new SqlConnection(GetConnectionString()); + + // To emulate a long-running query, wait for + // a few seconds before working with the data. + string commandText = + "WAITFOR DELAY '00:00:03';" + + "SELECT Name, ListPrice FROM Production.Product " + + "WHERE ListPrice < 100 " + + "FOR XML AUTO, XMLDATA"; + + command = new SqlCommand(commandText, connection); + connection.Open(); + + DisplayStatus("Executing..."); + isExecuting = true; + // Although it is not required that you pass the + // SqlCommand object as the second parameter in the + // BeginExecuteXmlReader call, doing so makes it easier + // to call EndExecuteXmlReader in the callback procedure. + AsyncCallback callback = new AsyncCallback(HandleCallback); + command.BeginExecuteXmlReader(callback, command); + + } + catch (Exception ex) + { + isExecuting = false; + DisplayStatus(string.Format("Ready (last error: {0})", ex.Message)); + if (connection != null) + { + connection.Close(); + } + } + } + } + + private void HandleCallback(IAsyncResult result) + { + try + { + // Retrieve the original command object, passed + // to this procedure in the AsyncState property + // of the IAsyncResult parameter. + SqlCommand command = (SqlCommand)result.AsyncState; + XmlReader reader = command.EndExecuteXmlReader(result); + + // You may not interact with the form and its contents + // from a different thread, and this callback procedure + // is all but guaranteed to be running from a different thread + // than the form. + + // Instead, you must call the procedure from the form's thread. + // One simple way to accomplish this is to call the Invoke + // method of the form, which calls the delegate you supply + // from the form's thread. + DisplayReaderDelegate del = new DisplayReaderDelegate(DisplayProductInfo); + this.Invoke(del, reader); + + } + catch (Exception ex) + { + // Because you are now running code in a separate thread, + // if you do not handle the exception here, none of your other + // code catches the exception. Because none of + // your code is on the call stack in this thread, there is nothing + // higher up the stack to catch the exception if you do not + // handle it here. You can either log the exception or + // invoke a delegate (as in the non-error case in this + // example) to display the error on the form. In no case + // can you simply display the error without executing a delegate + // as in the try block here. + + // You can create the delegate instance as you + // invoke it, like this: + this.Invoke(new DisplayInfoDelegate(DisplayStatus), + String.Format("Ready(last error: {0}", ex.Message)); + } + finally + { + isExecuting = false; + if (connection != null) + { + connection.Close(); + } + } + } + + private void Form1_Load(object sender, System.EventArgs e) + { + this.button1.Click += new System.EventHandler(this.button1_Click); + this.FormClosing += new System.Windows.Forms. + FormClosingEventHandler(this.Form1_FormClosing); + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Any error that occurred while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + is set to true and a parameter with direction Output or InputOutput has been added to the collection. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + Tries to cancel the execution of a . + + + + If there is nothing to cancel, nothing occurs. However, if there is a command in process, and the attempt to cancel fails, no exception is generated. + + + In some rare cases, if you call , then call (implicitly or explicitly) before calling , and then call , the cancel command will not be sent to SQL Server and the result set can continue to stream after you call . To avoid this, make sure that you call before closing the reader or connection. + + + + + The following example demonstrates the use of the method. + + + using System; + using System.Data; + using System.Threading; + using Microsoft.Data.SqlClient; + + class Program + { + private static SqlCommand m_rCommand; + + public static SqlCommand Command + { + get { return m_rCommand; } + set { m_rCommand = value; } + } + + public static void Thread_Cancel() + { + Command.Cancel(); + } + + static void Main() + { + string connectionString = GetConnectionString(); + try + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + Command = connection.CreateCommand(); + Command.CommandText = "DROP TABLE TestCancel"; + try + { + Command.ExecuteNonQuery(); + } + catch { } + + Command.CommandText = "CREATE TABLE TestCancel(co1 int, co2 char(10))"; + Command.ExecuteNonQuery(); + Command.CommandText = "INSERT INTO TestCancel VALUES (1, '1')"; + Command.ExecuteNonQuery(); + + Command.CommandText = "SELECT * FROM TestCancel"; + SqlDataReader reader = Command.ExecuteReader(); + + Thread rThread2 = new Thread(new ThreadStart(Thread_Cancel)); + rThread2.Start(); + rThread2.Join(); + + reader.Read(); + System.Console.WriteLine(reader.FieldCount); + reader.Close(); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + Creates a new object that is a copy of the current instance. + + + A new object that is a copy of this instance. + + + + + Gets the column encryption setting for this command. + + + The column encryption setting for this command. + + + + + Gets or sets the Transact-SQL statement, table name or stored procedure to execute at the data source. + + + The Transact-SQL statement or stored procedure to execute. The default is an empty string. + + + + When the property is set to , the property should be set to the name of the stored procedure. The user may be required to use escape character syntax if the stored procedure name contains any special characters. The command executes this stored procedure when you call one of the Execute* methods. + + + The Microsoft .NET Framework Data Provider for SQL Server does not support the question mark (?) placeholder for passing parameters to a Transact-SQL statement or a stored procedure called by a command of . In this case, named parameters must be used. For example: + + + + SELECT * FROM dbo.Customers WHERE CustomerID = @CustomerID + + + + For more information, see Configuring parameters. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + + public void CreateCommand() + { + SqlCommand command = new SqlCommand(); + command.CommandText = "SELECT * FROM Categories ORDER BY CategoryID"; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + } + } + + + + + + Gets or sets the wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. + + + The time in seconds to wait for the command to execute. The default is 30 seconds. + + + + A value of 0 indicates no limit (an attempt to execute a command will wait indefinitely). + + + + The property will be ignored during old-style asynchronous method calls such as . It will be honored by the newer async methods such as . + + + + + This property is the cumulative time-out (for all network packets that are read during the invocation of a method) for all network reads during command execution or processing of the results. A time-out can still occur after the first row is returned, and does not include user processing time, only network read time. + + + + For example, with a 30 second time out, if requires two network packets, then it has 30 seconds to read both network packets. If you call again, it will have another 30 seconds to read any data that it requires. + + + + + + using System; + using Microsoft.Data.SqlClient; + + public class A + { + public static void Main() + { + string connectionString = "<Your-connection-string-here>"; + + // Wait for 5 second delay in the command + string queryString = "waitfor delay '00:00:05'"; + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + SqlCommand command = new SqlCommand(queryString, connection); + // Setting command timeout to 1 second + command.CommandTimeout = 1; + try + { + command.ExecuteNonQuery(); + } + catch (SqlException e) + { + Console.WriteLine("Got expected SqlException due to command timeout "); + Console.WriteLine(e); + } + } + } + } + + + + The value set is less than 0. + + + + + Gets or sets a value indicating how the property is to be interpreted. + + + One of the values. The default is . + + + + When you set the property to , you should set the property to the name of the stored procedure. The command executes this stored procedure when you call one of the Execute methods. + + + The Microsoft .NET Framework Data Provider for SQL Server does not support the question mark (?) placeholder for passing parameters to a SQL Statement or a stored procedure called with a of . In this case, named parameters must be used. For example: + + + SELECT * FROM Customers WHERE CustomerID = @CustomerID + + + For more information, see Configuring parameters. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Xml; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + + public void CreateSqlCommand() + { + SqlCommand command = new SqlCommand(); + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + } + } + + + + + + Gets or sets the used by this instance of the . + + + The connection to a data source. The default value is . + + + + If the command is enlisted in an existing transaction, and the connection is changed, trying to execute the command will throw an . + + + If the property is not null and the transaction has already been committed or rolled back, is set to null. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + + namespace SqlCommandCS + { + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + } + + private static void CreateCommand(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection( + connectionString)) + { + SqlCommand command = new SqlCommand(); + command.Connection = connection; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + command.CommandText = queryString; + + connection.Open(); + SqlDataReader reader = command.ExecuteReader(); + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}, {1}", + reader[0], reader[1])); + } + } + } + } + } + + + + The property was changed while the command was enlisted in a transaction. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Creates a new instance of a object. + + + A object. + + + The method is a strongly-typed version of . + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets the collection of objects. + + + The parameters of the SQL statement or stored procedure. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets or sets a value indicating whether the command object should be visible in a Windows Form Designer control. + + + A value indicating whether the command object should be visible in a control. The default is . + + + + + To be added. + + + To be added. + + + To be added. + + - Gets or sets a value indicating whether the command object should optimize parameter performance by disabling Output and InputOutput directions when submitting the command to the SQL Server. + Gets or sets a value indicating whether the command object should optimize parameter performance by disabling Output and InputOutput directions when submitting the command to the SQL Server.
This option is only used when the is otherwise it is ignored. +
+ + A value indicating whether the command object should optimize parameter performance by disabling Output and InputOutput parameter directions when submitting the command to the SQL Server. The default is . + + + + You must set the value for this property before the command is executed for it to take effect. + + + When a command is submitted to the server with parameters a list of the parameter names is sent as part of the submission. The list is used on the server to match Output and InputOutput parameters to the results of the query execution so that the values can be returned to the caller. This option disables the construction and submission of the parameter name list and as a consequence disables the use of Output and InputOutput parameters. The return parameter is not affected by this option. + + + A command sent with this option changes the way parameters are handled on the server, because there is no need to maintain an output parameter map. The result of this change is that queries with large numbers of input parameters may execute much faster. + + + The fewest number of parameters where this will take effect depends on the individual situation and should be detected by measuring query duration with and without the option enabled. Any query with more than 24 parameters may show lower overall query duration. Queries with parameter counts lower than 24 are unlikely to show a difference. + + + + If the option is enabled and a parameter with Direction Output or InputOutput is present in the Parameters collection an InvalidOperationException will be thrown when the command is executed. + + + +
+ + + The returned by the call to . + + + Finishes asynchronous execution of a Transact-SQL statement. + + + The number of rows affected (the same behavior as ). + + + When you call to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. + + + For examples demonstrating the use of the method, see . + + + parameter is null ( in Microsoft Visual Basic) + + + was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called to complete execution of a call to . + + + + + The amount of time specified in elapsed and the asynchronous operation specified with is not complete. + + + In some situations, can set incorrectly. If this occurs and is called, EndExecuteNonQuery could raise a SqlException error if the amount of time specified in elapsed and the asynchronous operation specified with is not complete. To correct this situation, you should either increase the value of CommandTimeout or reduce the work being done by the asynchronous operation. + + + + + + + The returned by the call to . + + + Finishes asynchronous execution of a Transact-SQL statement, returning the requested . + + + A object that can be used to retrieve the requested rows. + + + When you call to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. + + + For examples demonstrating the use of the method, see . + + + parameter is null ( in Microsoft Visual Basic) + + + was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called to complete execution of a call to . + + + + + The returned by the call to . + + + Finishes asynchronous execution of a Transact-SQL statement, returning the requested data as XML. + + + An object that can be used to fetch the resulting XML data. + + + When you call to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. + + + For examples demonstrating the use of the method, see . + + + parameter is null ( in Microsoft Visual Basic) + + + was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called to complete execution of a call to . + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Executes a Transact-SQL statement against the connection and returns the number of rows affected. + + + The number of rows affected. + + + + You can use the to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database without using a by executing UPDATE, INSERT, or DELETE statements. + + + Although the returns no rows, any output parameters or return values mapped to parameters are populated with data. + + + For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. When SET NOCOUNT ON is set on the connection (before or as part of executing the command, or as part of a trigger initiated by the execution of the command) the rows affected by individual statements stop contributing to the count of rows affected that is returned by this method. If no statements are detected that contribute to the count, the return value is -1. If a rollback occurs, the return value is also -1. + + + + + The following example creates a and then executes it using . The example is passed a string that is a Transact-SQL statement (such as UPDATE, INSERT, or DELETE) and a string to use to connect to the data source. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlCommandCS + { + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + } + private static void CreateCommand(string queryString, + string connectionString) + { + using (SqlConnection connection = new SqlConnection( + connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + command.Connection.Open(); + command.ExecuteNonQuery(); + } + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The cancellation instruction. + + + An asynchronous version of , which executes a Transact-SQL statement against the connection and returns the number of rows affected. The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + For long-running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Sends the to the and builds a . + + + A object. + + + + When the property is set to , the property should be set to the name of the stored procedure. The command executes this stored procedure when you call . + + + If a transaction is deadlocked, an exception may not be thrown until is called. + + + The multiple active result set (MARS) feature allows for multiple actions using the same connection. + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + + + The following example creates a , and then executes it by passing a string that is a Transact-SQL SELECT statement, and a string to use to connect to the data source. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + } + + private static void CreateCommand(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = new SqlCommand(queryString, connection); + SqlDataReader reader = command.ExecuteReader(); + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}", reader[0])); + } + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + The current state of the connection is closed. requires an open . + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + One of the values. + + + Sends the to the , and builds a using one of the values. + + + A object. + + + + When the property is set to , the property should be set to the name of the stored procedure. The command executes this stored procedure when you call . + + + Use to retrieve large values and binary data. Otherwise, an might occur and the connection will be closed. + + + The multiple active result set (MARS) feature allows for multiple actions using the same connection. + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + + + The following example creates a , and then executes it by passing a string that is a Transact-SQL SELECT statement, and a string to use to connect to the data source. is set to . + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + } + + private static void CreateCommand(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + connection.Open(); + SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection); + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}", reader[0])); + } + } + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An asynchronous version of , which sends the to the and builds a . Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + For long-running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + An invalid value. + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Options for statement execution and data retrieval. When is set to , reads the entire row before returning a complete Task. + + + An asynchronous version of , which sends the to the , and builds a . Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + An invalid value. + + + + + Calling more than once for the same instance before task completion. + + + closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The cancellation instruction. + + + An asynchronous version of , which sends the to the and builds a . The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + An invalid value. + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Options for statement execution and data retrieval. When is set to , reads the entire row before returning a complete Task. + + + The cancellation instruction. + + + An asynchronous version of , which sends the to the , and builds a The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + An invalid value. + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. + + + The first column of the first row in the result set, or a null reference ( in Visual Basic) if the result set is empty. Returns a maximum of 2033 characters. + + + + Use the method to retrieve a single value (for example, an aggregate value) from a database. This requires less code than using the method, and then performing the operations that you need to generate the single value using the data returned by a . + + + + + A typical query can be formatted as in the following C# example: + + + cmd.CommandText = "SELECT COUNT(*) FROM dbo.region"; + Int32 count = (Int32) cmd.ExecuteScalar(); + + + + + The following example creates a and then executes it using . The example is passed a string representing a new value to be inserted into a table, and a string to use to connect to the data source. The function returns the new Identity column value if a new row was inserted, 0 on failure. > + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void CreateSqlCommand(string queryString, SqlConnection connection) + { + SqlCommand command = new SqlCommand(queryString, connection); + command.Connection.Open(); + command.ExecuteScalar(); + connection.Close(); + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The cancellation instruction. + + + An asynchronous version of , which executes the query asynchronously and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + For long-running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Sends the to the and builds an object. + + + An object. + + + + The returned by this method does not support asynchronous operations. The property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, can also specify a statement that returns ntext or nvarchar data that contains valid XML, or the contents of a column defined with the xml data type. + + + A typical query can be formatted as in the following Microsoft Visual C# example: + + + SqlCommand command = new SqlCommand("SELECT * FROM dbo.Customers FOR XML AUTO, XMLDATA", SqlConn); + + + This method can also be used to retrieve a single-row, single-column result set that contains XML data. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. + + + The multiple active result set (MARS) feature allows for multiple actions using the same connection. + + + If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. + + + + + The following example creates a and then executes it using . The example is passed a string that is a Transact-SQL FOR XML SELECT statement, and a string to use to connect to the data source. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + private static void CreateXMLReader(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + SqlCommand command = new SqlCommand(queryString, connection); + System.Xml.XmlReader reader = command.ExecuteXmlReader(); + } + } + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An asynchronous version of , which sends the to the and builds an object. + Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + + The returned by this method does not support asynchronous operations. For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + For long-running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. + + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + The cancellation instruction. + + + An asynchronous version of , which sends the to the and builds an object. The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + A task representing the asynchronous operation. + + + The returned by this method does not support asynchronous operations. For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + + A other than Binary or VarBinary was used when was set to . For more information about streaming, see SqlClient Streaming Support. + + + A other than Char, NChar, NVarChar, VarChar, or Xml was used when was set to . + + + A other than Xml was used when was set to . + + + + + + + Calling more than once for the same instance before task completion. + + + The closed or dropped during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + + + SQL Server returned an error while executing the command text. + + + A timeout occurred during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + An error occurred in a , or object during a streaming operation.For more information about streaming, see SqlClient Streaming Support. + + + The , or object was closed during a streaming operation. For more information about streaming, see SqlClient Streaming Support. + + + + + Gets or sets a value that specifies the object bound to this command. - A value indicating whether the command object should optimize parameter performance by disabling Output and InputOuput parameter directions when submitting the command to the SQL Server. - The default is . + When set to null (default), no notification should be requested. - - [!NOTE] -If the option is enabled and a parameter with Direction Output or InputOutput is present in the Parameters collection an InvalidOperationException will be thrown when the command is executed. - -]]> - + You must set the value for this property before the command is executed for it to take effect. - - - - The - - returned by the call to - - . - - - Finishes asynchronous execution of a Transact-SQL statement. - - - The number of rows affected (the same behavior as - - ). - - - to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. - -## Examples -For examples demonstrating the use of the method, see . -]]> - - - - parameter is null ( - - in Microsoft Visual Basic) - - - - was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called - - to complete execution of a call to - - . - - - The amount of time specified in - - elapsed and the asynchronous operation specified with - - is not complete. - - -or- - - In some situations, - - can be set to - - incorrectly. If this occurs and - - is called, EndExecuteNonQuery could raise a SqlException error if the amount of time specified in - - elapsed and the asynchronous operation specified with - - is not complete. To correct this situation, you should either increase the value of CommandTimeout or reduce the work being done by the asynchronous operation. - - - - - To be added. - - - To be added. - - - - - The - - returned by the call to - - . - - - Finishes asynchronous execution of a Transact-SQL statement, returning the requested - - . - - - A - - object that can be used to retrieve the requested rows. - - - to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. - - -## Examples -For examples demonstrating the use of the method, see . -]]> - - - - parameter is null ( - - in Microsoft Visual Basic) - - - - was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called - - to complete execution of a call to - - . - - - - - The - - returned by the call to - - . - - - Finishes asynchronous execution of a Transact-SQL statement, returning the requested data as XML. - - - An - - object that can be used to fetch the resulting XML data. - - - to execute a Transact-SQL statement, you must call in order to complete the operation. If the process of executing the command has not yet finished, this method blocks until the operation is complete. Users can verify that the command has completed its operation by using the instance returned by the method. If a callback procedure was specified in the call to , this method must be called. - -## Examples -For examples demonstrating the use of the method, see . -]]> - - - - parameter is null ( - - in Microsoft Visual Basic) - - - - was called more than once for a single command execution, or the method was mismatched against its execution method (for example, the code called - - to complete execution of a call to - - . - - - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - - - Executes a Transact-SQL statement against the connection and returns the number of rows affected. - - - The number of rows affected. - - - to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database without using a by executing UPDATE, INSERT, or DELETE statements. - -Although the returns no rows, any output parameters or return values mapped to parameters are populated with data. - -For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1. -When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. -When SET NOCOUNT ON is set on the connection (before or as part of executing the command, or as part of a trigger initiated by the execution of the command) the rows affected by individual statements stop contributing to the count of rows affected that is returned by this method. -If no statements are detected that contribute to the count, the return value is -1. If a rollback occurs, the return value is also -1. -## Examples -The following example creates a and then executes it using . The example is passed a string that is a Transact-SQL statement (such as UPDATE, INSERT, or DELETE) and a string to use to connect to the data source. - -[!code-csharp[SqlCommand_ExecuteNonQuery](~/../sqlclient/doc/samples/SqlCommand_ExecuteNonQuery.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - The cancellation instruction. - - - An asynchronous version of - - , which executes a Transact-SQL statement against the connection and returns the number of rows affected. The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - [!NOTE] -> For long running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. - - -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Sends the - - to the - - and builds a - - . - - - A - - object. - - - property is set to `StoredProcedure`, the property should be set to the name of the stored procedure. The command executes this stored procedure when you call . - -> [!NOTE] -> If a transaction is deadlocked, an exception may not be thrown until is called. - -The multiple active result set (MARS) feature allows for multiple actions using the same connection. - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - - -## Examples -The following example creates a , and then executes it by passing a string that is a Transact-SQL SELECT statement, and a string to use to connect to the data source. - -[!code-csharp[SqlCommand_ExecuteReader](~/../sqlclient/doc/samples/SqlCommand_ExecuteReader.cs)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The current state of the connection is closed. - - requires an open - - . - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - One of the - - values. - - - Sends the - - to the - - , and builds a - - using one of the - - values. - - - A - - object. - - - property is set to `StoredProcedure`, the property should be set to the name of the stored procedure. The command executes this stored procedure when you call . - -> [!NOTE] -> Use to retrieve large values and binary data. Otherwise, an might occur and the connection will be closed. - -The multiple active result set (MARS) feature allows for multiple actions using the same connection. - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -## Examples -The following example creates a , and then executes it by passing a string that is a Transact-SQL SELECT statement, and a string to use to connect to the data source. is set to . - -[!code-csharp[SqlCommand_ExecuteReader2](~/../sqlclient/doc/samples/SqlCommand_ExecuteReader2.cs#1)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An asynchronous version of - - , which sends the - - to the - - and builds a - - . Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - [!NOTE] -> For long running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. - -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An invalid - - value. - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Options for statement execution and data retrieval. When is set to - - , - - reads the entire row before returning a complete Task. - - - An asynchronous version of - - , which sends the - - to the - - , and builds a - - . Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An invalid - - value. - - - Calling - - more than once for the same instance before task completion. - - -or- - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - The cancellation instruction. - - - An asynchronous version of - - , which sends the - - to the - - and builds a - - . - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An invalid - - value. - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Options for statement execution and data retrieval. When is set to - - , - - reads the entire row before returning a complete Task. - - - The cancellation instruction. - - - An asynchronous version of - - , which sends the - - to the - - , and builds a - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An invalid - - value. - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. - - - The first column of the first row in the result set, or a null reference ( - - in Visual Basic) if the result set is empty. Returns a maximum of 2033 characters. - - - method to retrieve a single value (for example, an aggregate value) from a database. This requires less code than using the method, and then performing the operations that you need to generate the single value using the data returned by a . - -A typical query can be formatted as in the following C# example: - -```csharp -cmd.CommandText = "SELECT COUNT(*) FROM dbo.region"; -Int32 count = (Int32) cmd.ExecuteScalar(); -``` - -## Examples -The following example creates a and then executes it using . The example is passed a string representing a new value to be inserted into a table, and a string to use to connect to the data source. The function returns the new **Identity** column value if a new row was inserted, 0 on failure. - -[!code-csharp[SqlCommand.ExecuteScalar#1](~/../sqlclient/doc/samples/SqlCommand_ExecuteScalar.cs#1)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - The cancellation instruction. - - - An asynchronous version of - - , which executes the query asynchronously and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - [!NOTE] -> For long running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. - -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Sends the - - to the - - and builds an - - object. - - - An - - object. - - - property ordinarily specifies a Transact-SQL statement with a valid FOR XML clause. However, can also specify a statement that returns `ntext` or `nvarchar` data that contains valid XML, or the contents of a column defined with the `xml` data type. - -A typical query can be formatted as in the following Microsoft Visual C# example: - -```csharp -SqlCommand command = new SqlCommand("SELECT * FROM dbo.Customers FOR XML AUTO, XMLDATA", SqlConn); -``` - -This method can also be used to retrieve a single-row, single-column result set that contains XML data. In this case, if more than one row is returned, the method attaches the to the value on the first row, and discards the rest of the result set. - -The multiple active result set (MARS) feature allows for multiple actions using the same connection. - -If you use or to access XML data, SQL Server will return any XML results greater than 2,033 characters in length in multiple rows of 2,033 characters each. To avoid this behavior, use or to read FOR XML queries. - -## Examples -The following example creates a and then executes it using . The example is passed a string that is a Transact-SQL FOR XML SELECT statement, and a string to use to connect to the data source. - -[!code-csharp[SqlCommand_ExecuteXmlReader#1](~/../sqlclient/doc/samples/SqlCommand_ExecuteXmlReader.cs#1)] -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - An exception occurred while executing the command against a locked row. This exception is not generated when you are using Microsoft .NET Framework version 1.0. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - An asynchronous version of - - , which sends the - - to the - - and builds an - - object. - - Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - [!NOTE] -> For long running queries on the server, consider using due to a known issue with canceling queries via a cancellation token. Also, consider canceling execution using the method. - -]]> - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - The cancellation instruction. - - - An asynchronous version of - - , which sends the - - to the - - and builds an - - object. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - - A task representing the asynchronous operation. - - - - - - A - - other than **Binary** or **VarBinary** was used when - - was set to - - . For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - -or- - - A - - other than **Char**, **NChar**, **NVarChar**, **VarChar**, or **Xml** was used when - - was set to - - . - - -or- - - A - - other than **Xml** was used when - - was set to - - . - - - Calling - - more than once for the same instance before task completion. - - -or- - - The - - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - SQL Server returned an error while executing the command text. - - -or- - - A timeout occurred during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - An error occurred in a - - , - - or - - object during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - The - - , - - or - - object was closed during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - - - Gets or sets a value that specifies the - - object bound to this command. - - - When set to null (default), no notification should be requested. - - - - - - - Dictionary of custom column encryption key providers - Registers the encryption key store providers on the instance. If this function has been called, any providers registered using the or - methods will be ignored. This function can be called more than once. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. - - A null dictionary was provided. - - -or- - - A string key in the dictionary was null or empty. - - -or- - - A value in the dictionary was null. - - - A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. - - - - - - - - Gets or sets a value that specifies the - - object bound to this command. - - - When set to null (default), the default non-retriable provider will be used. - - - type. -2. Create a by using one of the following static methods of the class: - - - - - - - - -3. Assign the object to the `RetryLogicProvider` property. - -> [!NOTE] -> Detecting retriable exceptions is a vital part of the retry pattern. Before applying retry logic, it is important to investigate exceptions and choose a retry provider that best fits your scenario. First, log your exceptions and find transient faults. - -> [!NOTE] -> The command **timeout** restarts for each execution of a command within the retry logic and after applying the retry time delay. There is no timing overlap between these two actions. - -> [!NOTE] -> The default retry logic provider is not enabled unless it is configured in an application configuration file. For more information, see [Configurable retry logic configuration file](/sql/connect/ado-net/configurable-retry-logic-config-file-sqlclient). - -> [!CAUTION] -> A command with isn't compatible with the built-in retry logic. The underlying connection is immediately closed after the first execution attempt and is no longer available for subsequent retries. - -## Example -The following sample creates a database and establishes an active connection to it. While the database has an active connection, it tries to drop it with a new and a that uses a . You should kill the active connection through the database to unblock the second command before exceeding the number of retries. -The blocking connection simulates a situation like a command still running in the database and unlikely to finish. - -[!code-csharp[SqlConfigurableRetryLogic_SqlCommand#1](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_SqlCommand.cs#1)] - -### How to use with synchronous commands - -[!code-csharp[SqlConfigurableRetryLogic_SqlCommand#2](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_SqlCommand.cs#2)] - -### How to use with asynchoronous commands - -[!code-csharp[SqlConfigurableRetryLogic_SqlCommand#3](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_SqlCommand.cs#3)] - -### How to use with legacy asynchronous commands -Besides assigning the provider to the command and executing the command, it's possible to run it directly using the following methods: -- -- -- - -[!code-csharp[SqlConfigurableRetryLogic_SqlCommand#4](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_SqlCommand.cs#4)] - -> [!NOTE] -> The Asynchronous Programming Model (APM) is a legacy pattern that uses a pair of methods starting with `Begin` and `End`, and an interface called `IAsyncResult`. It's not recommended to use this pattern in new applications. These methods are for backwards compatibility. - -]]> - - - - - Gets or sets a value indicating whether the application should automatically receive query notifications from a common - - object. - - - - if the application should automatically receive query notifications; otherwise - - . The default value is - - . - - - - - - - - Gets the - - . - - - The parameters of the Transact-SQL statement or stored procedure. The default is an empty collection. - - - [!NOTE] -> If the parameters in the collection do not match the requirements of the query to be executed, an error may result. - -For more information, see [Configuring parameters](/sql/connect/ado-net/configure-parameters). - -## Examples -The following example demonstrates how to create a and add parameters to the . - -[!code-csharp[SqlParameterCollection.AddWithValue#1](~/../sqlclient/doc/samples/SqlParameterCollection_AddWithValue.cs#1)] -]]> - - - - - Creates a prepared version of the command on an instance of SQL Server. - - - is set to `StoredProcedure`, the call to should succeed, although it may cause a no-op. - -Before you call , specify the data type of each parameter in the statement to be prepared. For each parameter that has a variable length data type, you must set the property to the maximum size needed. returns an error if these conditions are not met. - -> [!NOTE] -> If the database context is changed by executing the Transact-SQL `USE ` statement, or by calling the method, then must be called a second time. - -If you call an `Execute` method after calling , any parameter value that is larger than the value specified by the property is automatically truncated to the original specified size of the parameter, and no truncation errors are returned. - -Output parameters (whether prepared or not) must have a user-specified data type. If you specify a variable length data type, you must also specify the maximum . - -Prior to Visual Studio 2010, threw an exception. Beginning in Visual Studio 2010, this method does not throw an exception. - -## Examples -The following example demonstrates the use of the method. - -[!code-csharp[SqlCommand.Prepare#1](~/../sqlclient/doc/samples/SqlCommand_Prepare.cs#1)] -]]> - - - - Resets the property to its default value. - - - is 30 seconds. -]]> - - - - - Occurs when the execution of a Transact-SQL statement completes. - - - To be added. - - - - - Creates a new instance of a object. - - - A object. - - - To be added. - - - - - Gets or sets the - - within which the - - executes. - - - The - - . The default value is - - . - - - property if it is already set to a specific value, and the command is in the process of executing. If you set the transaction property to a object that is not connected to the same as the object, an exception is thrown the next time that you attempt to execute a statement. -]]> - - - - - Gets or sets how command results are applied to the when used by the **Update** method of the . - - - One of the values. - - - value is **Both** unless the command is automatically generated (as in the case of the ), in which case the default is **None**. - -For more information about using the **UpdatedRowSource** property, see [DataAdapter Parameters](/sql/connect/ado-net/dataadapter-parameters). -]]> - - -
+ + + + Dictionary of custom column encryption key providers + + + Registers the encryption key store providers on the instance. If this function has been called, any providers registered using the or methods will be ignored. This function can be called more than once. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. + + + + Custom master key store providers can be registered with the driver at three different layers. The precedence of the three registrations is as follows: + + + The per-command registration will be checked if it is not empty. + If the per-command registration is empty, the per-connection registration will be checked if it is not empty. + If the per-connection registration is empty, the global registration will be checked. + + + Once any key store provider is found at a registration level, the driver will NOT fall back to the other registrations to search for a provider. If providers are registered but the proper provider is not found at a level, an exception will be thrown containing only the registered providers in the registration that was checked. + + + The built-in column master key store providers that are available for the Windows Certificate Store, CNG Store and CSP are pre-registered. + + + This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. + + + + + A null dictionary was provided. + A string key in the dictionary was null or empty. + + A value in the dictionary was null. + + + + + A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. + + + + + Gets or sets a value that specifies the object bound to this command. + + + When set to null (default), the default non-retryable provider will be used. + + + + You must set the value for this property before the command is executed for it to take effect. + + + To apply the retry logic, do the following steps before executing the command: + + + + Define the configuration parameters by using type. + + + Create a by using one of the following static methods of the class: + + + + + + + + + + + + + + + + + Assign the object to the RetryLogicProvider property. + + + + Detecting retryable exceptions is a vital part of the retry pattern. Before applying retry logic, it is important to investigate exceptions and choose a retry provider that best fits your scenario. First, log your exceptions and find transient faults. + + + The command timeout restarts for each execution of a command within the retry logic and after applying the retry time delay. There is no timing overlap between these two actions. + + + The default retry logic provider is not enabled unless it is configured in an application configuration file. For more information, see Configurable retry logic configuration file. + + + A command with isn't compatible with the built-in retry logic. The underlying connection is immediately closed after the first execution attempt and is no longer available for subsequent retries. + + + + + The following sample creates a database and establishes an active connection to it. While the database has an active connection, it tries to drop it with a new and a that uses a . You should kill the active connection through the database to unblock the second command before exceeding the number of retries. The blocking connection simulates a situation like a command still running in the database and unlikely to finish. + + + + /// Detecting retriable exceptions is a vital part of the retry pattern. + /// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario. + /// First, log your exceptions and find transient faults. + /// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic. + + private const string DefaultDB = "Northwind"; + private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;"; + private const string DropDatabaseFormat = "DROP DATABASE {0}"; + private const string CreateDatabaseFormat = "CREATE DATABASE {0}"; + + // For general use + private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB)); + + static void Main(string[] args) + { + // 1. Define the retry logic parameters + var options = new SqlRetryLogicOption() + { + NumberOfTries = 5, + MaxTimeInterval = TimeSpan.FromSeconds(20), + DeltaTime = TimeSpan.FromSeconds(1), + AuthorizedSqlCondition = null, + // error number 3702 : Cannot drop database "xxx" because it is currently in use. + TransientErrors = new int[] { 3702 } + }; + + // 2. Create a retry provider + var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options); + + // define the retrying event to report execution attempts + provider.Retrying += (object s, SqlRetryingEventArgs e) => + { + int attempts = e.RetryCount + 1; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n"); + Console.ForegroundColor = ConsoleColor.DarkGray; + if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex) + { + Console.WriteLine($"{ex.Number}-{ex.Message}\n"); + } + else + { + Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n"); + } + + // It is not good practice to do time-consuming tasks inside the retrying event which blocks the running task. + // Use parallel programming patterns to mitigate it. + if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1) + { + Console.WriteLine("This is the last chance to execute the command before throwing the exception."); + Console.WriteLine("Press Enter when you're ready:"); + Console.ReadLine(); + Console.WriteLine("continue ..."); + } + }; + + // Open a general connection. + s_generalConnection.Open(); + + try + { + // Assume the database is creating and other services are going to connect to it. + RetryCommand(provider); + } + catch + { + s_generalConnection.Close(); + // exception is thrown if connecting to the database isn't successful. + throw; + } + s_generalConnection.Close(); + } + + private static void ExecuteCommand(SqlConnection cn, string command) + { + using var cmd = cn.CreateCommand(); + cmd.CommandText = command; + cmd.ExecuteNonQuery(); + } + + private static void FindActiveSessions(SqlConnection cnn, string dbName) + { + using var cmd = cnn.CreateCommand(); + cmd.CommandText = "DECLARE @query NVARCHAR(max) = '';" + Environment.NewLine + + $"SELECT @query = @query + 'KILL ' + CAST(spid as varchar(50)) + ';' FROM sys.sysprocesses WHERE dbid = DB_ID('{dbName}')" + Environment.NewLine + + "SELECT @query AS Active_sessions;"; + var reader = cmd.ExecuteReader(); + if (reader.Read()) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.Write($">> Execute the '{reader.GetString(0)}' command in SQL Server to unblock the running task."); + Console.ResetColor(); + } + reader.Close(); + } + + + How to use with synchronous commands: + + + + private static void RetryCommand(SqlRetryLogicBaseProvider provider) + { + // Change this if you already have a database with the same name in your database. + string dbName = "RetryCommand_TestDatabase"; + + // Subscribe a new event on retry event and discover the active sessions on a database + EventHandler<SqlRetryingEventArgs> retryEvent = (object s, SqlRetryingEventArgs e) => + { + // Run just at first execution + if (e.RetryCount == 1) + { + FindActiveSessions(s_generalConnection, dbName); + Console.WriteLine($"Before exceeding {provider.RetryLogic.NumberOfTries} attempts."); + } + }; + + provider.Retrying += retryEvent; + + // Create a new database. + ExecuteCommand(s_generalConnection, string.Format(CreateDatabaseFormat, dbName)); + Console.WriteLine($"The '{dbName}' database is created."); + + // Open a connection to the newly created database to block it from being dropped. + using var blockingCnn = new SqlConnection(string.Format(CnnStringFormat, dbName)); + blockingCnn.Open(); + Console.WriteLine($"Established a connection to '{dbName}' to block it from being dropped."); + + Console.WriteLine($"Dropping `{dbName}`..."); + // Try to drop the new database. + RetryCommandSync(provider, dbName); + + Console.WriteLine("Command executed successfully."); + + provider.Retrying -= retryEvent; + } + + private static void RetryCommandSync(SqlRetryLogicBaseProvider provider, string dbName) + { + using var cmd = s_generalConnection.CreateCommand(); + cmd.CommandText = string.Format(DropDatabaseFormat, dbName); + // 3. Assign the `provider` to the command + cmd.RetryLogicProvider = provider; + Console.WriteLine("The first attempt, before getting into the retry logic."); + cmd.ExecuteNonQuery(); + } + + + How to use with asynchronous commands: + + + + private static void RetryCommand(SqlRetryLogicBaseProvider provider) + { + // Change this if you already have a database with the same name in your database. + string dbName = "RetryCommand_TestDatabase"; + + // Subscribe to the retry event and discover active sessions in a database + EventHandler<SqlRetryingEventArgs> retryEvent = (object s, SqlRetryingEventArgs e) => + { + // Run just at first execution + if (e.RetryCount == 1) + { + FindActiveSessions(s_generalConnection, dbName); + Console.WriteLine($"Before exceeding {provider.RetryLogic.NumberOfTries} attempts."); + } + }; + + provider.Retrying += retryEvent; + + // Create a new database. + ExecuteCommand(s_generalConnection, string.Format(CreateDatabaseFormat, dbName)); + Console.WriteLine($"The '{dbName}' database is created."); + + // Open a connection to the newly created database to block it from being dropped. + using var blockingCnn = new SqlConnection(string.Format(CnnStringFormat, dbName)); + blockingCnn.Open(); + Console.WriteLine($"Established a connection to '{dbName}' to block it from being dropped."); + + Console.WriteLine("Dropping the database..."); + // Try to drop the new database. + RetryCommandAsync(provider, dbName).Wait(); + + Console.WriteLine("Command executed successfully."); + + provider.Retrying -= retryEvent; + } + + private static async Task RetryCommandAsync(SqlRetryLogicBaseProvider provider, string dbName) + { + using var cmd = s_generalConnection.CreateCommand(); + cmd.CommandText = string.Format(DropDatabaseFormat, dbName); + // 3. Assign the `provider` to the command + cmd.RetryLogicProvider = provider; + Console.WriteLine("The first attempt, before getting into the retry logic."); + await cmd.ExecuteNonQueryAsync(); + } + + + How to use with legacy asynchronous commands: + + + Besides assigning the provider to the command and executing the command, it's possible to run it directly using the following methods: + + + + + + + + + + + + + + + private static void RetryCommand(SqlRetryLogicBaseProvider provider) + { + // Change this if you already have a database with the same name in your database. + string dbName = "RetryCommand_TestDatabase"; + + // Subscribe to the retry event and discover the active sessions in a database + EventHandler<SqlRetryingEventArgs> retryEvent = (object s, SqlRetryingEventArgs e) => + { + // Run just at first execution + if (e.RetryCount == 1) + { + FindActiveSessions(s_generalConnection, dbName); + Console.WriteLine($"Before exceeding {provider.RetryLogic.NumberOfTries} attempts."); + } + }; + + provider.Retrying += retryEvent; + + // Create a new database. + ExecuteCommand(s_generalConnection, string.Format(CreateDatabaseFormat, dbName)); + Console.WriteLine($"The '{dbName}' database is created."); + + // Open a connection to the newly created database to block it from being dropped. + using var blockingCnn = new SqlConnection(string.Format(CnnStringFormat, dbName)); + blockingCnn.Open(); + Console.WriteLine($"Established a connection to '{dbName}' to block it from being dropped."); + + Console.WriteLine("Dropping the database..."); + // Try to drop the new database. + RetryCommandBeginExecuteAsync(provider, dbName).Wait(); + + Console.WriteLine("Command executed successfully."); + + provider.Retrying -= retryEvent; + } + + private static async Task RetryCommandBeginExecuteAsync(SqlRetryLogicBaseProvider provider, string dbName) + { + using var cmd = s_generalConnection.CreateCommand(); + cmd.CommandText = string.Format(DropDatabaseFormat, dbName); + // Execute the BeginExecuteXXX and EndExecuteXXX functions by using Task.Factory.FromAsync(). + // Apply the retry logic by using the ExecuteAsync function of the configurable retry logic provider. + Console.WriteLine("The first attempt, before getting into the retry logic."); + await provider.ExecuteAsync(cmd, () => Task.Factory.FromAsync(cmd.BeginExecuteNonQuery(), cmd.EndExecuteNonQuery)); + } + + + + + + Gets or sets a value indicating whether the application should automatically receive query notifications from a common object. + + + if the application should automatically receive query notifications; otherwise . The default value is . + + + This feature is used in ASP.NET applications to receive notifications for all commands executed in an ASP page against SQL Server. This enables ASP.NET to cache the page until the queries used to render the page would produce a different result. Automatic enlistment. + + + This property applies only to versions of SQL Server that support query notifications. For earlier versions, setting this property to has no effect on the application. + + + + + + Gets the . + + + The parameters of the Transact-SQL statement or stored procedure. The default is an empty collection. + + + + The Microsoft .NET Framework Data Provider for SQL Server does not support the question mark (?) placeholder for passing parameters to a SQL Statement or a stored procedure called by a command of . In this case, named parameters must be used. For example: + + + SELECT * FROM Customers WHERE CustomerID = @CustomerID + + + If the parameters in the collection do not match the requirements of the query to be executed, an error may result. + + + For more information, see Configuring parameters. + + + + + The following example demonstrates how to create a and add parameters to the . + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + string demo = @"<StoreSurvey xmlns=""http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey""><AnnualSales>1500000</AnnualSales><AnnualRevenue>150000</AnnualRevenue><BankName>Primary International</BankName><BusinessType>OS</BusinessType><YearOpened>1974</YearOpened><Specialty>Road</Specialty><SquareFeet<38000</SquareFeet><Brands>3</Brands><Internet>DSL</Internet><NumberEmployees>40</NumberEmployees></StoreSurvey>"; + Int32 id = 3; + UpdateDemographics(id, demo, connectionString); + Console.ReadLine(); + } + private static void UpdateDemographics(Int32 customerID, + string demoXml, string connectionString) + { + // Update the demographics for a store, which is stored + // in an xml column. + string commandText = "UPDATE Sales.Store SET Demographics = @demographics " + + "WHERE CustomerID = @ID;"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(commandText, connection); + command.Parameters.Add("@ID", SqlDbType.Int); + command.Parameters["@ID"].Value = customerID; + + // Use AddWithValue to assign Demographics. + // SQL Server will implicitly convert strings into XML. + command.Parameters.AddWithValue("@demographics", demoXml); + + try + { + connection.Open(); + Int32 rowsAffected = command.ExecuteNonQuery(); + Console.WriteLine("RowsAffected: {0}", rowsAffected); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + Creates a prepared version of the command on an instance of SQL Server. + + + + If is set to , the call to should succeed, although it may cause a no-op. + + + Before you call , specify the data type of each parameter in the statement to be prepared. For each parameter that has a variable length data type, you must set the property to the maximum size needed. returns an error if these conditions are not met. + + + If the database context is changed by executing the Transact-SQL USE <database> statement, or by calling the method, then must be called a second time. + + + If you call an Execute* method after calling , any parameter value that is larger than the value specified by the property is automatically truncated to the original specified size of the parameter, and no truncation errors are returned. + + + Output parameters (whether prepared or not) must have a user-specified data type. If you specify a variable length data type, you must also specify the maximum . + + + Prior to Visual Studio 2010, threw an exception. Beginning in Visual Studio 2010, this method does not throw an exception. + + + + + The following example demonstrates the use of the method. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlPrepareCS + { + class Program + { + static void Main() + { + string connectionString = "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + SqlCommandPrepareEx(connectionString); + Console.ReadLine(); + + } + private static void SqlCommandPrepareEx(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + SqlCommand command = new SqlCommand(null, connection); + + // Create and prepare an SQL statement. + command.CommandText = + "INSERT INTO Region (RegionID, RegionDescription) " + + "VALUES (@id, @desc)"; + SqlParameter idParam = new SqlParameter("@id", SqlDbType.Int, 0); + SqlParameter descParam = new SqlParameter("@desc", SqlDbType.Text, 100); + idParam.Value = 20; + descParam.Value = "First Region"; + command.Parameters.Add(idParam); + command.Parameters.Add(descParam); + + // Call Prepare after setting the Commandtext and Parameters. + command.Prepare(); + command.ExecuteNonQuery(); + + // Change parameter values and call ExecuteNonQuery. + command.Parameters[0].Value = 21; + command.Parameters[1].Value = "Second Region"; + command.ExecuteNonQuery(); + } + } + } + } + + + + + + Resets the property to its default value. + + + The default value of the is 30 seconds. + + + + + Occurs when the execution of a Transact-SQL statement completes. + + + + + Gets or sets the within which the executes. + + + The . The default value is . + + + You cannot set the property if it is already set to a specific value, and the command is in the process of executing. If you set the transaction property to a object that is not connected to the same as the object, an exception is thrown the next time that you attempt to execute a statement. + + + + + Gets or sets how command results are applied to the when used by the Update method of the . + + + One of the values. + + + + The default value is unless the command is automatically generated (as in the case of the ), in which case the default is . + + + For more information about using the UpdatedRowSource property, see DataAdapter Parameters. + + + +
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommandBuilder.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommandBuilder.xml index 87ddd2c8b8..5cf4867488 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommandBuilder.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommandBuilder.xml @@ -1,439 +1,530 @@ - - - - - Automatically generates single-table commands that are used to reconcile changes made to a - - with the associated SQL Server database. This class cannot be inherited. - - - does not automatically generate the Transact-SQL statements required to reconcile changes made to a with the associated instance of SQL Server. However, you can create a object to automatically generate Transact-SQL statements for single-table updates if you set the property of the . Then, any additional Transact-SQL statements that you do not set are generated by the . - -The registers itself as a listener for events whenever you set the property. You can only associate one or object with each other at one time. - -To generate INSERT, UPDATE, or DELETE statements, the uses the property to retrieve a required set of metadata automatically. If you change the after the metadata has been retrieved, such as after the first update, you should call the method to update the metadata. - -The `SelectCommand` must also return at least one primary key or unique column. If none are present, an **InvalidOperation** exception is generated, and the commands are not generated. - -The also uses the , , and properties referenced by the . The user should call if one or more of these properties are modified, or if the itself is replaced. Otherwise the , , and properties retain their previous values. - -If you call , the is disassociated from the , and the generated commands are no longer used. - - -## Examples -The following example uses the , along and , to select rows from a data source. The example is passed a connection string, a query string that is a Transact-SQL SELECT statement, and a string that is the name of the database table. The example then creates a . - -[!code-csharp[SqlCommandBuilder#1](~/../sqlclient/doc/samples/SqlCommandBuilder.cs#1)] -]]> - - - - - Initializes a new instance of the - - class. - - - To be added. - - - - - The name of the - - . - - - Initializes a new instance of the - - class with the associated - - object. - - - registers itself as a listener for events that are generated by the specified in this property. - -When you create a new instance of , any existing associated with this is released. -]]> - - - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - To be added. - - - - - Sets or gets the - - for an instance of the - - class. - - - A - - object. - - - To be added. - - - - - Sets or gets a string used as the catalog separator for an instance of the - - class. - - - A string that indicates the catalog separator for use with an instance of the - - class. - - - To be added. - - - - Gets or sets a object for which Transact-SQL statements are automatically generated. - A object. - - registers itself as a listener for events that are generated by the specified in this property. - -When you create a new instance of , any existing associated with this is released. - -]]> - - - - The referencing the stored procedure from which the parameter information is to be derived. The derived parameters are added to the collection of the . - Retrieves parameter information from the stored procedure specified in the and populates the collection of the specified object. - - with arbitrary Transact-SQL statements, such as a parameterized SELECT statement. - -For more information, see [Configuring parameters](/sql/connect/ado-net/configure-parameters). - -]]> - - The command text is not a valid stored procedure name. - - - To be added. - To be added. - To be added. - - - Gets the automatically generated object required to perform deletions on the database. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - Gets the automatically generated object required to perform deletions on the database. - The automatically generated object required to perform deletions. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. - Gets the automatically generated object that is required to perform deletions on the database. - The automatically generated object that is required to perform deletions. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The SQL statements are first generated when the application calls either or . - -The default behavior, when generating parameter names, is to use `@p1`, `@p2`, and so on for the various parameters. Passing `true` for the `useColumnsForParameterNames` parameter lets you force the to generate parameters based on the column names instead. This succeeds only if the following conditions are met: - -- The returned from the **GetSchema** method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. - -- The generated parameter name meets the criteria specified in the returned from the **GetSchema** method call and found in the collection regular expression. - -- A returned from the **GetSchema** method call and found in the collection is specified. - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - Gets the automatically generated object that is required to perform insertions on the database. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - Gets the automatically generated object required to perform insertions on the database. - The automatically generated object required to perform insertions. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. - Gets the automatically generated object that is required to perform insertions on the database. - The automatically generated object that is required to perform insertions. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -The default behavior, when generating parameter names, is to use `@p1`, `@p2`, and so on for the various parameters. Passing `true` for the `useColumnsForParameterNames` parameter lets you force the to generate parameters based on the column names instead. This succeeds only if the following conditions are met: - -- The returned from the **GetSchema** method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. - -- The generated parameter name meets the criteria specified in the returned from the **GetSchema** method call and found in the collection regular expression. - -- A returned from the **GetSchema** method call and found in the collection is specified. - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - Gets the automatically generated object required to perform updates on the database. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - Gets the automatically generated object required to perform updates on the database. - The automatically generated object that is required to perform updates. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. - Gets the automatically generated object required to perform updates on the database. - The automatically generated object required to perform updates. - - method for informational or troubleshooting purposes because it returns the object to be executed. - -You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . - -After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . - -The default behavior, when generating parameter names, is to use `@p1`, `@p2`, and so on for the various parameters. Passing `true` for the `useColumnsForParameterNames` parameter lets you force the to generate parameters based on the column names instead. This succeeds only if the following conditions are met: - -- The returned from the **GetSchema** method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. - -- The generated parameter name meets the criteria specified in the returned from the **GetSchema** method call and found in the collection regular expression. - -- A returned from the **GetSchema** method call and found in the collection is specified. - -For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - -]]> - - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - Gets or sets the starting character or characters to use when specifying SQL Server database objects, such as tables or columns, whose names contain characters such as spaces or reserved tokens. - The starting character or characters to use. The default is an empty string. - - [!NOTE] -> Although you cannot change the or properties after an insert, update, or delete command has been generated, you can change their settings after calling the `Update` method of a DataAdapter. - -]]> - - This property cannot be changed after an INSERT, UPDATE, or DELETE command has been generated. - - - Gets or sets the ending character or characters to use when specifying SQL Server database objects, such as tables or columns, whose names contain characters such as spaces or reserved tokens. - The ending character or characters to use. The default is an empty string. - - [!NOTE] -> Although you cannot change the or properties after an insert, update, or delete operation has been generated, you can change their settings after calling the `Update` method of a DataAdapter. - -]]> - - This property cannot be changed after an insert, update, or delete command has been generated. - - - Clears the commands that are associated with this command builder. - To be added. - - - Gets or sets the character to be used for the separator between the schema identifier and any other identifiers. - The character to be used as the schema separator. - - - - - - To be added. - To be added. - To be added. - - - The identifier that will have its embedded quotes removed. - Given a quoted identifier, returns the correct unquoted form of that identifier. This includes correctly unescaping any embedded quotes in the identifier. - The unquoted identifier, with embedded quotes properly unescaped. - To be added. - Connecting and Retrieving Data in ADO.NET - Using the .NET Framework Data Provider for SQL Server - Overview of the SqlClient driver - - + + + + + Automatically generates single-table commands that are used to reconcile changes made to a with the associated SQL Server database. This class cannot be inherited. + + + + The does not automatically generate the Transact-SQL statements required to reconcile changes made to a with the associated instance of SQL Server. However, you can create a object to automatically generate Transact-SQL statements for single-table updates if you set the property of the . Then, any additional Transact-SQL statements that you do not set are generated by the . + + + The registers itself as a listener for events whenever you set the property. You can only associate one or object with each other at one time. + + + To generate INSERT, UPDATE, or DELETE statements, the uses the property to retrieve a required set of metadata automatically. If you change the after the metadata has been retrieved, such as after the first update, you should call the method to update the metadata. + + + The must also return at least one primary key or unique column. If none are present, an exception is generated, and the commands are not generated. + + + The also uses the , , and properties referenced by the . The user should call if one or more of these properties are modified, or if the itself is replaced. Otherwise the , , and properties retain their previous values. + + + If you call , the is disassociated from the , and the generated commands are no longer used. + + + + + The following example uses the , along and , to select rows from a data source. The example is passed a connection string, a query string that is a Transact-SQL SELECT statement, and a string that is the name of the database table. The example then creates a . + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlCommandBuilderCS + { + class Program + { + static void Main() + { + string cnnst = ""; + string queryst = ""; + string tablen = ""; + DataSet ds = SelectSqlRows(cnnst, queryst, tablen); + } + + public static DataSet SelectSqlRows(string connectionString, string queryString, string tableName) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + adapter.SelectCommand = new SqlCommand(queryString, connection); + SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + + connection.Open(); + + DataSet dataSet = new DataSet(); + adapter.Fill(dataSet, tableName); + + // code to modify data in DataSet here + + builder.GetUpdateCommand(); + + // Without the SqlCommandBuilder this line would fail + adapter.Update(dataSet, tableName); + + return dataSet; + } + } + } + } + + + + + + Initializes a new instance of the class. + + + + + The name of the . + + + Initializes a new instance of the class with the associated object. + + + + The registers itself as a listener for events that are generated by the specified in this property. + + + When you create a new instance of , any existing associated with this is released. + + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Sets or gets the for an instance of the class. + + + A object. + + + + + Sets or gets a string used as the catalog separator for an instance of the class. + + + A string that indicates the catalog separator for use with an instance of the class. + + + + + Gets or sets a object for which Transact-SQL statements are automatically generated. + + + A object. + + + + The registers itself as a listener for events that are generated by the specified in this property. + + + When you create a new instance of , any existing associated with this is released. + + + + + + The referencing the stored procedure from which the parameter information is to be derived. The derived parameters are added to the collection of the . + + + Retrieves parameter information from the stored procedure specified in the and populates the collection of the specified object. + + + + DeriveParameters overwrites any existing parameter information for the . + + + DeriveParameters requires an additional call to the database to obtain the information. If the parameter information is known in advance, it is more efficient to populate the parameters collection by setting the information explicitly. + + + You can only use DeriveParameters with stored procedures. You cannot use DeriveParameters with extended stored procedures. You cannot use DeriveParameters to populate the with arbitrary Transact-SQL statements, such as a parameterized SELECT statement. + + + For more information, see Configuring parameters. + + + + The command text is not a valid stored procedure name. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets the automatically generated object required to perform deletions on the database. + + + The automatically generated object required to perform deletions. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The SQL statements are first generated when the application calls either or . + + + For more information, see Generating Commands with CommandBuilders. + + + + + + If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. + + + Gets the automatically generated object that is required to perform deletions on the database. + + + The automatically generated object that is required to perform deletions. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The SQL statements are first generated when the application calls either or . + + + The default behavior, when generating parameter names, is to use @p1, @p2, and so on for the various parameters. Passing for the parameter lets you force the command builder to generate parameters based on the column names instead. This succeeds only if the following conditions are met: + + + + The returned from the GetSchema method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. + + + The generated parameter name meets the criteria specified in the returned from the GetSchema method call and found in the collection regular expression. + + + A returned from the GetSchema method call and found in the collection is specified. + + + + For more information, see Generating Commands with CommandBuilders. + + + + + + Gets the automatically generated object required to perform insertions on the database. + + + The automatically generated object required to perform insertions. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . + + + For more information, see Generating Commands with CommandBuilders. + + + + + + If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. + + + Gets the automatically generated object that is required to perform insertions on the database. + + + The automatically generated object that is required to perform insertions. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . + + + The default behavior, when generating parameter names, is to use @p1, @p2, and so on for the various parameters. Passing for the parameter lets you force the command builder to generate parameters based on the column names instead. This succeeds only if the following conditions are met: + + + + The returned from the GetSchema method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. + + + The generated parameter name meets the criteria specified in the returned from the GetSchema method call and found in the collection regular expression. + + + A returned from the GetSchema method call and found in the collection is specified. + + + + For more information, see Generating Commands with CommandBuilders. + + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Gets the automatically generated object required to perform updates on the database. + + + The automatically generated object that is required to perform updates. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . + + + For more information, see Generating Commands with CommandBuilders. + + + + + + If , generate parameter names matching column names if possible. If , generate @p1, @p2, and so on. + + + Gets the automatically generated object required to perform updates on the database. + + + The automatically generated object required to perform updates. + + + + An application can use the method for informational or troubleshooting purposes because it returns the object to be executed. + + + You can also use as the basis of a modified command. For example, you might call and modify the value, and then explicitly set that on the . + + + After the Transact-SQL statement is first generated, the application must explicitly call if it changes the statement in any way. Otherwise, the will still be using information from the previous statement, which might not be correct. The Transact-SQL statements are first generated when the application calls either or . + + + The default behavior, when generating parameter names, is to use @p1, @p2, and so on for the various parameters. Passing for the parameter lets you force the command builder to generate parameters based on the column names instead. This succeeds only if the following conditions are met: + + + + The returned from the GetSchema method call and found in the collection has been specified and its length is equal to or greater than the generated parameter name. + + + The generated parameter name meets the criteria specified in the returned from the GetSchema method call and found in the collection regular expression. + + + A returned from the GetSchema method call and found in the collection is specified. + + + + For more information, see Generating Commands with CommandBuilders. + + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Gets or sets the starting character or characters to use when specifying SQL Server database objects, such as tables or columns, whose names contain characters such as spaces or reserved tokens. + + + The starting character or characters to use. The default is an empty string. + + + + Although you cannot change the or properties after an insert, update, or delete command has been generated, you can change their settings after calling the Update method of a DataAdapter. + + + + This property cannot be changed after an INSERT, UPDATE, or DELETE command has been generated. + + + + + Gets or sets the ending character or characters to use when specifying SQL Server database objects, such as tables or columns, whose names contain characters such as spaces or reserved tokens. + + + The ending character or characters to use. The default is an empty string. + + + + Although you cannot change the or properties after an insert, update, or delete operation has been generated, you can change their settings after calling the Update method of a DataAdapter. + + + + This property cannot be changed after an insert, update, or delete command has been generated. + + + + + Gets or sets the character to be used for the separator between the schema identifier and any other identifiers. + + + The character to be used as the schema separator. + + + + Generally, database servers indicate the schema for a identifier by separating the schema name from the identifier with some character. For example, SQL Server uses a period, creating complete identifiers such as Person.CustomerName, where "Person" is the schema name and "CustomerName" is the identifier. Setting this property lets developers modify this behavior. + + + + + + To be added. + + + To be added. + + + To be added. + + + + + The identifier that will have its embedded quotes removed. + + + Given a quoted identifier, returns the correct unquoted form of that identifier. This includes correctly unescaping any embedded quotes in the identifier. + + + The unquoted identifier, with embedded quotes properly unescaped. + + + Connecting and Retrieving Data in ADO.NET + + + Using the .NET Framework Data Provider for SQL Server + + + Overview of the SqlClient driver + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommandColumnEncryptionSetting.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommandColumnEncryptionSetting.xml index 849c975612..ddd254827a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommandColumnEncryptionSetting.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommandColumnEncryptionSetting.xml @@ -1,29 +1,39 @@ - - - - Note that these settings cannot be used to bypass encryption and gain access to plaintext data. For details, see Always Encrypted (Database Engine). - - - - - - - Specifies the connection does not use Always Encrypted. Should be used if no queries sent over the connection access encrypted columns. - - - Enables Always Encrypted for the query. - - - Specifies that only the results of the command should be processed by the Always Encrypted routine in the driver. Use this value when the command has no parameters that require encryption. - - - Specifies that the command should default to the Always Encrypted setting in the connection string. - - + + + + + Note that these settings cannot be used to bypass encryption and gain access to plaintext data. For details, see Always Encrypted (Database Engine). + + + + + If Always Encrypted is disabled for a query and the query has parameters that need to be encrypted (parameters that correspond to encrypted columns), the query will fail. + + + If Always Encrypted is disabled for a query and the query returns results from encrypted columns, the query will return encrypted values. The encrypted values will have the varbinary datatype. + + + + + + + Specifies the connection does not use Always Encrypted. Should be used if no queries sent over the connection access encrypted columns. + + + + + Enables Always Encrypted for the query. + + + + + Specifies that only the results of the command should be processed by the Always Encrypted routine in the driver. Use this value when the command has no parameters that require encryption. + + + + + Specifies that the command should default to the Always Encrypted setting in the connection string. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConfigurableRetryFactory.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConfigurableRetryFactory.xml index cbeb9de0b1..c8c5513ea5 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConfigurableRetryFactory.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConfigurableRetryFactory.xml @@ -1,116 +1,250 @@ - - - - - Provides different retry logic providers with a common list of transient errors. - - - - - - - An object of containing the configuration for the object. - Provides an exponential time interval retry logic provider. - A object. - - [!NOTE] -> The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. - -]]> - - If the `retryLogicOption` parameter was null. - If at least one of the following conditions occurs: -- `NumberOfTries` is less than 1 or bigger than 60. -- `DeltaTime` is bigger than 120 seconds. -- `MinTimeInterval` is bigger than 120 seconds. -- `MaxTimeInterval` is bigger than 120 seconds. -- `MinTimeInterval` is not less than `MaxTimeInterval`. - - - - An object of containing the configuration for the object. - Provides an incremental time interval retry logic provider. - A object. - - [!NOTE] -> The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. - -]]> - - If the `retryLogicOption` parameter was null. - If at least one of the following conditions occurs: -- `NumberOfTries` is less than 1 or bigger than 60. -- `DeltaTime` is bigger than 120 seconds. -- `MinTimeInterval` is bigger than 120 seconds. -- `MaxTimeInterval` is bigger than 120 seconds. -- `MinTimeInterval` is not less than `MaxTimeInterval`. - - - - An object of containing the configuration for the object. - Provides a fixed interval time retry logic provider. - A object. - - [!NOTE] -> The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. - -]]> - - If the `retryLogicOption` parameter was null. - If at least one of the following conditions occurs: -- `NumberOfTries` is less than 1 or bigger than 60. -- `DeltaTime` is bigger than 120 seconds. -- `MinTimeInterval` is bigger than 120 seconds. -- `MaxTimeInterval` is bigger than 120 seconds. -- `MinTimeInterval` is not less than `MaxTimeInterval`. - - - - Provides a non-retriable provider with a that returns . - A object. - - [!NOTE] -> The returned provider of this function performs a single execution without any retry logic. - -]]> - - - - + + + + + Provides different retry logic providers with a common list of transient errors. + + + + The following table shows the inner transient error list. + + + + Error Number + Description + + + 1204 + + The instance of the SQL Server Database Engine cannot obtain a LOCK resource at this time. Rerun your statement when there are fewer active users. Ask the database administrator to check the lock and memory configuration for this instance, or to check for long-running transactions. + + + + 1205 + + Transaction (Process ID) was deadlocked on resources with another process and has been chosen as the deadlock victim. Rerun the transaction. + + + + 1222 + Lock request time out period exceeded. + + + 49918 + Cannot process request. Not enough resources to process request. + + + 49919 + + Cannot process create or update request. Too many create or update operations in progress for subscription "%ld". + + + + 49920 + Cannot process request. Too many operations in progress for subscription "%ld". + + + 4060 + Cannot open database "%.*ls" requested by the login. The login failed. + + + 4221 + + Login to read-secondary failed due to long wait on 'HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING'. The replica is not available for login because row versions are missing for transactions that were in-flight when the replica was recycled. The issue can be resolved by rolling back or committing the active transactions on the primary replica. Occurrences of this condition can be minimized by avoiding long write transactions on the primary. + + + + 40143 + The service has encountered an error processing your request. Please try again. + + + 40613 + + Database '%.*ls' on server '%.*ls' is not currently available. Please retry the connection later. If the problem persists, contact customer support, and provide them the session tracing ID of '%.*ls'. + + + + 40501 + The service is currently busy. Retry the request after 10 seconds. Incident ID: %ls. Code: %d. + + + 40540 + The service has encountered an error processing your request. Please try again. + + + 40197 + The service has encountered an error processing your request. Please try again. Error code %d. + + + 10929 + + Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d. However, the server is currently too busy to support requests greater than %d for this database. For more information, see http://go.microsoft.com/fwlink/?LinkId=267637. Otherwise, please try again later. + + + + 10928 + + Resource ID: %d. The %s limit for the database is %d and has been reached. For more information, see http://go.microsoft.com/fwlink/?LinkId=267637. + + + + 10060 + + An error has occurred while establishing a connection to the server. When connecting to SQL Server, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.) (Microsoft SQL Server, Error: 10060) + + + + 10054 + The data value for one or more columns overflowed the type used by the provider. + + + 10053 + Could not convert the data value due to reasons other than sign mismatch or overflow. + + + 997 + + A connection was successfully established with the server, but then an error occurred during the login process. (provider: Named Pipes Provider, error: 0 - Overlapped I/O operation is in progress) + + + + 233 + + A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.) (Microsoft SQL Server, Error: 233) + + + + + + + + An object of containing the configuration for the object. + + + Provides an exponential time interval retry logic provider. + + + A object. + + + + The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. + + + + If the parameter was null. + + + If at least one of the following conditions occurs: + + + is less than 1 or bigger than 60. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is not less than . + + + + + + + An object of containing the configuration for the object. + + + Provides an incremental time interval retry logic provider. + + + A object. + + + + The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. + + + + If the parameter was null. + + + If at least one of the following conditions occurs: + + + is less than 1 or bigger than 60. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is not less than . + + + + + + + An object of containing the configuration for the object. + + + Provides a fixed interval time retry logic provider. + + + A object. + + + + The inner enumerator includes randomization to prevent multiple instances of the client from performing subsequent retry attempts at the same time. + + + + If the `retryLogicOption` parameter was null. + + + If at least one of the following conditions occurs: + + + is less than 1 or bigger than 60. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is bigger than 120 seconds. + + + is not less than . + + + + + + + Provides a non-retryable provider with a that returns . + + + A object. + + + + The returned provider of this function performs a single execution without any retry logic. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml index 2eb4d4c5aa..f7ca3d1237 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml @@ -1,1320 +1,3345 @@ - - - - - Represents a connection to a SQL Server database. This class cannot be inherited. - - object represents a unique session to a SQL Server data source. With a client/server database system, it is equivalent to a network connection to the server. is used together with and to increase performance when connecting to a Microsoft SQL Server database. For all third-party SQL Server products and other OLE DB-supported data sources, use . - - When you create an instance of , all properties are set to their initial values. For a list of these values, see the constructor. - - See for a list of the keywords in a connection string. - - If the goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling `Close` or `Dispose`. `Close` and `Dispose` are functionally equivalent. If the connection pooling value `Pooling` is set to `true` or `yes`, the underlying connection is returned back to the connection pool. On the other hand, if `Pooling` is set to `false` or `no`, the underlying connection to the server is actually closed. - -> [!NOTE] -> Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool, because the connection is not actually closed when it is returned to the connection pool. For more information, see [SQL Server Connection Pooling (ADO.NET)](/sql/connect/ado-net/sql-server-connection-pooling). - - To ensure that connections are always closed, open the connection inside of a `using` block, as shown in the following code fragment. Doing so ensures that the connection is automatically closed when the code exits the block. - -```vb -Using connection As New SqlConnection(connectionString) - connection.Open() - ' Do work here; connection closed on following line. -End Using - -``` - -```csharp -using (SqlConnection connection = new SqlConnection(connectionString)) - { - connection.Open(); - // Do work here; connection closed on following line. - } -``` - -> [!NOTE] -> To deploy high-performance applications, you must use connection pooling. When you use the .NET Framework Data Provider for SQL Server, you do not have to enable connection pooling because the provider manages this automatically, although you can modify some settings. For more information, see [SQL Server Connection Pooling (ADO.NET)](/sql/connect/ado-net/sql-server-connection-pooling). - - If a is generated by the method executing a , the remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. - - An application that creates an instance of the object can require all direct and indirect callers to have sufficient permission to the code by setting declarative or imperative security demands. makes security demands using the object. Users can verify that their code has sufficient permissions by using the object. Users and administrators can also use the [Caspol.exe (Code Access Security Policy Tool)](/dotnet/framework/tools/caspol-exe-code-access-security-policy-tool) to modify security policy at the machine, user, and enterprise levels. For more information, see [Security in .NET](/dotnet/standard/security/). For an example demonstrating how to use security demands, see [Code Access Security and ADO.NET](/dotnet/framework/data/adonet/code-access-security). - - For more information about handling warning and informational messages from the server, see [Connection Events](/sql/connect/ado-net/connection-events). For more information about SQL Server engine errors and error messages, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - -> [!CAUTION] -> You can force TCP instead of shared memory. You can do that by prefixing tcp: to the server name in the connection string or you can use localhost. - - - -## Examples - The following example creates a and a . The is opened and set as the for the . The example then calls . To accomplish this, the is passed a connection string and a query string that is a Transact-SQL INSERT statement. The connection is closed automatically when the code exits the using block. - - [!code-csharp[SqlCommand_ExecuteNonQuery Example#1](~/../sqlclient/doc/samples/SqlCommand_ExecuteNonQuery.cs#1)] - - ]]> - - - - Initializes a new instance of the class. - - - Initializes a new instance of the class. - - is created, the read/write properties are set to the following initial values unless they are specifically set using their associated keywords in the property. - -|Properties|Initial value| -|----------------|-------------------| -||empty string ("")| -||15| -||empty string ("")| -||empty string ("")| - - You can change the value for these properties only by using the property. The class provides functionality for creating and managing the contents of connection strings. - - - -## Examples - The following example creates and opens a . - - [!code-csharp[SqlConnection_SqlConnection Example#1](~/../sqlclient/doc/samples/SqlConnection_SqlConnection.cs#1)] - - ]]> - - - - The connection used to open the SQL Server database. - Initializes a new instance of the class when given a string that contains the connection string. - - is created, the read/write properties are set to the following initial values unless they are specifically set using their associated keywords in the property. - -|Properties|Initial value| -|----------------|-------------------| -||`connectionString`| -||15| -||empty string ("")| -||empty string ("")| - - You can change the value for these properties only by using the property. The class provides functionality for creating and managing the contents of connection strings. - - - -## Examples - The following example creates and opens a . - - [!code-csharp[SqlConnection_SqlConnection1 Example#1](~/../sqlclient/doc/samples/SqlConnection_SqlConnection1.cs#1)] - - ]]> - - The supplied connection string argument failed validation. - - - A connection string that does not use any of the following connection string keywords: , , or ; or that does not use . - A object. If is null, is functionally equivalent to . - Initializes a new instance of the class given a connection string, that does not use and a object that contains the user ID and password. - To be added. - The supplied arguments failed validation, including validation. - - - Gets or sets the access token for the connection. - The access token for the connection. - - - + + + + Represents a connection to a SQL Server database. This class cannot be inherited. + + + + A object represents a unique session to a SQL Server data source. With a client/server database system, it is equivalent to a network connection to the server. is used together with and to increase performance when connecting to a Microsoft SQL Server database. For all third-party SQL Server products and other OLE DB-supported data sources, use . + + + When you create an instance of , all properties are set to their initial values. For a list of these values, see the constructor. + + + See for a list of the keywords in a connection string. + + + If the goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling or . and are functionally equivalent. If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is actually closed. + + + Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool, because the connection is not actually closed when it is returned to the connection pool. For more information, see SQL Server Connection Pooling (ADO.NET). + + + To ensure that connections are always closed, open the connection inside of a using block, as shown in the following code fragment. Doing so ensures that the connection is automatically closed when the code exits the block. + + + Using connection As New SqlConnection(connectionString) + connection.Open() + ' Do work here; connection closed on following line. + End Using + + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + // Do work here; connection closed on following line. + } + + + To deploy high-performance applications, you must use connection pooling. When you use the .NET Framework Data Provider for SQL Server, you do not have to enable connection pooling because the provider manages this automatically, although you can modify some settings. For more information, see SQL Server Connection Pooling (ADO.NET). + + + If a is generated by the method executing a , the remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. An application that creates an instance of the object can require all direct and indirect callers to have sufficient permission to the code by setting declarative or imperative security demands. makes security demands using the object. Users can verify that their code has sufficient permissions by using the object. Users and administrators can also use the Caspol.exe (Code Access Security Policy Tool) to modify security policy at the machine, user, and enterprise levels. For more information, see Security in .NET. For an example demonstrating how to use security demands, see Code Access Security and ADO.NET. + For more information about handling warning and informational messages from the server, see Connection Events. For more information about SQL Server engine errors and error messages, see Database Engine Events and Errors. + + + You can force TCP instead of shared memory. You can do that by prefixing tcp: to the server name in the connection string or you can use localhost. + + + + + The following example creates a and a . The is opened and set as the for the . The example then calls . To accomplish this, the is passed a SqlConnection and a query string that is a Transact-SQL INSERT statement. The connection is closed automatically when the code exits the using block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlCommandCS + { + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + string qs = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + CreateCommand(qs, str); + } + private static void CreateCommand(string queryString, string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + command.Connection.Open(); + command.ExecuteNonQuery(); + } + } + } + } + + + + + + Initializes a new instance of the class. + + + + When a new instance of is created, the read/write properties are set to the following initial values unless they are specifically set using their associated keywords in the property. + + + + Properties + Initial value + + + + empty string ("") + + + + 15 + + + + empty string ("") + + + + empty string ("") + + + + You can change the value for these properties only by using the property. The class provides functionality for creating and managing the contents of connection strings. + + + + + The following example creates and opens a . + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + OpenSqlConnection(); + Console.ReadLine(); + } + + private static void OpenSqlConnection() + { + string connectionString = GetConnectionString(); + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationManager.ConnectionStrings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + + + The connection used to open the SQL Server database. + + + Initializes a new instance of the class when given a string that contains the connection string. + + + + When a new instance of is created, the read/write properties are set to the following initial values unless they are specifically set using their associated keywords in the property. + + + + Properties + Initial value + + + + connectionString + + + + 15 + + + + empty string ("") + + + + empty string ("") + + + + You can change the value for these properties only by using the property. The class provides functionality for creating and managing the contents of connection strings. + + + + + The following example creates and opens a . + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + OpenSqlConnection(); + Console.ReadLine(); + } + + private static void OpenSqlConnection() + { + string connectionString = GetConnectionString(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + Console.WriteLine("State: {0}", connection.State); + Console.WriteLine("ConnectionString: {0}", + connection.ConnectionString); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + The supplied connection string argument failed validation. + + + + + A connection string that does not use any of the following connection string keywords: Integrated Security = true, UserId, or Password; or that does not use ConnectionContext = true. + + + A object. If is null, is functionally equivalent to . + + + Initializes a new instance of the class given a connection string, that does not use Integrated Security = true and a object that contains the user ID and password. + + + The supplied arguments failed validation, including validation. + + + + + Gets or sets the access token for the connection. + + + The access token for the connection. + + + The AccessToken is a part of the connection pool key. Care should be taken when using this property to manage your own access token. The application is responsible for knowing when the token expires and connections from the pool should no longer be used. If you set a minimum pool size > 0 along with AccessToken, you must call after the access token expires to ensure the connection pool doesn't maintain those connections indefinitely. + + + + + Gets or sets the access token callback for the connection. + + + The Func that takes a and and returns a . + + + + The following example demonstrates how to define and set an . + + + + using System; + using System.Collections.Concurrent; + using System.Threading; + using System.Threading.Tasks; + using Azure.Core; + using Azure.Identity; + using Microsoft.Data.SqlClient; -## Remarks - The AccessToken is a part of the connection pool key. Care should be taken when using this property to manage your own access token. The application is responsible for knowing when the token expires and connections from the pool should no longer be used. - - If you set a minimum pool size > 0 along with AccessToken, you must call after the access token expires to ensure the connection pool doesn't maintain those connections indefinitely. - - ]]> - - - - - Gets or sets the access token callback for the connection. - - The Func that takes a and and returns a . - - . - - [!code-csharp[SqlConnection_AccessTokenCallback Example#1](~/../sqlclient/doc/samples/SqlConnection_AccessTokenCallback.cs#1)] - - ]]> - - The AccessTokenCallback is combined with other conflicting authentication configurations. - - - To be added. - To be added. - To be added. - To be added. - - - Starts a database transaction. - - - Starts a database transaction. - An object representing the new transaction. - - or method. To make sure that the .NET Framework Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. - -> [!NOTE] -> If you do not specify an isolation level, the default isolation level is used. To specify an isolation level with the method, use the overload that takes the `iso` parameter (). The isolation level set for a transaction persists after the transaction is completed and until the connection is closed or disposed. Setting the isolation level to **Snapshot** in a database where the snapshot isolation level is not enabled does not throw an exception. The transaction will complete using the default isolation level. - -> [!CAUTION] -> If a transaction is started and a level 16 or higher error occurs on the server, the transaction will not be rolled back until the method is invoked. No exception is thrown on **ExecuteReader**. - -> [!CAUTION] -> When your query returns a large amount of data and calls `BeginTransaction`, a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , a , and methods. - - [!code-csharp[SqlConnection_BeginTransaction Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction.cs#1)] - - ]]> - - Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). - Parallel transactions are not supported. - - - The isolation level under which the transaction should run. - Starts a database transaction with the specified isolation level. - An object representing the new transaction. - - or method. To make sure that the .NET Framework Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. - -> [!NOTE] -> After a transaction is committed or rolled back, the isolation level of the transaction persists for all subsequent commands that are in autocommit mode (the SQL Server default). This can produce unexpected results, such as an isolation level of REPEATABLE READ persisting and locking other users out of a row. To reset the isolation level to the default (READ COMMITTED), execute the Transact-SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED statement, or call followed immediately by . For more information on SQL Server isolation levels, see [Transaction Isolation Levels](/sql/t-sql/language-elements/transaction-isolation-levels). - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - -> [!CAUTION] -> When your query returns a large amount of data and calls `BeginTransaction`, a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , a , and methods. - - [!code-csharp[SqlConnection_BeginTransaction1 Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction1.cs#1)] - - ]]> - - Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). - Parallel transactions are not supported. - - - The name of the transaction. - Starts a database transaction with the specified transaction name. - An object representing the new transaction. - - and in the `savePoint` parameter of the method. - - You must explicitly commit or roll back the transaction using the or method. To make sure that the .NET Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - -> [!CAUTION] -> When your query returns a large amount of data and calls `BeginTransaction`, a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , a , and methods. - - [!code-csharp[SqlConnection_BeginTransaction2 Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction2.cs#1)] - - ]]> - - Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). - Parallel transactions are not supported. - - - The isolation level under which the transaction should run. - The name of the transaction. - Starts a database transaction with the specified isolation level and transaction name. - An object representing the new transaction. - - and in the `savePoint` parameter of the method. - - You must explicitly commit or roll back the transaction using the or method. To make sure that the SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. - -> [!NOTE] -> After a transaction is committed or rolled back, the isolation level of the transaction persists for all subsequent commands that are in autocommit mode (the SQL Server default). This can produce unexpected results, such as an isolation level of REPEATABLE READ persisting and locking other users out of a row. To reset the isolation level to the default (READ COMMITTED), execute the Transact-SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED statement, or call followed immediately by . For more information on SQL Server isolation levels, see [Transaction Isolation Levels](/sql/t-sql/language-elements/transaction-isolation-levels). - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - -> [!CAUTION] -> When your query returns a large amount of data and calls `BeginTransaction`, a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , a , and methods. - - [!code-csharp[SqlConnection_BeginTransaction3 Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction3.cs#1)] - - ]]> - - Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). - Parallel transactions are not supported. - - - The name of the database to use instead of the current database. - Changes the current database for an open . - - and displays some of its read-only properties. - - [!code-csharp[SqlConnection_Database Example#1](~/../sqlclient/doc/samples/SqlConnection_Database.cs#1)] - - ]]> - - The database name is not valid. - The connection is not open. - Cannot change the database. - - - Changes the SQL Server password. - - - The connection string that contains enough information to connect to the server that you want. The connection string must contain the user ID and the current password. - The new password to set. This password must comply with any password security policy set on the server, including minimum length, requirements for specific characters, and so on. - Changes the SQL Server password for the user indicated in the connection string to the supplied new password. - - method changes the SQL Server password for the user indicated in the supplied `connectionString` parameter to the value supplied in the `newPassword` parameter. If the connection string includes the option for integrated security (that is, "Integrated Security=True" or the equivalent), an exception is thrown. - - To determine that the password has expired, calling the method raises a . In order to indicate that the password that is contained within the connection string must be reset, the property for the exception contains the status value 18487 or 18488. The first value (18487) indicates that the password has expired and the second (18488) indicates that the password must be reset before logging in. - - This method opens its own connection to the server, requests the password change, and closes the connection as soon as it has completed. This connection is not retrieved from, nor returned to, the SQL Server connection pool. - - - -## Examples - The following is a simple example of changing a password: - -```csharp -class Program { - static void Main(string[] args) { - Microsoft.Data.SqlClient.SqlConnection.ChangePassword( - "Data Source=a_server;Initial Catalog=a_database;UID=user;PWD=old_password", - "new_password"); - } -} - -``` - -```vb -Module Module1 - Sub Main() -Microsoft.Data.SqlClient.SqlConnection.ChangePassword( - "Data Source=a_server;Initial Catalog=a_database;UID=user;PWD=old_password", - "new_password") - End Sub -End Module - -``` - - The following console application demonstrates the issues involved in changing a user's password because the current password has expired. - - [!code-csharp[SqlConnection_ConnectionString1#1](~/../sqlclient/doc/samples/SqlConnection_ConnectionString1.cs#1)] - - ]]> - - The connection string includes the option to use integrated security. - - Or - - The exceeds 128 characters. - Either the or the parameter is null. - - - The connection string that contains enough information to connect to a server. The connection string should not use any of the following connection string keywords: , , or ; or . - A object. - The new password. must be read only. The password must also comply with any password security policy set on the server (for example, minimum length and requirements for specific characters). - Changes the SQL Server password for the user indicated in the object. - To be added. - - The connection string contains any combination of , , or . + const string defaultScopeSuffix = "/.default"; + // Reuse credential objects to take advantage of underlying token caches + private static ConcurrentDictionar<string, DefaultAzureCredential> credentials = new ConcurrentDictionary<string, DefaultAzureCredential>(); --or- + // Use a shared callback function for connections that should be in the same connection pool + private static Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken>> myAccessTokenCallback = + async (authParams, cancellationToken) => + { + string scope = authParams.Resource.EndsWith(defaultScopeSuffix) + ? authParams.Resource + : $"{authParams.Resource}{defaultScopeSuffix}"; - is greater than 128 characters. + DefaultAzureCredentialOptions options = new DefaultAzureCredentialOptions(); + options.ManagedIdentityClientId = authParams.UserId; --or- + // Reuse the same credential object if we are using the same MI Client ID + AccessToken token = await credentials.GetOrAdd(authParams.UserId, new DefaultAzureCredential(options)).GetTokenAsync( + new TokenRequestContext(new string[] { scope }), + cancellationToken); - is not read only. + return new SqlAuthenticationToken(token.Token, token.ExpiresOn); + }; --or- + private static void OpenSqlConnection() + { + // (Optional) Pass a User-Assigned Managed Identity Client ID. + // This will ensure different MI Client IDs are in different connection pools. + string connectionString = "Server=myServer.database.windows.net;Encrypt=Mandatory;UserId=<ManagedIdentityClientId>;"; - is an empty string. - One of the parameters (, , or ) is null. - - - Empties the connection pool. - - resets (or empties) the connection pool. If there are connections in use at the time of the call, they are marked appropriately and will be discarded (instead of being returned to the pool) when is called on them. - - ]]> - - - - The to be cleared from the pool. - Empties the connection pool associated with the specified connection. - - clears the connection pool that is associated with the `connection`. If additional connections associated with `connection` are in use at the time of the call, they are marked appropriately and are discarded (instead of being returned to the pool) when is called on them. - - ]]> - - - - The connection ID of the most recent connection attempt, regardless of whether the attempt succeeded or failed. - The connection ID of the most recent connection attempt. - - works regardless of which version of the server you connect to, but extended events logs and entry on connectivity ring buffer errors will not be present in SQL Server 2008 R2 and earlier. - - You can locate the connection ID in the extended events log to see if the failure was on the server if the extended event for logging connection ID is enabled. You can also locate the connection ID in the connection ring buffer ([Connectivity troubleshooting in SQL Server 2008 with the Connectivity Ring Buffer](https://go.microsoft.com/fwlink/?LinkId=207752)) for certain connection errors. If the connection ID is not in the connection ring buffer, you can assume a network error. - - ]]> - - - - Closes the connection to the database. This is the preferred method of closing any open connection. - - method rolls back any pending transactions. It then releases the connection to the connection pool, or closes the connection if connection pooling is disabled. - -> [!NOTE] -> Pending transactions started using Transact-SQL or are automatically rolled back when the connection is reset if connection pooling is enabled. If connection pooling is off, the transaction is rolled back after `SqlConnection.Close` is called. Transactions started through are controlled through the `System.Transactions` infrastructure, and are not affected by `SqlConnection.Close`. - - An application can call more than one time. No exception is generated. - - If the goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling `Close` or `Dispose`. `Close` and `Dispose` are functionally equivalent. If the connection pooling value `Pooling` is set to `true` or `yes`, the underlying connection is returned back to the connection pool. On the other hand, if `Pooling` is set to `false` or `no`, the underlying connection to the server is closed. - -> [!NOTE] -> Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool, because the connection is not actually closed when it is returned to the connection pool. For more information, see [SQL Server Connection Pooling (ADO.NET)](/sql/connect/ado-net/sql-server-connection-pooling). - -> [!CAUTION] -> Do not call `Close` or `Dispose` on a Connection, a DataReader, or any other managed object in the `Finalize` method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a `Finalize` method in your class definition. For more information, see [Garbage Collection](/dotnet/standard/garbage-collection/). - - - -## Examples - The following example creates a , opens it, displays some of its properties. The connection is automatically closed at the end of the `using` block. - - [!code-csharp[SqlConnection_Open Example#1](~/../sqlclient/doc/samples/SqlConnection_Open.cs#1)] - - ]]> - - The connection-level error that occurred while opening the connection. - - - Gets or sets the time-to-live for column encryption key entries in the column encryption key cache for the Always Encrypted feature. The default value is 2 hours. 0 means no caching at all. - The time interval. - To be added. - - - Gets or sets a value that indicates whether query metadata caching is enabled (true) or not (false) for parameterized queries running against Always Encrypted enabled databases. The default value is true. - Returns true if query metadata caching is enabled; otherwise false. true is the default. - - - - - - Allows you to set a list of trusted key paths for a database server. If while processing an application query the driver receives a key path that is not on the list, the query will fail. This property provides additional protection against security attacks that involve a compromised SQL Server providing fake key paths, which may lead to leaking key store credentials. - The list of trusted master key paths for the column encryption. - To be added. - - - - Gets the default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. - - - The time in seconds to wait for the command to execute. The default is 30 seconds. - - - + + + The is combined with other conflicting authentication configurations. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Starts a database transaction. + + + An object representing the new transaction. + + + + This command maps to the SQL Server implementation of BEGIN TRANSACTION.You must explicitly commit or roll back the transaction using the or method. To make sure that the .NET Framework Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. + + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation level with the method, use the overload that takes the iso parameter (). The isolation level set for a transaction persists after the transaction is completed and until the connection is closed or disposed. Setting the isolation level to Snapshot in a database where the snapshot isolation level is not enabled does not throw an exception. The transaction will complete using the default isolation level. + + + If a transaction is started and a level 16 or higher error occurs on the server, the transaction will not be rolled back until the method is invoked. No exception is thrown on . + + + When your query returns a large amount of data and calls , a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + + + The following example creates a and a . It also demonstrates how to use the , a , and methods. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1Cs + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction(); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback(); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). + + + Parallel transactions are not supported. + + + + + The isolation level under which the transaction should run. + + + Starts a database transaction with the specified isolation level. + + + An object representing the new transaction. + + + + This command maps to the SQL Server implementation of BEGIN TRANSACTION. You must explicitly commit or roll back the transaction using the or method. To make sure that the .NET Framework Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. + + + After a transaction is committed or rolled back, the isolation level of the transaction persists for all subsequent commands that are in autocommit mode (the SQL Server default). This can produce unexpected results, such as an isolation level of REPEATABLE READ persisting and locking other users out of a row. To reset the isolation level to the default (READ COMMITTED), execute the Transact-SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED statement, or call followed immediately by . For more information on SQL Server isolation levels, see Transaction Isolation Levels. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + When your query returns a large amount of data and calls , a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. + + + + + The following example creates a and a . It also demonstrates how to use the , a , and methods. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception e) + { + try + { + transaction.Rollback(); + } + catch (SqlException ex) + { + if (transaction.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + } + } + } + + + + Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). + + + Parallel transactions are not supported. + + + + + The name of the transaction. + + + Starts a database transaction with the specified transaction name. + + + An object representing the new transaction. + + + + This command maps to the SQL Server implementation of BEGIN TRANSACTION. The length of the parameter must not exceed 32 characters; otherwise an exception will be thrown. The value in the parameter can be used in later calls to and in the savePoint parameter of the method. You must explicitly commit or roll back the transaction using the or method. To make sure that the .NET Data Provider for SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + When your query returns a large amount of data and calls , a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. + + + + + The following example creates a and a . It also demonstrates how to use the , a , and methods. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction("SampleTransaction"); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback("SampleTransaction"); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). + + + Parallel transactions are not supported. + + + + + The isolation level under which the transaction should run. + + + The name of the transaction. + + + Starts a database transaction with the specified isolation level and transaction name. + + + An object representing the new transaction. + + + + This command maps to the SQL Server implementation of BEGIN TRANSACTION. The value in the parameter can be used in later calls to and in the savePoint parameter of the method. You must explicitly commit or roll back the transaction using the or method. To make sure that the SQL Server transaction management model performs correctly, avoid using other transaction management models, such as the one provided by SQL Server. + + + After a transaction is committed or rolled back, the isolation level of the transaction persists for all subsequent commands that are in autocommit mode (the SQL Server default). This can produce unexpected results, such as an isolation level of REPEATABLE READ persisting and locking other users out of a row. To reset the isolation level to the default (READ COMMITTED), execute the Transact-SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED statement, or call followed immediately by . For more information on SQL Server isolation levels, see Transaction Isolation Levels. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + When your query returns a large amount of data and calls , a is thrown because SQL Server does not allow parallel transactions when using MARS. To avoid this problem, always associate a transaction with the command, the connection, or both before any readers are open. + + + + + The following example creates a and a . It also demonstrates how to use the , a , and methods. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } - You can set the default wait time by using the `Command Timeout` keyword in the connection string. A value of 0 indicates no limit (an attempt to execute a command will wait indefinitely). - - ]]> - - - - Gets or sets the string used to open a SQL Server database. - The connection string that includes the source database name, and other parameters needed to establish the initial connection. The default value is an empty string. - - - is similar to an OLE DB connection string, but is not identical. Unlike OLE DB or ADO, the connection string that is returned is the same as the user-set , minus security information if the Persist Security Info value is set to `false` (default). The .NET Framework Data Provider for SQL Server does not persist or return the password in a connection string unless you set Persist Security Info to `true`. - You can use the property to connect to a database. The following example illustrates a typical connection string. - -``` -"Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local)" -``` - - Use the new to construct valid connection strings at run time. For more information, see [Connection String Builders](/sql/connect/ado-net/connection-string-builders). - - The property can be set only when the connection is closed. Many of the connection string values have corresponding read-only properties. When the connection string is set, these properties are updated, except when an error is detected. In this case, none of the properties are updated. properties return only those settings that are contained in the . - - To connect to a local computer, specify "(local)" for the server. If a server name is not specified, a connection will be attempted to the default instance on the local computer. - - Resetting the on a closed connection resets all connection string values (and related properties) including the password. For example, if you set a connection string that includes "Database= AdventureWorks", and then reset the connection string to "Data Source=myserver;Integrated Security=true", the property is no longer set to "AdventureWorks". - - The connection string is parsed immediately after being set. If errors in syntax are found when parsing, a runtime exception, such as , is generated. Other errors can be found only when an attempt is made to open the connection. - - The basic format of a connection string includes a series of keyword/value pairs separated by semicolons. The equal sign (=) connects each keyword and its value. To include values that contain a semicolon, single-quote character, or double-quote character, the value must be enclosed in double quotation marks. If the value contains both a semicolon and a double-quote character, the value can be enclosed in single quotation marks. The single quotation mark is also useful if the value starts with a double-quote character. Conversely, the double quotation mark can be used if the value starts with a single quotation mark. If the value contains both single-quote and double-quote characters, the quotation mark character used to enclose the value must be doubled every time it occurs within the value. - - To include preceding or trailing spaces in the string value, the value must be enclosed in either single quotation marks or double quotation marks. Any leading or trailing spaces around integer, Boolean, or enumerated values are ignored, even if enclosed in quotation marks. However, spaces within a string literal keyword or value are preserved. Single or double quotation marks may be used within a connection string without using delimiters (for example, Data Source= my'Server or Data Source= my"Server), unless a quotation mark character is the first or last character in the value. - - Keywords are not case sensitive. - - The following table lists the valid names for keyword values within the . - -|Keyword|Default|Description| -|-------------|-------------|-----------------| -|Addr|N/A|Synonym of **Data Source**.| -|Address|N/A|Synonym of **Data Source**.| -|App|N/A|Synonym of **Application Name**.| -|Application Intent

-or-

ApplicationIntent|ReadWrite|Declares the application workload type when connecting to a server. Possible values are `ReadOnly` and `ReadWrite`. For example:

`ApplicationIntent=ReadOnly`

For more information about SqlClient support for Always On Availability Groups, see [SqlClient Support for High Availability, Disaster Recovery](/sql/connect/ado-net/sql/sqlclient-support-high-availability-disaster-recovery).| -|Application Name|N/A|The name of the application. If no application name is provided, 'Framework Microsoft SqlClient Data Provider' when running on .NET Framework and 'Core Microsoft SqlClient Data Provider' otherwise.

An application name can be 128 characters or less.| -|AttachDBFilename

-or-

Extended Properties

-or-

Initial File Name|N/A|The name of the primary database file, including the full path name of an attachable database. AttachDBFilename is only supported for primary data files with an .mdf extension.

If the value of the AttachDBFileName key is specified in the connection string, the database is attached and becomes the default database for the connection.

If this key is not specified and if the database was previously attached, the database will not be reattached. The previously attached database will be used as the default database for the connection.

If this key is specified together with the AttachDBFileName key, the value of this key will be used as the alias. However, if the name is already used in another attached database, the connection will fail.

The path may be absolute or relative by using the DataDirectory substitution string. If DataDirectory is used, the database file must exist within a subdirectory of the directory pointed to by the substitution string. **Note:** Remote server, HTTP, and UNC path names are not supported.

The database name must be specified with the keyword 'database' (or one of its aliases) as in the following:

"AttachDbFileName=|DataDirectory|\data\YourDB.mdf;integrated security=true;database=YourDatabase"

An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path.| -|Attestation Protocol|NotSpecified|Gets or sets the value of Attestation Protocol.

When no value is specified, secure enclaves are disabled on the connection.

Valid values are:
`AAS`
`HGS`
`None` (Only valid in v3.1 and v4.1+))| -|Authentication|N/A|The authentication method used for [Connecting to SQL Database By Using Azure Active Directory Authentication](https://azure.microsoft.com/documentation/articles/sql-database-aad-authentication/#7-connect-to-your-database-by-using-azure-active-directory-identities).

Valid values are:

`Active Directory Integrated`, `Active Directory Interactive`, `Active Directory Password`, `Active Directory Service Principal`, `Active Directory Device Code Flow`, `Active Directory Managed Identity`, `Active Directory MSI`, `Active Directory Default`, `Sql Password`.

For additional information see [Using Azure Active Directory authentication with SqlClient](https://docs.microsoft.com/sql/connect/ado-net/sql/azure-active-directory-authentication?view=sql-server-ver15).| -|Column Encryption Setting|disabled|Enables or disables [Always Encrypted](/sql/relational-databases/security/encryption/always-encrypted-database-engine) functionality for the connection. Supported values are: `enabled` and `disabled`| -|Command Timeout|30|The default wait time (in seconds) before terminating the attempt to execute a command and generating an error.

Valid values are greater than or equal to 0 and less than or equal to 2147483647.| -|Connect Retry Count

-or-

ConnectRetryCount|1|Controls the number of reconnection attempts after the client identifies an idle connection failure. Valid values are 0 to 255. The default is 1. 0 means do not attempt to reconnect (disable connection resiliency).

For additional information about idle connection resiliency, see[.NET SqlConnection parameters for connection retry](https://learn.microsoft.com/azure/azure-sql/database/troubleshoot-common-connectivity-issues?view=azuresql#net-sqlconnection-parameters-for-connection-retry) and [Technical Article - Idle Connection Resiliency](https://go.microsoft.com/fwlink/?LinkId=393996).| -|Connect Retry Interval

-or-

ConnectRetryInterval|10|Specifies the time between each connection retry attempt (`ConnectRetryCount`). Valid values are 1 to 60 seconds (default=10), applied after the first reconnection attempt. When a broken connection is detected, the client immediately attempts to reconnect; this is the first reconnection attempt and only occurs if `ConnectRetryCount` is greater than 0. If the first reconnection attempt fails and `ConnectRetryCount` is greater than 1, the client waits `ConnectRetryInterval` to try the second and subsequent reconnection attempts.

For additional information about idle connection resiliency, see[.NET SqlConnection parameters for connection retry](https://learn.microsoft.com/azure/azure-sql/database/troubleshoot-common-connectivity-issues?view=azuresql#net-sqlconnection-parameters-for-connection-retry) and [Technical Article - Idle Connection Resiliency](https://go.microsoft.com/fwlink/?LinkId=393996).| -|Connect Timeout

-or-

Connection Timeout

-or-

Timeout|15|The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error.

Valid values are greater than or equal to 0 and less than or equal to 2147483647.

When opening a connection to a Azure SQL Database, set the connection timeout to 30 seconds.| -|Current Language

-or-

Language|N/A|Sets the language used for database server warning or error messages.

The language name can be 128 characters or less.| -|Data Source

-or-

Server

-or-

Address

-or-

Addr

-or-

Network Address|N/A|The name or network address of the instance of SQL Server to which to connect. The port number can be specified after the server name:

`server=tcp:servername, portnumber`

When specifying a local instance, always use (local). To force a protocol, add one of the following prefixes:

`np:(local), tcp:(local), lpc:(local)`

You can also connect to a LocalDB database as follows:

`server=(localdb)\\myInstance`

For more information about LocalDB, see [SqlClient Support for LocalDB](/sql/connect/ado-net/sql/sqlclient-support-localdb).

**Data Source** must use the TCP format or the Named Pipes format.

TCP format is as follows:

- tcp:\\\
- tcp:\,\

The TCP format must start with the prefix "tcp:" and is followed by the database instance, as specified by a host name and an instance name. This format is not applicable when connecting to Azure SQL Database. TCP is automatically selected for connections to Azure SQL Database when no protocol is specified.

The host name MUST be specified in one of the following ways:

- NetBIOSName
- IPv4Address
- IPv6Address

The instance name is used to resolve to a particular TCP/IP port number on which a database instance is hosted. Alternatively, specifying a TCP/IP port number directly is also allowed. If both instance name and port number are not present, the default database instance is used.

The Named Pipes format is as follows:

- np:\\\\\pipe\\

The Named Pipes format MUST start with the prefix "np:" and is followed by a named pipe name.

The host name MUST be specified in one of the following ways:

- NetBIOSName
- IPv4Address
- IPv6Address

The pipe name is used to identify the database instance to which the .NET application will connect.

If the value of the **Network** key is specified, the prefixes "tcp:" and "np:" should not be specified. **Note:** You can force the use of TCP instead of shared memory, either by prefixing **tcp:** to the server name in the connection string, or by using **localhost**.| -|Enclave Attestation Url|N/A|Gets or sets the enclave attestation URL to be used with enclave based Always Encrypted.| -|Encrypt|'true' in 4.0 and above

'false' in 3.x and below|Recognized values are:
versions 1 - 4: `true`/`yes` and `false`/`no`
versions 5+: `true`/`yes`/`mandatory`, `false`/`no`/`optional` and `strict`. When `true`, TLS encryption is used for all data sent between the client and server if the server has a certificate installed. When `strict`, TDS 8.0 TLS encryption is used and the `TrustServerCertificate` setting is ignored and treated as false. For more information, see [Connection String Syntax](/sql/connect/ado-net/connection-string-syntax).

When `Encrypt` is `mandatory` or `strict` and `TrustServerCertificate` is `false`, the server name (or IP address) in a server's certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. | -|Enlist|'true'|`true` indicates that the SQL Server connection pooler automatically enlists the connection in the creation thread's current transaction context.| -|Failover Partner|N/A|The name of the failover partner server where database mirroring is configured.

If the value of this key is "", then **Initial Catalog** must be present, and its value must not be "".

The server name can be 128 characters or less.

If you specify a failover partner but the failover partner server is not configured for database mirroring and the primary server (specified with the Server keyword) is not available, then the connection will fail.

If you specify a failover partner and the primary server is not configured for database mirroring, the connection to the primary server (specified with the Server keyword) will succeed if the primary server is available.| -|Failover Partner SPN

-or-

FailoverPartnerSPN|N/A|The SPN for the failover partner. The default value is an empty string, which causes SqlClient to use the default, driver-generated SPN.

(Only available in v5.0+)| -|Host Name In Certificate

-or-

HostNameInCertificate|N/A|The host name to use when validating the server certificate. When not specified, the server name from the Data Source is used for certificate validation.

(Only available in v5.0+)| -|Server Certificate

-or-

ServerCertificate|N/A|The path to a certificate file to match against the SQL Server TLS/SSL certificate. The accepted certificate formats are PEM, DER, and CER. If specified, the SQL Server certificate is checked by verifying if the ServerCertificate provided is an exact match.

(Only available in v5.1+)| -|Initial Catalog

-or-

Database|N/A|The name of the database.

The database name can be 128 characters or less.| -|Integrated Security

-or-

Trusted_Connection|'false'|When `false`, User ID and Password are specified in the connection. When `true`, the current Windows account credentials are used for authentication.

Recognized values are `true`, `false`, `yes`, `no`, and `sspi` (strongly recommended), which is equivalent to `true`.

If User ID and Password are specified and Integrated Security is set to true, the User ID and Password will be ignored and Integrated Security will be used.

is a more secure way to specify credentials for a connection that uses SQL Server Authentication (`Integrated Security=false`).| -|IP Address Preference

-or-

IPAddressPreference|IPv4First|The IP address family preference when establishing TCP connections. If `Transparent Network IP Resolution` (in .NET Framework) or `Multi Subnet Failover` is set to true, this setting has no effect. Supported values include:

`IPAddressPreference=IPv4First`

`IPAddressPreference=IPv6First`

`IPAddressPreference=UsePlatformDefault`| -|Load Balance Timeout

-or-

Connection Lifetime|0|When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by `Connection Lifetime`. This is useful in clustered configurations to force load balancing between a running server and a server just brought online.

A value of zero (0) causes pooled connections to have the maximum connection timeout.| -|Max Pool Size|100|The maximum number of connections that are allowed in the pool.

Valid values are greater than or equal to 1. Values that are less than **Min Pool Size** generate an error.| -|Min Pool Size|0|The minimum number of connections that are allowed in the pool.

Valid values are greater than or equal to 0. Zero (0) in this field means no minimum connections are initially opened.

Values that are greater than **Max Pool Size** generate an error.| -|Multiple Active Result Sets

-or-

MultipleActiveResultSets|false|When `true`, an application can maintain multiple active result sets (MARS). When `false`, an application must process or cancel all result sets from one batch before it can execute any other batch on that connection.

Recognized values are `true` and `false`.

For more information, see [Multiple Active Result Sets (MARS)](/sql/connect/ado-net/sql/multiple-active-result-sets-mars).| -|Multi Subnet Failover

-or-

MultiSubnetFailover|false|Always specify `multiSubnetFailover=True` when connecting to the availability group listener of a SQL Server 2012 (or later) availability group or a SQL Server 2012 (or later) Failover Cluster Instance. `multiSubnetFailover=True` configures SqlClient to provide faster detection of and connection to the (currently) active server. Possible values are `Yes` and `No`, `True` and `False` or `1` and `0`. For example:

`MultiSubnetFailover=True`

The default is `False`. For more information about SqlClient's support for Always On AGs, see [SqlClient Support for High Availability, Disaster Recovery](/sql/connect/ado-net/sql/sqlclient-support-high-availability-disaster-recovery).| -|Network Library

-or-

Network

-or-

Net|N/A|The network library used to establish a connection to an instance of SQL Server. Supported values include:

dbnmpntw (Named Pipes)

dbmsrpcn (Multiprotocol, Windows RPC)

dbmsadsn (Apple Talk)

dbmsgnet (VIA)

dbmslpcn (Shared Memory)

dbmsspxn (IPX/SPX)

dbmssocn (TCP/IP)

Dbmsvinn (Banyan Vines)

The corresponding network DLL must be installed on the system to which you connect. If you do not specify a network and you use a local server (for example, "." or "(local)"), shared memory is used. In this example, the network library is Win32 Winsock TCP/IP (dbmssocn), and 1433 is the port being used.

`Network Library=dbmssocn;Data Source=000.000.000.000,1433;`| -|Packet Size|8000|Size in bytes of the network packets used to communicate with an instance of SQL Server.

The packet size can be greater than or equal to 512 and less than or equal to 32768.| -|Password

-or-

PWD|N/A|The password for the SQL Server account logging on. Not recommended. To maintain a high level of security, we strongly recommend that you use the `Integrated Security` or `Trusted_Connection` keyword instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication.

The password must be 128 characters or less.| -|Persist Security Info

-or-

PersistSecurityInfo|'false'|When set to `false` or `no` (strongly recommended), security-sensitive information, such as the password or access token, is not returned as part of the connection if the connection is open or has ever been in an open state. This property should only be set to `true` if your application has a specific need to read the password out of an already-opened database connection. The default value of `false` is the more secure setting; using `true` for this property opens your application to security risks such as accidentally logging or tracing the database password.

Resetting the connection string resets all connection string values including the password. Recognized values are `true`, `false`, `yes`, and `no`.| -|Pool Blocking Period

-or-

PoolBlockingPeriod|Auto|Sets the blocking period behavior for a connection pool. See property for details.| -|Pooling|'true'|When the value of this key is set to true, any newly created connection will be added to the pool when closed by the application. In a next attempt to open the same connection, that connection will be drawn from the pool.

Connections are considered the same if they have the same connection string. Different connections have different connection strings.

The value of this key can be "true", "false", "yes", or "no".| -|Replication|'false'|`true` if replication is supported using the connection.| -|Server SPN

-or-

ServerSPN|N/A|The SPN for the data source. The default value is an empty string, which causes SqlClient to use the default, driver-generated SPN.

(Only available in v5.0+)| -|Transaction Binding|Implicit Unbind|Controls connection association with an enlisted `System.Transactions` transaction.

Possible values are:

`Transaction Binding=Implicit Unbind;`

`Transaction Binding=Explicit Unbind;`

Implicit Unbind causes the connection to detach from the transaction when it ends. After detaching, additional requests on the connection are performed in autocommit mode. The `System.Transactions.Transaction.Current` property is not checked when executing requests while the transaction is active. After the transaction has ended, additional requests are performed in autocommit mode.

If the system ends the transaction (in the scope of a using block) before the last command completes, it will throw .

Explicit Unbind causes the connection to remain attached to the transaction until the connection is closed or an explicit `SqlConnection.TransactionEnlist(null)` is called. Beginning in .NET Framework 4.0, changes to Implicit Unbind make Explicit Unbind obsolete. An `InvalidOperationException` is thrown if `Transaction.Current` is not the enlisted transaction or if the enlisted transaction is not active.| -|Transparent Network IP Resolution

-or-

TransparentNetworkIPResolution|See description.|When the value of this key is set to `true`, the application is required to retrieve all IP addresses for a particular DNS entry and attempt to connect with the first one in the list. If the connection is not established within 0.5 seconds, the application will try to connect to all others in parallel. When the first answers, the application will establish the connection with the respondent IP address.

If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.

If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.

The value of this key must be `true`, `false`, `yes`, or `no`.

A value of `yes` is treated the same as a value of `true`.

A value of `no` is treated the same as a value of `false`.

The default values are as follows:

  • `false` when:

    • Connecting to Azure SQL Database where the data source ends with:

      • .database.chinacloudapi.cn
      • .database.usgovcloudapi.net
      • .database.cloudapi.de
      • .database.windows.net
    • `Authentication` is 'Active Directory Password' or 'Active Directory Integrated'
  • `true` in all other cases.
| -|Trust Server Certificate

-or-

TrustServerCertificate|'false'|When set to `true`, TLS is used to encrypt the channel when bypassing walking the certificate chain to validate trust. If TrustServerCertificate is set to `true` and Encrypt is set to `false`, the channel is not encrypted. Recognized values are `true`, `false`, `yes`, and `no`. For more information, see [Connection String Syntax](/sql/connect/ado-net/connection-string-syntax).| -|Type System Version|N/A|A string value that indicates the type system the application expects. The functionality available to a client application is dependent on the version of SQL Server and the compatibility level of the database. Explicitly setting the type system version that the client application was written for avoids potential problems that could cause an application to break if a different version of SQL Server is used. **Note:** The type system version cannot be set for common language runtime (CLR) code executing in-process in SQL Server. For more information, see [SQL Server Common Language Runtime Integration](/dotnet/framework/data/adonet/sql/sql-server-common-language-runtime-integration).

Possible values are:

`Type System Version=SQL Server 2012;`

`Type System Version=SQL Server 2008;`

`Type System Version=SQL Server 2005;`

`Type System Version=Latest;`

`Type System Version=SQL Server 2012;` specifies that the application will require version 11.0.0.0 of Microsoft.SqlServer.Types.dll. The other `Type System Version` settings will require version 10.0.0.0 of Microsoft.SqlServer.Types.dll.

`Latest` is obsolete and should not be used. `Latest` is equivalent to `Type System Version=SQL Server 2008;`.| -|User ID

-or-

UID

-or-

User|N/A|The SQL Server login account. Not recommended. To maintain a high level of security, we strongly recommend that you use the `Integrated Security` or `Trusted_Connection` keywords instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication.

The user ID must be 128 characters or less.| -|User Instance|'false'|A value that indicates whether to redirect the connection from the default SQL Server Express instance to a runtime-initiated instance running under the account of the caller.| -|Workstation ID

-or-

WSID|The local computer name|The name of the workstation connecting to SQL Server.

The ID must be 128 characters or less.| - - The following list contains the valid names for connection pooling values within the . For more information, see [SQL Server Connection Pooling (ADO.NET)](/sql/connect/ado-net/sql-server-connection-pooling). - -- Connection Lifetime (or Load Balance Timeout) - -- Enlist - -- Max Pool Size - -- Min Pool Size - -- Pooling - - When you are setting keyword or connection pooling values that require a Boolean value, you can use 'yes' instead of 'true', and 'no' instead of 'false'. Integer values are represented as strings. -> [!NOTE] -> The .NET Framework Data Provider for SQL Server uses its own protocol to communicate with SQL Server. Therefore, it does not support the use of an ODBC data source name (DSN) when connecting to SQL Server because it does not add an ODBC layer. - -> [!NOTE] -> Universal data link (UDL) files are not supported for the .NET Framework Data Provider for SQL Server. - -> [!CAUTION] -> In this release, the application should use caution when constructing a connection string based on user input (for example when retrieving user ID and password information from a dialog box, and appending it to the connection string). The application should make sure that a user cannot embed additional connection string parameters in these values (for example, entering a password as "validpassword;database=somedb" in an attempt to attach to a different database). If you need to construct connection strings based on user input, use the new , which validates the connection string and helps to eliminate this problem. See [Connection String Builders](/sql/connect/ado-net/connection-string-builders) for more information. - - - -## Examples - The following example creates a and sets the property before opening the connection. - - [!code-csharp[SqlConnection_ConnectionString Example#1](~/../sqlclient/doc/samples/SqlConnection_ConnectionString.cs#1)] - - ]]>
-
- An invalid connection string argument has been supplied, or a required connection string argument has not been supplied. -
- - Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. - The time (in seconds) to wait for a connection to open. The default value is 15 seconds. - - because an attempt to connect waits indefinitely. - - - -## Examples - The following example creates a and sets the `Connection Timeout` to 30 seconds in the connection string. The code opens the connection and displays the property in the console window. - - [!code-csharp[SqlConnection_ConnectionTimeout Example#1](~/../sqlclient/doc/samples/SqlConnection_ConnectionTimeout.cs#1)] - - ]]> - - The value set is less than 0. - - - Creates and returns a object associated with the . - A object. - - - - - - To be added. - To be added. - To be added. - - - Gets or sets the object for this connection. - The object for this connection. - - object with . - - The default value of is null. - - An exception will be raised: - -- If is set on an open connection. - -- If is set when `Integrated Security = true`. - -- If is set when the connection string uses `Password`. - -- If is set when the connection string uses `UserID`. - - ]]> - - - - To be added. - To be added. - To be added. - - - Gets the name of the current database or the database to be used after a connection is opened. - The name of the current database or the name of the database to be used after a connection is opened. The default value is an empty string. - - property updates dynamically. If you change the current database using a Transact-SQL statement or the method, an informational message is sent and the property is updated automatically. - - - -## Examples - The following example creates a and displays some of its read-only properties. - - [!code-csharp[SqlConnection_Database Example#1](~/../sqlclient/doc/samples/SqlConnection_Database.cs#1)] - - ]]> - - - - Gets the name of the instance of SQL Server to which to connect. - The name of the instance of SQL Server to which to connect. The default value is an empty string. - - + + + Parallel transactions are not allowed when using Multiple Active Result Sets (MARS). + + + Parallel transactions are not supported. + + + + + Gets a value that indicates whether this instance supports the class. + + + if this instance supports the class; otherwise, . The default is . + + + ADO.net SQL provider implemented and overrides CanCreateBatch property to return . + + + + + The name of the database to use instead of the current database. + + + Changes the current database for an open . + + + The value supplied in the parameter must be a valid database name. The parameter cannot contain a null value, an empty string, or a string with only blank characters. + + + + The following example creates a and displays some of its read-only properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + ChangeSqlDatabase(s); + Console.ReadLine(); + } + + private static void ChangeSqlDatabase(string connectionString) + { + // Assumes connectionString represents a valid connection string + // to the AdventureWorks sample database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("Database: {0}", connection.Database); + + connection.ChangeDatabase("Northwind"); + Console.WriteLine("Database: {0}", connection.Database); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + The database name is not valid. + + + The connection is not open. + + + Cannot change the database. + + + + + Changes the SQL Server password. + + + + + The connection string that contains enough information to connect to the server that you want. The connection string must contain the user ID and the current password. + + + The new password to set. This password must comply with any password security policy set on the server, including minimum length, requirements for specific characters, and so on. + + + Changes the SQL Server password for the user indicated in the connection string to the supplied new password. + + + When you are using SQL Server on Windows Server, developers can take advantage of functionality that lets the client application supply both the current and a new password in order to change the existing password. Applications can implement functionality such as prompting the user for a new password during initial login if the old one has expired, and this operation can be completed without administrator intervention. This method changes the SQL Server password for the user indicated in the supplied connectionString parameter to the value supplied in the parameter. If the connection string includes the option for integrated security (that is, "Integrated Security=True" or the equivalent), an exception is thrown. To determine that the password has expired, calling the method raises a . In order to indicate that the password that is contained within the connection string must be reset, the property for the exception contains the status value 18487 or 18488. The first value (18487) indicates that the password has expired and the second (18488) indicates that the password must be reset before logging in. This method opens its own connection to the server, requests the password change, and closes the connection as soon as it has completed. This connection is not retrieved from, nor returned to, the SQL Server connection pool. + + + + The following is a simple example of changing a password: + + + class Program + { + static void Main(string[] args) + { + Microsoft.Data.SqlClient.SqlConnection.ChangePassword( + "Data Source=a_server;Initial Catalog=a_database;UID=user;PWD=old_password", + "new_password"); + } + } + + + Module Module1 + Sub Main() + Microsoft.Data.SqlClient.SqlConnection.ChangePassword( + "Data Source=a_server;Initial Catalog=a_database;UID=user;PWD=old_password", + "new_password") + End Sub + End Module + + + + + The following console application demonstrates the issues involved in changing a user's password because the current password has expired. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + DemonstrateChangePassword(); + } + catch (Exception ex) + { + Console.WriteLine("Error: " + ex.Message); + } + Console.WriteLine("Press ENTER to continue..."); + Console.ReadLine(); + } + + private static void DemonstrateChangePassword() + { + // Retrieve the connection string. In a production application, + // this string should not be contained within the source code. + string connectionString = GetConnectionString(); + + using (SqlConnection cnn = new SqlConnection()) + { + for (int i = 0; i <= 1; i++) + { + // Run this loop at most two times. If the first attempt fails, + // the code checks the Number property of the SqlException object. + // If that contains the special values 18487 or 18488, the code + // attempts to set the user's password to a new value. + // Assuming this succeeds, the second pass through + // successfully opens the connection. + // If not, the exception handler catches the exception. + try + { + cnn.ConnectionString = connectionString; + cnn.Open(); + // Once this succeeds, just get out of the loop. + // No need to try again if the connection is already open. + break; + } + catch (SqlException ex) + { + if (i == 0 && ((ex.Number == 18487) || (ex.Number == 18488))) + { + // You must reset the password. + connectionString = + ModifyConnectionString(connectionString, + GetNewPassword()); + + } + else + // Bubble all other SqlException occurrences + // back up to the caller. + throw; + } + } + SqlCommand cmd = new SqlCommand( + "SELECT ProductID, Name FROM Product", cnn); + // Use the connection and command here... + } + } + + private static string ModifyConnectionString( + string connectionString, string NewPassword) + { + + // Use the SqlConnectionStringBuilder class to modify the + // password portion of the connection string. + SqlConnectionStringBuilder builder = + new SqlConnectionStringBuilder(connectionString); + builder.Password = NewPassword; + return builder.ConnectionString; + } + + private static string GetNewPassword() + { + // In a real application, you might display a modal + // dialog box to retrieve the new password. The concepts + // are the same as for this simple console application, however. + Console.Write("Your password must be reset. Enter a new password: "); + return Console.ReadLine(); + } + + private static string GetConnectionString() + { + // For this demonstration, the connection string must + // contain both user and password information. In your own + // application, you might want to retrieve this setting + // from a config file, or from some other source. + + // In a production application, you would want to + // display a modal form that could gather user and password + // information. + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder( + "Data Source=(local);Initial Catalog=AdventureWorks"); + + Console.Write("Enter your user id: "); + builder.UserID = Console.ReadLine(); + Console.Write("Enter your password: "); + builder.Password = Console.ReadLine(); + + return builder.ConnectionString; + } + } + + + + + + The connection string includes the option to use integrated security. + + + The exceeds 128 characters. + + + + + Either the or the parameter is null. + + + + + The connection string that contains enough information to connect to a server. The connection string should not use any of the following connection string keywords: Integrated Security = true, UserId, or Password ; or ContextConnection = true. + + + A object. + + + The new password. must be read only. The password must also comply with any password security policy set on the server (for example, minimum length and requirements for specific characters). + + + Changes the SQL Server password for the user indicated in the object. + + + + + The connection string contains any combination of UserId, Password, or Integrated Security=true. + + + is greater than 128 characters. + + + is not read only. + + + is an empty string. + + + + + One of the parameters (, , or ) is null. + + + + + Empties the connection pool. + + + resets (or empties) the connection pool. If there are connections in use at the time of the call, they are marked appropriately and will be discarded (instead of being returned to the pool) when is called on them. + + + + + The to be cleared from the pool. + + + Empties the connection pool associated with the specified connection. + + + clears the connection pool that is associated with the . If additional connections associated with are in use at the time of the call, they are marked appropriately and are discarded (instead of being returned to the pool) when is called on them. + + + + + The connection ID of the most recent connection attempt, regardless of whether the attempt succeeded or failed. + + + The connection ID of the most recent connection attempt. + + + + works regardless of which version of the server you connect to, but extended events logs and entry on connectivity ring buffer errors will not be present in SQL Server 2008 R2 and earlier. + + + You can locate the connection ID in the extended events log to see if the failure was on the server if the extended event for logging connection ID is enabled. You can also locate the connection ID in the connection ring buffer (Connectivity troubleshooting in SQL Server 2008 with the Connectivity Ring Buffer) for certain connection errors. If the connection ID is not in the connection ring buffer, you can assume a network error. + + + + + + Closes the connection to the database. This is the preferred method of closing any open connection. + + + + The method rolls back any pending transactions. It then releases the connection to the connection pool, or closes the connection if connection pooling is disabled. + + + Pending transactions started using Transact-SQL or are automatically rolled back when the connection is reset if connection pooling is enabled. If connection pooling is off, the transaction is rolled back after SqlConnection.Close is called. Transactions started through are controlled through the infrastructure, and are not affected by SqlConnection.Close. + + + An application can call more than one time. No exception is generated. If the goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent. If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is closed. + + + Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool, because the connection is not actually closed when it is returned to the connection pool. For more information, see SQL Server Connection Pooling (ADO.NET). + + + Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. For more information, see Garbage Collection. + + + + + The following example creates a , opens it, displays some of its properties. The connection is automatically closed at the end of the using block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + OpenSqlConnection(s); + Console.ReadLine(); + } + + private static void OpenSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + The connection-level error that occurred while opening the connection. + + + + + Gets or sets the time-to-live for column encryption key entries in the column encryption key cache for the Always Encrypted feature. The default value is 2 hours. 0 means no caching at all. + + + The time interval. + + + + + Gets or sets a value that indicates whether query metadata caching is enabled (true) or not (false) for parameterized queries running against Always Encrypted enabled databases. The default value is true. + + + Returns true if query metadata caching is enabled; otherwise false. true is the default. + + + For parameterized queries, SqlClient makes a roundtrip to SQL Server for parameter metadata, to see which parameter it needs to encrypt and how (which keys and algorithms should be used). If the application calls the same query multiple times, an extra roundtrip is made to the server each time, which degrades application performance. With ColumnEncryptionQueryMetadataCacheEnabled set to true, if the same query is called multiple times, the roundtrip to the server will be made only once. The cache has a non-configurable Max size parameter that is set to 2000 queries. + + + + + Allows you to set a list of trusted key paths for a database server. If while processing an application query the driver receives a key path that is not on the list, the query will fail. This property provides additional protection against security attacks that involve a compromised SQL Server providing fake key paths, which may lead to leaking key store credentials. + + + The list of trusted master key paths for the column encryption. + + + + + Gets the default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. + + + The time in seconds to wait for the command to execute. The default is 30 seconds. + + + You can set the default wait time by using the Command Timeout keyword in the connection string. A value of 0 indicates no limit (an attempt to execute a command will wait indefinitely). + + + + + Gets or sets the string used to open a SQL Server database. + + + The connection string that includes the source database name, and other parameters needed to establish the initial connection. The default value is an empty string. + + + + The is similar to an OLE DB connection string, but is not identical. Unlike OLE DB or ADO, the connection string that is returned is the same as the user-set , minus security information if the Persist Security Info value is set to false (default). The .NET Framework Data Provider for SQL Server does not persist or return the password in a connection string unless you set Persist Security Info to true. You can use the property to connect to a database. The following example illustrates a typical connection string. + + + "Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local)" + + + Use the new to construct valid connection strings at run time. For more information, see Connection String Builders. The property can be set only when the connection is closed. Many of the connection string values have corresponding read-only properties. When the connection string is set, these properties are updated, except when an error is detected. In this case, none of the properties are updated. properties return only those settings that are contained in the . To connect to a local computer, specify "(local)" for the server. If a server name is not specified, a connection will be attempted to the default instance on the local computer. Resetting the on a closed connection resets all connection string values (and related properties) including the password. For example, if you set a connection string that includes "Database= AdventureWorks", and then reset the connection string to Data Source=myserver;Integrated Security=true, the property is no longer set to "AdventureWorks". The connection string is parsed immediately after being set. If errors in syntax are found when parsing, a runtime exception, such as , is generated. Other errors can be found only when an attempt is made to open the connection. The basic format of a connection string includes a series of keyword/value pairs separated by semicolons. The equal sign (=) connects each keyword and its value. To include values that contain a semicolon, single-quote character, or double-quote character, the value must be enclosed in double quotation marks. If the value contains both a semicolon and a double-quote character, the value can be enclosed in single quotation marks. The single quotation mark is also useful if the value starts with a double-quote character. Conversely, the double quotation mark can be used if the value starts with a single quotation mark. If the value contains both single-quote and double-quote characters, the quotation mark character used to enclose the value must be doubled every time it occurs within the value. To include preceding or trailing spaces in the string value, the value must be enclosed in either single quotation marks or double quotation marks. Any leading or trailing spaces around integer, Boolean, or enumerated values are ignored, even if enclosed in quotation marks. However, spaces within a string literal keyword or value are preserved. Single or double quotation marks may be used within a connection string without using delimiters (for example, Data Source= my'Server or Data Source= my"Server), unless a quotation mark character is the first or last character in the value. Keywords are not case-sensitive. The following table lists the valid names for keyword values within the . + + + + Keyword + Default + Description + + + Addr + N/A + Synonym of Data Source. + + + Address + N/A + Synonym of Data Source. + + + App + N/A + Synonym of Application Name. + + + + Application Intent or ApplicationIntent + + ReadWrite + + + Declares the application workload type when connecting to a server. Possible values are ReadOnly and ReadWrite. For example: ApplicationIntent=ReadOnly + + + For more information about SqlClient support for Always On Availability Groups, see SqlClient Support for High Availability, Disaster Recovery. + + + + + Application Name + N/A + + + The name of the application. If no application name is provided, 'Framework Microsoft SqlClient Data Provider' when running on .NET Framework and 'Core Microsoft SqlClient Data Provider' otherwise. + + + An application name can be 128 characters or fewer. + + + + + + AttachDBFilename or Extended Properties or Initial File Name + + N/A + + + The name of the primary database file, including the full path name of an attachable database. AttachDBFilename is only supported for primary data files with an .mdf extension. + + + If the value of the AttachDBFileName key is specified in the connection string, the database is attached and becomes the default database for the connection. + + + If this key is not specified and if the database was previously attached, the database will not be reattached. The previously attached database will be used as the default database for the connection. + + + If this key is specified together with the AttachDBFileName key, the value of this key will be used as the alias. However, if the name is already used in another attached database, the connection will fail. + + + The path may be absolute or relative by using the DataDirectory substitution string. If DataDirectory is used, the database file must exist within a subdirectory of the directory pointed to by the substitution string. Note: Remote server, HTTP, and UNC path names are not supported. + + + The database name must be specified with the keyword 'database' (or one of its aliases) as in the following: + + + AttachDbFileName=|DataDirectory|\data\YourDB.mdf;integrated security=true;database=YourDatabase + + + An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path. + + + + + Attestation Protocol + NotSpecified + + + Gets or sets the value of Attestation Protocol. + + + When no value is specified, secure enclaves are disabled on the connection. + + + Valid values are: + + + AAS + HGS + None (Only valid in v3.1 and v4.1+) + + + + + Authentication + N/A + + + The authentication method used for Connecting to SQL Database By Using Azure Active Directory Authentication. + + + Valid values are: + + + Active Directory Integrated + Active Directory Interactive + Active Directory Password + Active Directory Service Principal + Active Directory Device Code Flow + Active Directory Managed Identity + Active Directory MSI + Active Directory Default + Sql Password + + + For additional information see Using Azure Active Directory authentication with SqlClient. + + + + + Column Encryption Setting + disabled + + Enables or disables Always Encrypted functionality for the connection. Supported values are: enabled and disabled + + + + Command Timeout + 30 + + + The default wait time (in seconds) before terminating the attempt to execute a command and generating an error. + + + Valid values are greater than or equal to 0 and less than or equal to 2147483647. + + + + + + Connect Retry Count or ConnectRetryCount + + 1 + + + Controls the number of reconnection attempts after the client identifies an idle connection failure. Valid values are 0 to 255. 0 means do not attempt to reconnect (disable connection resiliency). + + + Note: Since version 5.x the default value for non Azure endpoints is 1. For Azure SQL endpoints, the default is 2. For Azure SQL serverless or on demand endpoints, the default is 5 to improve connection success for connections to an idle or paused instance. + + + For additional information about idle connection resiliency, see .NET SqlConnection parameters for connection retry and Technical Article - Idle Connection Resiliency. + + + + + + Connect Retry Interval or ConnectRetryInterval + + 10 + + + Specifies the time between each connection retry attempt (ConnectRetryCount). Valid values are 1 to 60 seconds (default=10), applied after the first reconnection attempt. When a broken connection is detected, the client immediately attempts to reconnect; this is the first reconnection attempt and only occurs if ConnectRetryCount is greater than 0. If the first reconnection attempt fails and ConnectRetryCount is greater than 1, the client waits ConnectRetryInterval to try the second and subsequent reconnection attempts. + + + For additional information about idle connection resiliency, see .NET SqlConnection parameters for connection retry and Technical Article - Idle Connection Resiliency. + + + + + + Connect Timeout or Connection Timeout or Timeout + + 15 + + + The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error. + + + Valid values are greater than or equal to 0 and less than or equal to 2147483647. + + + When opening a connection to a Azure SQL Database, set the connection timeout to 30 seconds. + + + + + + Current Language or Language + + N/A + + + Sets the language used for database server warning or error messages. + + + The language name can be 128 characters or fewer. + + + + + + Data Source or Server or Address or Addr or Network Address + + N/A + + + The name or network address of the instance of SQL Server to which to connect. The port number can be specified after the server name: server=tcp:servername, portnumber + + + When specifying a local instance, always use (local). To force a protocol, add one of the following prefixes: np:(local), tcp:(local), lpc:(local) + + + You can also connect to a LocalDB database as follows: server=(localdb)\\myInstance + + + For more information about LocalDB, see SqlClient Support for LocalDB. + + + Data Source must use the TCP format or the Named Pipes format. + + + TCP format is as follows: + + + tcp:\<host name>\\<instance name>\ + tcp:\<host name>,\<TCP/IP port number> + + + The TCP format must start with the prefix "tcp:" and is followed by the database instance, as specified by a host name and an instance name. This format is not applicable when connecting to Azure SQL Database. TCP is automatically selected for connections to Azure SQL Database when no protocol is specified. + + + The host name MUST be specified in one of the following ways: + + + NetBIOSName + IPv4Address + IPv6Address + + + The instance name is used to resolve to a particular TCP/IP port number on which a database instance is hosted. Alternatively, specifying a TCP/IP port number directly is also allowed. If both instance name and port number are not present, the default database instance is used. + + + The Named Pipes format is as follows: + + + np:\\\\<host name>\pipe\\<pipe name> + + + The Named Pipes format MUST start with the prefix "np:" and is followed by a named pipe name.

+ The host name MUST be specified in one of the following ways: +
+ + NetBIOSName + IPv4Address + IPv6Address + + + The pipe name is used to identify the database instance to which the .NET application will connect. + + + If the value of the Network key is specified, the prefixes "tcp:" and "np:" should not be specified. Note: You can force the use of TCP instead of shared memory, either by prefixing tcp: to the server name in the connection string, or by using localhost. + +
+
+ + Enclave Attestation Url + N/A + Gets or sets the enclave attestation URL to be used with enclave based Always Encrypted. + + + Encrypt + + true in 4.0 and above

+ false in 3.x and below +
+ + + Recognized values are: + + + + versions 1 - 4: true / yes and false / no + + + versions 5+: true / yes / mandatory, false / no / optional and strict. When true, TLS encryption is used for all data sent between the client and server if the server has a certificate installed. When strict, TDS 8.0 TLS encryption is used and the TrustServerCertificate setting is ignored and treated as false. For more information, see Connection String Syntax. + + + + When Encrypt is mandatory or strict and TrustServerCertificate is false, the server name (or IP address) in a server's certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. + + +
+ + Enlist + 'true' + + true indicates that the SQL Server connection pooler automatically enlists the connection in the creation thread's current transaction context. + + + + Failover Partner + N/A + + + The name of the failover partner server where database mirroring is configured. + + + If the value of this key is "", then Initial Catalog must be present, and its value must not be "". + + + The server name can be 128 characters or fewer. + + + If you specify a failover partner but the failover partner server is not configured for database mirroring and the primary server (specified with the Server keyword) is not available, then the connection will fail. + + + If you specify a failover partner and the primary server is not configured for database mirroring, the connection to the primary server (specified with the Server keyword) will succeed if the primary server is available. + + + + + + Failover Partner SPN or FailoverPartnerSPN + + N/A + + The SPN for the failover partner. The default value is an empty string, which causes SqlClient to use the default, driver-generated SPN. (Only available in v5.0+) + + + + + Host Name In Certificate or HostNameInCertificate + + N/A + + The host name to use when validating the server certificate. When not specified, the server name from the Data Source is used for certificate validation. (Only available in v5.0+) + + + + + Server Certificate or ServerCertificate + + N/A + + The path to a certificate file to match against the SQL Server TLS/SSL certificate. The accepted certificate formats are PEM, DER, and CER. If specified, the SQL Server certificate is checked by verifying if the ServerCertificate provided is an exact match. (Only available in v5.1+) + + + + + Initial Catalog or Database + + N/A + + + The name of the database. + + + The database name can be 128 characters or fewer. + + + + + + Integrated Security or Trusted_Connection + + false + + + When false, User ID and Password are specified in the connection. When true, the current Windows account credentials are used for authentication. + + + Recognized values are true, false, yes, no, and sspi (strongly recommended), which is equivalent to true. + + + If User ID and Password are specified and Integrated Security is set to true, the User ID and Password will be ignored and Integrated Security will be used. + + + is a more secure way to specify credentials for a connection that uses SQL Server Authentication (Integrated Security=false). + + + + + + IP Address Preference or IPAddressPreference + + IPv4First + + + The IP address family preference when establishing TCP connections. If Transparent Network IP Resolution (in .NET Framework) or Multi Subnet Failover is set to true, this setting has no effect. Supported values include: + + + IPAddressPreference=IPv4First + IPAddressPreference=IPv6First + IPAddressPreference=UsePlatformDefault + + + + + + Load Balance Timeout or Connection Lifetime + + 0 + + + When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by Connection Lifetime. This is useful in clustered configurations to force load balancing between a running server and a server just brought online. + + + A value of zero (0) causes pooled connections to have the maximum connection timeout. + + + + + Max Pool Size + 100 + + + The maximum number of connections that are allowed in the pool. + + + Valid values are greater than or equal to 1. Values that are less than Min Pool Size generate an error. + + + + + Min Pool Size + 0 + + + The minimum number of connections that are allowed in the pool. + + + Valid values are greater than or equal to 0. Zero (0) in this field means no minimum connections are initially opened. + + + Values that are greater than Max Pool Size generate an error. + + + + + + Multiple Active Result Sets or MultipleActiveResultSets + + false + + + When true, an application can maintain multiple active result sets (MARS). When false, an application must process or cancel all result sets from one batch before it can execute any other batch on that connection. + + + Recognized values are true and false. + + + For more information, see Multiple Active Result Sets (MARS). + + + + + + Multi Subnet Failover or MultiSubnetFailover + + false + + + Always specify multiSubnetFailover=True when connecting to the availability group listener of a SQL Server 2012 (or later) availability group or a SQL Server 2012 (or later) Failover Cluster Instance. multiSubnetFailover=True configures SqlClient to provide faster detection of and connection to the (currently) active server. Possible values are Yes and No, True and False or 1 and 0. For example: + + + MultiSubnetFailover=True + + + The default is False. For more information about SqlClient's support for Always On AGs, see SqlClient Support for High Availability, Disaster Recovery. + + + + + + Network Library or Network or Net + + N/A + + + The network library used to establish a connection to an instance of SQL Server. Supported values include: + + + dbnmpntw (Named Pipes) + dbmsrpcn (Multiprotocol, Windows RPC) + dbmsadsn (Apple Talk) + dbmsgnet (VIA) + dbmslpcn (Shared Memory) + dbmsspxn (IPX/SPX) + dbmssocn (TCP/IP) + Dbmsvinn (Banyan Vines) + + + The corresponding network DLL must be installed on the system to which you connect. If you do not specify a network and you use a local server (for example, "." or "(local)"), shared memory is used. In this example, the network library is Win32 Winsock TCP/IP (dbmssocn), and 1433 is the port being used. + + + Network Library=dbmssocn;Data Source=000.000.000.000,1433; + + + + + Packet Size + 8000 + + + Size in bytes of the network packets used to communicate with an instance of SQL Server. + + + The packet size can be greater than or equal to 512 and less than or equal to 32768. + + + + + + Password or PWD + + N/A + + + The password for the SQL Server account logging on. Not recommended. To maintain a high level of security, we strongly recommend that you use the Integrated Security or Trusted_Connection keyword instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication. + + + The password must be 128 characters or fewer. + + + + + + Persist Security Info or PersistSecurityInfo + + false + + + When set to false or no (strongly recommended), security-sensitive information, such as the password or access token, is not returned as part of the connection if the connection is open or has ever been in an open state. This property should only be set to true if your application has a specific need to read the password out of an already-opened database connection. The default value of false is the more secure setting; using true for this property opens your application to security risks such as accidentally logging or tracing the database password. + + + Resetting the connection string resets all connection string values including the password. + + + Recognized values are true, false, yes, and no. + + + + + + Pool Blocking Period or PoolBlockingPeriod + + Auto + + Sets the blocking period behavior for a connection pool. See property for details. + + + + Pooling + true + + + When the value of this key is set to true, any newly created connection will be added to the pool when closed by the application. In a next attempt to open the same connection, that connection will be drawn from the pool. + + + Connections are considered the same if they have the same connection string. Different connections have different connection strings. + + + The value of this key can be true, false, yes, and no. + + + + + Replication + false + true if replication is supported using the connection. + + + + Server SPN or ServerSPN + + N/A + + + The SPN for the data source. The default value is an empty string, which causes SqlClient to use the default, driver-generated SPN. (Only available in v5.0+) + + + + + Transaction Binding + Implicit Unbind + + + Controls connection association with an enlisted System.Transactions transaction. + + + Possible values are: + + + Transaction Binding=Implicit Unbind; + Transaction Binding=Explicit Unbind; + + + Implicit Unbind causes the connection to detach from the transaction when it ends. After detaching, additional requests on the connection are performed in autocommit mode. The System.Transactions.Transaction.Current property is not checked when executing requests while the transaction is active. After the transaction has ended, additional requests are performed in autocommit mode. + + + If the system ends the transaction (in the scope of a using block) before the last command completes, it will throw . + + + Explicit Unbind causes the connection to remain attached to the transaction until the connection is closed or an explicit SqlConnection.TransactionEnlist(null) is called. Beginning in .NET Framework 4.0, changes to Implicit Unbind make Explicit Unbind obsolete. An InvalidOperationException is thrown if Transaction.Current is not the enlisted transaction or if the enlisted transaction is not active. + + + + + + Transparent Network IP Resolution or TransparentNetworkIPResolution + + See description. + + + When the value of this key is set to true, the application is required to retrieve all IP addresses for a particular DNS entry and attempt to connect with the first one in the list. If the connection is not established within 0.5 seconds, the application will try to connect to all others in parallel. When the first answers, the application will establish the connection with the respondent IP address. + + + If the MultiSubnetFailover key is set to true, TransparentNetworkIPResolution is ignored. + + + If the Failover Partner key is set, TransparentNetworkIPResolution is ignored. + + + The value of this key must be true, false, yes, or no. + + + A value of yes is treated the same as a value of true. + + + A value of no is treated the same as a value of false. + + + The default values are as follows: + + + + false when: + + + Connecting to Azure SQL Database where the data source ends with: + + .database.chinacloudapi.cn + .database.usgovcloudapi.net + .database.cloudapi.de + .database.windows.net + + + Authentication is 'Active Directory Password' or 'Active Directory Integrated' + + + true in all other cases. + + + + + + Trust Server Certificate or TrustServerCertificate + + false + + When set to true, TLS is used to encrypt the channel when bypassing walking the certificate chain to validate trust. If TrustServerCertificate is set to true and Encrypt is set to false, the channel is not encrypted. Recognized values are true, false, yes, and no. For more information, see Connection String Syntax. + + + + Type System Version + N/A + + + A string value that indicates the type system the application expects. The functionality available to a client application is dependent on the version of SQL Server and the compatibility level of the database. Explicitly setting the type system version that the client application was written for avoids potential problems that could cause an application to break if a different version of SQL Server is used. Note: The type system version cannot be set for common language runtime (CLR) code executing in-process in SQL Server. For more information, see SQL Server Common Language Runtime Integration. + + + Possible values are: + + + Type System Version=SQL Server 2012; + Type System Version=SQL Server 2008; + Type System Version=SQL Server 2005; + Type System Version=Latest; + + + Type System Version=SQL Server 2012; specifies that the application will require version 11.0.0.0 of Microsoft.SqlServer.Types.dll. The other Type System Version settings will require version 10.0.0.0 of Microsoft.SqlServer.Types.dll. + + + Latest is obsolete and should not be used. Latest is equivalent to Type System Version=SQL Server 2008;. + + + + + + User ID or UID or User + + N/A + + + The SQL Server login account. Not recommended. To maintain a high level of security, we strongly recommend that you use the Integrated Security or Trusted_Connection keywords instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication. + + + The user ID must be 128 characters or fewer. + + + + + User Instance + false + + A value that indicates whether to redirect the connection from the default SQL Server Express instance to a runtime-initiated instance running under the account of the caller. + + + + + Workstation ID or WSID + + The local computer name + + The name of the workstation connecting to SQL Server. + The ID must be 128 characters or fewer. + + +
+ + The following list contains the valid names for connection pooling values within the . For more information, see SQL Server Connection Pooling (ADO.NET). + + + Connection Lifetime (or Load Balance Timeout) + Enlist + Max Pool Size + Min Pool Size + Pooling + + + When you are setting keyword or connection pooling values that require a Boolean value, you can use yed instead of true, and no instead of false. Integer values are represented as strings. + + + The .NET Framework Data Provider for SQL Server uses its own protocol to communicate with SQL Server. Therefore, it does not support the use of an ODBC data source name (DSN) when connecting to SQL Server because it does not add an ODBC layer. + + + Universal data link (UDL) files are not supported for the .NET Framework Data Provider for SQL Server. + + + In this release, the application should use caution when constructing a connection string based on user input (for example when retrieving user ID and password information from a dialog box, and appending it to the connection string). The application should make sure that a user cannot embed additional connection string parameters in these values (for example, entering a password as "validpassword;database=somedb" in an attempt to attach to a different database). If you need to construct connection strings based on user input, use the new , which validates the connection string and helps to eliminate this problem. See Connection String Builders for more information. + +
+ + + The following example creates a and sets the property before opening the connection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + OpenSqlConnection(); + Console.ReadLine(); + } + + private static void OpenSqlConnection() + { + string connectionString = GetConnectionString(); + + using (SqlConnection connection = new SqlConnection()) + { + connection.ConnectionString = connectionString; + + connection.Open(); + + Console.WriteLine("State: {0}", connection.State); + Console.WriteLine("ConnectionString: {0}", + connection.ConnectionString); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=MSSQL1;Initial Catalog=AdventureWorks;" + + "Integrated Security=true;"; + } + } + + + + An invalid connection string argument has been supplied, or a required connection string argument has not been supplied. + +
+ + + Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. + + + The time (in seconds) to wait for a connection to open. The default value is 15 seconds. + + + You can set the amount of time a connection waits to time out by using the Connect Timeout or Connection Timeout keywords in the connection string. A value of 0 indicates no limit, and should be avoided in a because an attempt to connect waits indefinitely. + + + + The following example creates a and sets the Connection Timeout to 30 seconds in the connection string. The code opens the connection and displays the property in the console window. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + OpenSqlConnection(); + Console.ReadLine(); + } + + private static void OpenSqlConnection() + { + string connectionString = GetConnectionString(); + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("State: {0}", connection.State); + Console.WriteLine("ConnectionTimeout: {0}", + connection.ConnectionTimeout); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;Connection Timeout=30"; + } + } + + + + The value set is less than 0. + + + + + Creates and returns a object associated with the . + + + A object. + + + + + using System.Data; + using Microsoft.Data.SqlClient; + + public class A + { + public static void Main() + { + using (SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;")) + { + connection.Open(); + SqlCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM Categories ORDER BY CategoryID"; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + } + } + } + + + + + + Returns a new instance of the class that implements the class. + + + A new instance of . + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets or sets the object for this connection. + + + The object for this connection. + + + + Persist Security Info = true is required to get the value of the object with . The default value of is null. An exception will be raised: + + + + If is set on an open connection. + + + If is set when Integrated Security = true. + + + If is set when the connection string uses Password. + + + If is set when the connection string uses UserID. + + + + + + + Gets the name of the current database or the database to be used after a connection is opened. + + + The name of the current database or the name of the database to be used after a connection is opened. The default value is an empty string. + + + The property updates dynamically. If you change the current database using a Transact-SQL statement or the method, an informational message is sent and the property is updated automatically. + + + + + + The following example creates a and displays some of its read-only properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + ChangeSqlDatabase(s); + Console.ReadLine(); + } + + private static void ChangeSqlDatabase(string connectionString) + { + // Assumes connectionString represents a valid connection string + // to the AdventureWorks sample database. + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("Database: {0}", connection.Database); + + connection.ChangeDatabase("Northwind"); + Console.WriteLine("Database: {0}", connection.Database); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + + + Gets the name of the instance of SQL Server to which to connect. + + + The name of the instance of SQL Server to which to connect. The default value is an empty string. + + + + The following example creates a and displays some of its read-only properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + OpenSqlConnection(s); + Console.ReadLine(); + } + + private static void OpenSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("DataSource: {0}", connection.DataSource); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + + + A reference to an existing in which to enlist. + + + Enlists in the specified transaction as a distributed transaction. + + + + You can use the method to enlist in a distributed transaction. Because it enlists a connection in a instance, takes advantage of functionality available in the namespace for managing distributed transactions, making it preferable to for this purpose. For more information, see Distributed Transactions. + + + You can continue to enlist in an existing distributed transaction using the EnlistDistributedTransaction method if auto-enlistment is disabled. Enlisting in an existing distributed transaction makes sure that, if the transaction is committed or rolled back, modifications made by the code at the data source are also committed or rolled back. EnlistDistributedTransaction returns an exception if the has already started a transaction using . However, if the transaction is a local transaction started at the data source (for example, by explicitly executing the BEGIN TRANSACTION statement using an object), EnlistDistributedTransaction rolls back the local transaction and enlists in the existing distributed transaction as requested. You do not receive notice that the local transaction was rolled back, and are responsible for managing any local transactions not started using . + + + + + + A reference to an existing in which to enlist. + + + Enlists in the specified transaction as a distributed transaction. + + + You can use the method to enlist in a distributed transaction. Because it enlists a connection in a instance, takes advantage of functionality available in the namespace for managing distributed transactions, making it preferable to , which uses a object (from namespace). It also has slightly different semantics: once a connection is explicitly enlisted on a transaction, it cannot be unenlisted or enlisted in another transaction until the first transaction finishes. For more information about distributed transactions, see Distributed Transactions. + + + + + Gets or sets the property. + + + if the property has been set; otherwise . + + + + When you set to true, errors that were previously treated as exceptions are now handled as events. All events fire immediately and are handled by the event handler. If is is set to false, then events are handled at the end of the procedure. + + + An error with a severity level of 17 or above that causes the server to stop processing the command needs to be handled as an exception. In this case, an exception is thrown regardless of how the error is handled in the event. + + + For more information on working with events, see Connection Events. For more information on errors generated by the SQL Server engine, see Database Engine Errors. + + + + + + Returns schema information for the data source of this . For more information about scheme, see SQL Server Schema Collections. + + + A that contains schema information. + + + + + Specifies the name of the schema to return. + + + Returns schema information for the data source of this using the specified string for the schema name. + + + A that contains schema information. + + + + You may need the schema information of the database, tables or columns. This sample: + + + Uses GetSchema to get schema information. + Use schema restrictions to get the specified information. + Gets schema information of the database, tables, and some columns. + + + + + Before you run the sample, you need to create the sample database, using the following Transact-SQL: + + + USE [master] + GO -## Examples - The following example creates a and displays some of its read-only properties. - - [!code-csharp[SqlConnection_DataSource Example#1](~/../sqlclient/doc/samples/SqlConnection_DataSource.cs#1)] - - ]]>
-
-
- - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - - - A reference to an existing in which to enlist. - Enlists in the specified transaction as a distributed transaction. - - method to enlist in a distributed transaction. Because it enlists a connection in a instance, **EnlistTransaction** takes advantage of functionality available in the namespace for managing distributed transactions, making it preferable to **EnlistDistributedTransaction** for this purpose. For more information, see [Distributed Transactions](/sql/connect/ado-net/distributed-transactions). - - You can continue to enlist in an existing distributed transaction using the **EnlistDistributedTransaction** method if auto-enlistment is disabled. Enlisting in an existing distributed transaction makes sure that, if the transaction is committed or rolled back, modifications made by the code at the data source are also committed or rolled back. - - `EnlistDistributedTransaction` returns an exception if the has already started a transaction using . However, if the transaction is a local transaction started at the data source (for example, by explicitly executing the BEGIN TRANSACTION statement using an object), **EnlistDistributedTransaction** rolls back the local transaction and enlists in the existing distributed transaction as requested. You do not receive notice that the local transaction was rolled back, and are responsible for managing any local transactions not started using . - - ]]> - - - - A reference to an existing in which to enlist. - Enlists in the specified transaction as a distributed transaction. - - method to enlist in a distributed transaction. Because it enlists a connection in a instance, **EnlistTransaction** takes advantage of functionality available in the namespace for managing distributed transactions, making it preferable to **EnlistDistributedTransaction**, which uses a **System.EnterpriseServices.ITransaction** object. It also has slightly different semantics: once a connection is explicitly enlisted on a transaction, it cannot be unenlisted or enlisted in another transaction until the first transaction finishes. For more information about distributed transactions, see [Distributed Transactions](/sql/connect/ado-net/distributed-transactions). - - ]]> - - - - Gets or sets the property. - - if the property has been set; otherwise . - - to `true`, errors that were previously treated as exceptions are now handled as events. All events fire immediately and are handled by the event handler. If is is set to `false`, then events are handled at the end of the procedure. - -> [!NOTE] -> An error with a severity level of 17 or above that causes the server to stop processing the command needs to be handled as an exception. In this case, an exception is thrown regardless of how the error is handled in the event. - - For more information on working with events, see [Connection Events](/sql/connect/ado-net/connection-events). For more information on errors generated by the SQL Server engine, see [Database Engine Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - - ]]> - - - - Returns schema information for the data source of this . - - - - - - Returns schema information for the data source of this . For more information about scheme, see [SQL Server Schema Collections](/sql/connect/ado-net/sql-server-schema-collections). - A that contains schema information. - To be added. - - - Specifies the name of the schema to return. - Returns schema information for the data source of this using the specified string for the schema name. - A that contains schema information. - - - - - is specified as null. - - - Specifies the name of the schema to return. - A set of restriction values for the requested schema. - Returns schema information for the data source of this using the specified string for the schema name and the specified string array for the restriction values. - A that contains schema information. - - , see . - - ]]> - - - is specified as null. - - - - Occurs when SQL Server returns a warning or informational message. - - delegate to listen to this event. - - The event occurs when a message with a severity of 10 or less is returned by SQL Server. Messages that have a severity between 11 and 20 raise an error and messages that have a severity over 20 causes the connection to close. For more information on SQL Server error levels, see [Database Engine Error Severities](/sql/relational-databases/errors-events/database-engine-error-severities). - - For more information and an example, see [Connection Events](/sql/connect/ado-net/connection-events). - - ]]> - - - - To be added. - To be added. - To be added. - - - Opens a database connection with the property settings specified by the . - - draws an open connection from the connection pool if one is available. Otherwise, it establishes a new connection to an instance of SQL Server. - -> [!NOTE] -> If the goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling . - -> [!NOTE] -> If you specify a port number other than 1433 when you are trying to connect to an instance of SQL Server and using a protocol other than TCP/IP, the method fails. To specify a port number other than 1433, include "server=machinename,port number" in the connection string, and use the TCP/IP protocol. - -> [!NOTE] -> The .NET Framework Data Provider for SQL Server requires the Security permission with "Allows calls to unmanaged assemblies" enabled ( with set to `UnmanagedCode`) to open a with SQL Debugging enabled. - - - -## Examples - The following example creates a , opens it, and displays some of its properties. The connection is automatically closed at the end of the `using` block. - - [!code-csharp[SqlConnection_Open Example#1](~/../sqlclient/doc/samples/SqlConnection_Open.cs#1)] - - ]]> - - Cannot open a connection without specifying a data source or server. - - or - - The connection is already open. - A connection-level error occurred while opening the connection. If the property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the method for more information. - - The tag in the app.config file has invalid or unknown elements. - There are two entries with the same name in the section. - - - Options to override default connection open behavior. - - Opens a database connection with the property settings specified by the . - - - - draws an open connection from the connection pool if one is available. Otherwise, it establishes a new connection to an instance of SQL Server. If overrides are specified, the first open attempt will apply the specified overrides to the open action. + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO -> [!NOTE] -> If the goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling . + CREATE TABLE [dbo].[Course]( + [CourseID] [nvarchar](10) NOT NULL, + [Year] [smallint] NOT NULL, + [Title] [nvarchar](100) NOT NULL, + [Credits] [int] NOT NULL, + [DepartmentID] [int] NOT NULL, + CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED ( + [CourseID] ASC, + [Year] ASC + ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] + GO -> [!NOTE] -> If you specify a port number other than 1433 when you are trying to connect to an instance of SQL Server and using a protocol other than TCP/IP, the method fails. To specify a port number other than 1433, include "server=machinename,port number" in the connection string, and use the TCP/IP protocol. + SET ANSI_NULLS ON + GO + SET QUOTED_IDENTIFIER ON + GO -> [!NOTE] -> The .NET Framework Data Provider for SQL Server requires the Security permission with "Allows calls to unmanaged assemblies" enabled ( with set to `UnmanagedCode`) to open a with SQL Debugging enabled. + CREATE TABLE [dbo].[Department]( + [DepartmentID] [int] IDENTITY(1,1) NOT NULL, + [Name] [nvarchar](50) NOT NULL, + [Budget] [money] NOT NULL, + [StartDate] [datetime] NOT NULL, + [Administrator] [int] NULL, + CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED ( + [DepartmentID] ASC + ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] + GO -## Examples - The following example creates a , opens it, and displays some of its properties. The connection is automatically closed at the end of the `using` block. + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) + VALUES (N'C1045', 2012, N'Calculus', 4, 7) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) + VALUES (N'C1061', 2012, N'Physics', 4, 1) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) + VALUES (N'C2021', 2012, N'Composition', 3, 2) + INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) + VALUES (N'C2042', 2012, N'Literature', 4, 2) + SET IDENTITY_INSERT [dbo].[Department] ON + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) + VALUES (1, N'Engineering', 350000.0000, CAST(0x0000999C00000000 AS DateTime), 2) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) + VALUES (2, N'English', 120000.0000, CAST(0x0000999C00000000 AS DateTime), 6) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) + VALUES (4, N'Economics', 200000.0000, CAST(0x0000999C00000000 AS DateTime), 4) + INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) + VALUES (7, N'Mathematics', 250024.0000, CAST(0x0000999C00000000 AS DateTime), 3) + SET IDENTITY_INSERT [dbo].[Department] OFF - [!code-csharp[SqlConnection_Open Example#1](~/../sqlclient/doc/samples/SqlConnection_Open.cs#1)] + ALTER TABLE [dbo].[Course] + WITH CHECK ADD + CONSTRAINT [FK_Course_Department] FOREIGN KEY([DepartmentID]) + REFERENCES [dbo].[Department] ([DepartmentID]) + GO -]]> - - - Cannot open a connection without specifying a data source or server. - - or - - The connection is already open. - - A connection-level error occurred while opening the connection. If the property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the method for more information. - - The tag in the app.config file has invalid or unknown elements. - There are two entries with the same name in the section. - - - The cancellation instruction. - An asynchronous version of , which opens a database connection with the property settings specified by the . The cancellation token can be used to request that the operation be abandoned before the connection timeout elapses. Exceptions will be propagated via the returned Task. If the connection timeout time elapses without successfully connecting, the returned Task will be marked as faulted with an Exception. The implementation returns a Task without blocking the calling thread for both pooled and non-pooled connections. - A task representing the asynchronous operation. - - , must return until the returned is completed. Then, if the connection was successful, must return . If the connection fails, must return . - - A call to will attempt to cancel or close the corresponding call. - - For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see [Asynchronous Programming](/sql/connect/ado-net/asynchronous-programming). - - ]]> - - Calling more than once for the same instance before task completion. - - A connection was not available from the connection pool before the connection time out elapsed. - Any error returned by SQL Server that occurred while opening the connection. - - - Gets the size (in bytes) of network packets used to communicate with an instance of SQL Server. - The size (in bytes) of network packets. The default value is 8000. - - ), which is sufficient for most data transfer operations. For most applications, the default packet size is best. - - may be a value in the range of 512 and 32767 bytes. An exception is generated if the value is outside this range. - - Setting the default value to a number greater than 8000 will cause the packets to use the MultiPage allocator on the instance of SQL Server instead of the much more efficient SinglePage allocator, reducing the overall scalability of the SQL Server. For more information on how SQL Server uses memory, see [Memory Management Architecture Guide](/sql/relational-databases/memory-management-architecture-guide). - - - -## Examples - The following example creates a , including setting the `Packet Size` to 512 in the connection string. It displays the and properties in the console window. - - [!code-csharp[SqlConnection_PacketSize Example#1](~/../sqlclient/doc/samples/SqlConnection_PacketSize.cs#1)] - - ]]> - - - - Dictionary of custom column encryption key store providers - - Registers the column encryption key store providers. This function should only be called once in an app. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. - - The built-in column master key store providers that are available for the Windows Certificate Store, CNG Store and CSP are pre-registered. - - - customKeyStoreProviders = new Dictionary(); - MySqlClientHSMProvider myProvider = new MySqlClientHSMProvider(); - customKeyStoreProviders.Add(@"HSM Provider", myProvider); - SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customKeyStoreProviders); - ``` - ]]> - - - A null dictionary was provided. - - -or- - - A string key in the dictionary was null or empty. - - -or- - - A value in the dictionary was null. - - - A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. - - - This function was called more than once. - - - - Dictionary of custom column encryption key providers - Registers the encryption key store providers on the instance. If this function has been called, any providers registered using the static methods will be ignored. This function can be called more than once. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. - - A null dictionary was provided. - - -or- - - A string key in the dictionary was null or empty. - - -or- - - A value in the dictionary was null. - - - A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. - - - - - - - Gets or sets a value that specifies the - - object bound to this command. - - - When set to null (default), the default non-retriable provider will be applied. - - - type. -2. Create a by using one of the following static methods of the class: - - - - - - - - -3. Assign the object to the `RetryLogicProvider` property. - -> [!NOTE] -> Detecting retriable exceptions is a vital part of the retry pattern. Before applying retry logic, it is important to investigate exceptions and choose a retry provider that best fits your scenario. First, log your exceptions and find transient faults. - -> [!NOTE] -> The connection **timeout** restarts for each execution of a connection open. There is no timing overlap between these two actions. - -> [!NOTE] -> The default retry logic provider is not enabled unless it is configured in an application configuration file. For more information, see [Configurable retry logic and configuration file](/sql/connect/ado-net/configurable-retry-logic-config-file-sqlclient). - -## Example -The following sample tries to open a connection to an invalid database to simulate a condition that the database service is temporarily unavailable . You should manually create the database while the tries to establish the connection. - -[!code-csharp[SqlConfigurableRetryLogic_OpenConnection#1](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_OpenConnection.cs#1)] - -]]> - - - - If statistics gathering is enabled, all values are reset to zero. - - - - - - Returns a name value pair collection of statistics at the point in time the method is called. - Returns a reference of type of items. - - - - - - Returns a name value pair collection of internal properties at the point in time the method is called. - Returns a reference of type of (string, object) items. - - - - - - Gets a string that contains the version of the instance of SQL Server to which the client is connected. - The version of the instance of SQL Server. - - was called while the returned Task was not completed and the connection was not opened after a call to . - - - -## Examples - The following example creates a and displays the property. - - [!code-csharp[SqlConnection_ServerVersion Example#1](~/../sqlclient/doc/samples/SqlConnection_ServerVersion.cs#1)] - - ]]> - - The connection is closed. - - was called while the returned Task was not completed and the connection was not opened after a call to . - - - Gets the server process Id (SPID) of the active connection. - The server process Id (SPID) of the active connection. - Returns 0 if the connection is inactive on the client side. - - - Indicates the state of the during the most recent network operation performed on the connection. - An enumeration. - - enumeration indicating the state of the . Closing and reopening the connection will refresh the value of . - - ]]> - - - - Occurs when the state of the connection changes. - - - When set to , enables statistics gathering for the current connection. - Returns if statistics gathering is enabled; otherwise . is the default. - - - - - - Begins a database transaction. - An object that represents the new transaction. - - or method. - ]]> - - - - One of the values. - Begins a database transaction with the specified value. - An object that represents the new transaction. - - or method. -]]> - - - - Creates and returns a Command object that is associated with the connection. - A Command object that is associated with the connection. - To be added. - - - Creates a new object that is a copy of the current instance. - A new object that is a copy of this instance. - - instance is cast to an interface. - - This member is only supported by the .NET Compact Framework. - - ]]> - - - - Gets a string that identifies the database client. - A string that identifies the database client. If not specified, the name of the client computer. If neither is specified, the value is an empty string. - - property corresponds to the `Workstation ID` connection string property. - - - -## Examples - The following example creates a and displays the property. - - [!code-csharp[SqlConnection_WorkstationId Example#1](~/../sqlclient/doc/samples/SqlConnection_WorkstationId.cs#1)] - - ]]> - - -
+ ALTER TABLE [dbo].[Course] + CHECK CONSTRAINT [FK_Course_Department] + GO + + + How to Get Schema Information from Database has C# and Visual Basic versions of this code sample in a Visual Studio project. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main(string[] args) + { + using (SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;")) + { + conn.Open(); + + // Get the Meta Data for Supported Schema Collections + DataTable metaDataTable = conn.GetSchema("MetaDataCollections"); + + Console.WriteLine("Meta Data for Supported Schema Collections:"); + ShowDataTable(metaDataTable, 25); + Console.WriteLine(); + + // Get the schema information of Databases in your instance + DataTable databasesSchemaTable = conn.GetSchema("Databases"); + + Console.WriteLine("Schema Information of Databases:"); + ShowDataTable(databasesSchemaTable, 25); + Console.WriteLine(); + + // First, get schema information of all the tables in current database; + DataTable allTablesSchemaTable = conn.GetSchema("Tables"); + + Console.WriteLine("Schema Information of All Tables:"); + ShowDataTable(allTablesSchemaTable, 20); + Console.WriteLine(); + + // You can specify the Catalog, Schema, Table Name, Table Type to get + // the specified table(s). + // You can use four restrictions for Table, so you should create a 4 members array. + String[] tableRestrictions = new String[4]; + + // For the array, 0-member represents Catalog; 1-member represents Schema; + // 2-member represents Table Name; 3-member represents Table Type. + // Now we specify the Table Name of the table what we want to get schema information. + tableRestrictions[2] = "Course"; + + DataTable courseTableSchemaTable = conn.GetSchema("Tables", tableRestrictions); + + Console.WriteLine("Schema Information of Course Tables:"); + ShowDataTable(courseTableSchemaTable, 20); + Console.WriteLine(); + + // First, get schema information of all the columns in current database. + DataTable allColumnsSchemaTable = conn.GetSchema("Columns"); + + Console.WriteLine("Schema Information of All Columns:"); + ShowColumns(allColumnsSchemaTable); + Console.WriteLine(); + + // You can specify the Catalog, Schema, Table Name, Column Name to get the specified column(s). + // You can use four restrictions for Column, so you should create a 4 members array. + String[] columnRestrictions = new String[4]; + + // For the array, 0-member represents Catalog; 1-member represents Schema; + // 2-member represents Table Name; 3-member represents Column Name. + // Now we specify the Table_Name and Column_Name of the columns what we want to get schema information. + columnRestrictions[2] = "Course"; + columnRestrictions[3] = "DepartmentID"; + + DataTable departmentIDSchemaTable = conn.GetSchema("Columns", columnRestrictions); + + Console.WriteLine("Schema Information of DepartmentID Column in Course Table:"); + ShowColumns(departmentIDSchemaTable); + Console.WriteLine(); + + // First, get schema information of all the IndexColumns in current database + DataTable allIndexColumnsSchemaTable = conn.GetSchema("IndexColumns"); + + Console.WriteLine("Schema Information of All IndexColumns:"); + ShowIndexColumns(allIndexColumnsSchemaTable); + Console.WriteLine(); + + // You can specify the Catalog, Schema, Table Name, Constraint Name, Column Name to + // get the specified column(s). + // You can use five restrictions for Column, so you should create a 5 members array. + String[] indexColumnsRestrictions = new String[5]; + + // For the array, 0-member represents Catalog; 1-member represents Schema; + // 2-member represents Table Name; 3-member represents Constraint Name;4-member represents Column Name. + // Now we specify the Table_Name and Column_Name of the columns what we want to get schema information. + indexColumnsRestrictions[2] = "Course"; + indexColumnsRestrictions[4] = "CourseID"; + + DataTable courseIdIndexSchemaTable = conn.GetSchema("IndexColumns", indexColumnsRestrictions); + + Console.WriteLine("Index Schema Information of CourseID Column in Course Table:"); + ShowIndexColumns(courseIdIndexSchemaTable); + Console.WriteLine(); + } + + Console.WriteLine("Please press any key to exit..."); + Console.ReadKey(); + } + + private static void ShowDataTable(DataTable table, Int32 length) + { + foreach (DataColumn col in table.Columns) + { + Console.Write("{0,-" + length + "}", col.ColumnName); + } + Console.WriteLine(); + + foreach (DataRow row in table.Rows) + { + foreach (DataColumn col in table.Columns) + { + if (col.DataType.Equals(typeof(DateTime))) + { + Console.Write("{0,-" + length + ":d}", row[col]); + } + else if (col.DataType.Equals(typeof(Decimal))) + { + Console.Write("{0,-" + length + ":C}", row[col]); + } + else { + Console.Write("{0,-" + length + "}", row[col]); + } + } + Console.WriteLine(); + } + } + + private static void ShowDataTable(DataTable table) + { + ShowDataTable(table, 14); + } + + private static void ShowColumns(DataTable columnsTable) + { + var selectedRows = from info in columnsTable.AsEnumerable() + select new + { + TableCatalog = info["TABLE_CATALOG"], + TableSchema = info["TABLE_SCHEMA"], + TableName = info["TABLE_NAME"], + ColumnName = info["COLUMN_NAME"], + DataType = info["DATA_TYPE"] + }; + + Console.WriteLine("{0,-15}{1,-15}{2,-15}{3,-15}{4,-15}", "TableCatalog", "TABLE_SCHEMA", + "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE"); + foreach (var row in selectedRows) + { + Console.WriteLine("{0,-15}{1,-15}{2,-15}{3,-15}{4,-15}", row.TableCatalog, + row.TableSchema, row.TableName, row.ColumnName, row.DataType); + } + } + + private static void ShowIndexColumns(DataTable indexColumnsTable) + { + var selectedRows = from info in indexColumnsTable.AsEnumerable() + select new + { + TableSchema = info["table_schema"], + TableName = info["table_name"], + ColumnName = info["column_name"], + ConstraintSchema = info["constraint_schema"], + ConstraintName = info["constraint_name"], + KeyType = info["KeyType"] + }; + + Console.WriteLine("{0,-14}{1,-11}{2,-14}{3,-18}{4,-16}{5,-8}", "table_schema", "table_name", "column_name", "constraint_schema", "constraint_name", "KeyType"); + foreach (var row in selectedRows) + { + Console.WriteLine("{0,-14}{1,-11}{2,-14}{3,-18}{4,-16}{5,-8}", row.TableSchema, + row.TableName, row.ColumnName, row.ConstraintSchema, row.ConstraintName, row.KeyType); + } + } + } + + + + is specified as null. + + + + + Specifies the name of the schema to return. + + + A set of restriction values for the requested schema. + + + Returns schema information for the data source of this using the specified string for the schema name and the specified string array for the restriction values. + + + A that contains schema information. + + + + The parameter can supply n depth of values, which are specified by the restrictions collection for a specific collection. In order to set values on a given restriction, and not set the values of other restrictions, you need to set the preceding restrictions to and then put the appropriate value in for the restriction that you would like to specify a value for. + + + An example of this is the "Tables" collection. If the "Tables" collection has three restrictions--database, owner, and table name--and you want to get back only the tables associated with the owner "Carl", you need to pass in the following values: null, "Carl". If a restriction value is not passed in, the default values are used for that restriction. This is the same mapping as passing in , which is different from passing in an empty string for the parameter value. In that case, the empty string ("") is considered to be the value for the specified parameter. + + + + For a code sample demonstrating , see . + + + is specified as null. + + + + + + Occurs when SQL Server returns a warning or informational message. + + + + Clients that want to process warnings or informational messages sent by the server should create an delegate to listen to this event. + + + The event occurs when a message with a severity of 10 or less is returned by SQL Server. Messages that have a severity between 11 and 20 raise an error and messages that have a severity over 20 causes the connection to close. For more information on SQL Server error levels, see Database Engine Error Severities. + For more information and an example, see Connection Events. + + + + + + To be added. + + + To be added. + + + To be added. + + + + + Opens a database connection with the property settings specified by the . + + + + The draws an open connection from the connection pool if one is available. Otherwise, it establishes a new connection to an instance of SQL Server. + + + If the goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling . + + + If you specify a port number other than 1433 when you are trying to connect to an instance of SQL Server and using a protocol other than TCP/IP, the method fails. To specify a port number other than 1433, include "server=machinename,port number" in the connection string, and use the TCP/IP protocol. + + + The .NET Framework Data Provider for SQL Server requires the Security permission with "Allows calls to unmanaged assemblies" enabled ( with set to UnmanagedCode) to open a with SQL Debugging enabled. + + + + + The following example creates a , opens it, and displays some of its properties. The connection is automatically closed at the end of the using block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + OpenSqlConnection(s); + Console.ReadLine(); + } + + private static void OpenSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + + Cannot open a connection without specifying a data source or server. + The connection is already open. + + + + + A connection-level error occurred while opening the connection. If the property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the method for more information. + + + The <system.data.localdb> tag in the app.config file has invalid or unknown elements. + + + + There are two entries with the same name in the <localdbinstances> section. + + + + + Options to override default connection open behavior. + + + Opens a database connection with the property settings specified by the . + + + + The draws an open connection from the connection pool if one is available. Otherwise, it establishes a new connection to an instance of SQL Server. If overrides are specified, the first open attempt will apply the specified overrides to the open action. + + + If the goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling . + + + If you specify a port number other than 1433 when you are trying to connect to an instance of SQL Server and using a protocol other than TCP/IP, the method fails. To specify a port number other than 1433, include "server=machinename,port number" in the connection string, and use the TCP/IP protocol. + + + The .NET Framework Data Provider for SQL Server requires the Security permission with "Allows calls to unmanaged assemblies" enabled ( with set to UnmanagedCode) to open a with SQL Debugging enabled. + + + + + The following example creates a , opens it, and displays some of its properties. The connection is automatically closed at the end of the using block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program1 + { + static void Main() + { + string s = GetConnectionString(); + + OpenSqlConnection(s); + Console.ReadLine(); + } + + private static void OpenSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + + + Cannot open a connection without specifying a data source or server. + The connection is already open. + + + + A connection-level error occurred while opening the connection. If the property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the method for more information. The <system.data.localdb> tag in the app.config file has invalid or unknown elements. + + + There are two entries with the same name in the <localdbinstances> section. + + + + + The cancellation instruction. + + + An asynchronous version of , which opens a database connection with the property settings specified by the . The cancellation token can be used to request that the operation be abandoned before the connection timeout elapses. Exceptions will be propagated via the returned Task. If the connection timeout time elapses without successfully connecting, the returned Task will be marked as faulted with an Exception. The implementation returns a Task without blocking the calling thread for both pooled and non-pooled connections. + + + A task representing the asynchronous operation. + + + + After calling , must return until the returned is completed. Then, if the connection was successful, must return . If the connection fails, must return . + + + A call to will attempt to cancel or close the corresponding call. For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + + + Calling more than once for the same instance before task completion. + + + A connection was not available from the connection pool before the connection time out elapsed. + + + + Any error returned by SQL Server that occurred while opening the connection. + + + + + Gets the size (in bytes) of network packets used to communicate with an instance of SQL Server. + + + The size (in bytes) of network packets. The default value is 8000. + + + + If an application performs bulk copy operations, or sends or receives lots of text or image data, a packet size larger than the default may improve efficiency because it causes fewer network read and write operations. If an application sends and receives small amounts of information, you can set the packet size to 512 bytes (using the Packet Size value in the ), which is sufficient for most data transfer operations. For most applications, the default packet size is best. may be a value in the range of 512 and 32767 bytes. An exception is generated if the value is outside this range. + + + Setting the default value to a number greater than 8000 will cause the packets to use the MultiPage allocator on the instance of SQL Server instead of the much more efficient SinglePage allocator, reducing the overall scalability of the SQL Server. For more information on how SQL Server uses memory, see Memory Management Architecture Guide. + + + + + The following example creates a , including setting the Packet Size to 512 in the connection string. It displays the and properties in the console window. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + OpenSqlConnection(); + Console.ReadLine(); + } + + private static void OpenSqlConnection() + { + string connectionString = GetConnectionString(); + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("PacketSize: {0}", connection.PacketSize); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;Packet Size=512"; + } + } + + + + + + Dictionary of custom column encryption key store providers + + + + Registers the column encryption key store providers. This function should only be called once in an app. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. + + + The built-in column master key store providers that are available for the Windows Certificate Store, CNG Store and CSP are pre-registered. + + + + + Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customKeyStoreProviders = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(); + MySqlClientHSMProvider myProvider = new MySqlClientHSMProvider(); + customKeyStoreProviders.Add(@"HSM Provider", myProvider); + SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customKeyStoreProviders); + + + + + A null dictionary was provided. + A string key in the dictionary was null or empty. + A value in the dictionary was null. + + + + A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. + + + This function was called more than once. + + + + + Dictionary of custom column encryption key providers + + + Registers the encryption key store providers on the instance. If this function has been called, any providers registered using the static methods will be ignored. This function can be called more than once. This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. + + + + Custom master key store providers can be registered with the driver at three different layers. The precedence of the three registrations is as follows: + + + + The per-command registration will be checked if it is not empty. + + + If the per-command registration is empty, the per-connection registration will be checked if it is not empty. + + + If the per-connection registration is empty, the global registration will be checked. + + + + Once any key store provider is found at a registration level, the driver will NOT fall back to the other registrations to search for a provider. If providers are registered but the proper provider is not found at a level, an exception will be thrown containing only the registered providers in the registration that was checked. + + + The built-in column master key store providers that are available for the Windows Certificate Store, CNG Store and CSP are pre-registered. + + + This does shallow copying of the dictionary so that the app cannot alter the custom provider list once it has been set. + + + + + A null dictionary was provided. + A string key in the dictionary was null or empty. + A value in the dictionary was null. + + + + A string key in the dictionary started with "MSSQL_". This prefix is reserved for system providers. + + + + + Gets or sets a value that specifies the object bound to this command. + + + When set to null (default), the default non-retryable provider will be applied. + + + + You must set the value for this property before opening the connection to take effect. + + + To apply the retry logic, do the following steps before opening the connection: + + + + Define the configuration parameters by using type. + + + Create a by using one of the following static methods of the class: + + + + + + + + + Assign the object to the RetryLogicProvider property. + + + + Detecting retryable exceptions is a vital part of the retry pattern. Before applying retry logic, it is important to investigate exceptions and choose a retry provider that best fits your scenario. First, log your exceptions and find transient faults. + + + The connection timeout restarts for each execution of a connection open. There is no timing overlap between these two actions. + + + The default retry logic provider is not enabled unless it is configured in an application configuration file. For more information, see Configurable retry logic and configuration file. + + + + + The following sample tries to open a connection to an invalid database to simulate a condition that the database service is temporarily unavailable . You should manually create the database while the tries to establish the connection. + + + + using System; + using Microsoft.Data.SqlClient; + + /// Detecting retriable exceptions is a vital part of the retry pattern. + /// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario. + /// First, log your exceptions and find transient faults. + /// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic. + class RetryLogicSample + { + private const string DefaultDB = "Northwind"; + private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;"; + private const string DropDatabaseFormat = "DROP DATABASE {0}"; + + // For general use + private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB)); + + static void Main(string[] args) + { + // 1. Define the retry logic parameters + var options = new SqlRetryLogicOption() + { + NumberOfTries = 5, + MaxTimeInterval = TimeSpan.FromSeconds(20), + DeltaTime = TimeSpan.FromSeconds(1) + }; + + // 2. Create a retry provider + var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options); + + // define the retrying event to report the execution attempts + provider.Retrying += (object s, SqlRetryingEventArgs e) => + { + int attempts = e.RetryCount + 1; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n"); + Console.ForegroundColor = ConsoleColor.DarkGray; + if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex) + { + Console.WriteLine($"{ex.Number}-{ex.Message}\n"); + } + else + { + Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n"); + } + + // It is not a good practice to do time-consuming tasks inside the retrying event which blocks the running task. + // Use parallel programming patterns to mitigate it. + if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1) + { + Console.WriteLine("This is the last chance to execute the command before throwing the exception."); + Console.WriteLine("Press Enter when you're ready:"); + Console.ReadLine(); + Console.WriteLine("continue ..."); + } + }; + + // Open the general connection. + s_generalConnection.Open(); + + try + { + // Assume the database is being created and other services are going to connect to it. + RetryConnection(provider); + } + catch + { + // exception is thrown if connecting to the database isn't successful. + throw; + } + } + + private static void ExecuteCommand(SqlConnection cn, string command) + { + using var cmd = cn.CreateCommand(); + cmd.CommandText = command; + cmd.ExecuteNonQuery(); + } + + private static void RetryConnection(SqlRetryLogicBaseProvider provider) + { + // Change this if you already have a database with the same name in your database. + string dbName = "Invalid_DB_Open"; + + // Create a connection to an invalid database. + using var cnn = new SqlConnection(string.Format(CnnStringFormat, dbName)); + // 3. Assign the `provider` to the connection + cnn.RetryLogicProvider = provider; + Console.WriteLine($"Connecting to the [{dbName}] ..."); + // Manually execute the following command in SSMS to create the invalid database while the SqlConnection is attempting to connect to it. + // >> CREATE DATABASE Invalid_DB_Open; + Console.WriteLine($"Manually, run the 'CREATE DATABASE {dbName};' in the SQL Server before exceeding the {provider.RetryLogic.NumberOfTries} attempts."); + // the connection tries to connect to the database 5 times + Console.WriteLine("The first attempt, before getting into the retry logic."); + cnn.Open(); + Console.WriteLine($"Connected to the [{dbName}] successfully."); + + cnn.Close(); + + // Drop it after test + ExecuteCommand(s_generalConnection, string.Format(DropDatabaseFormat, dbName)); + Console.WriteLine($"The [{dbName}] is removed."); + } + } + + + + + + If statistics gathering is enabled, all values are reset to zero. + + + If statistics gathering is not enabled and this method is called, no error is thrown. + + + + + Returns a name value pair collection of statistics at the point in time the method is called. + + + Returns a reference of type of items. + + + When this method is called, the values retrieved are those at the current point in time. If you continue using the connection, the values are incorrect. You need to re-execute the method to obtain the most current values. + + + + + Returns a name value pair collection of internal properties at the point in time the method is called. + + + Returns a reference of type of (string, object) items. + + + + When this method is called, the values retrieved are those at the current point in time. If you continue using the connection, the values are incorrect. You need to re-execute the method to obtain the most current values. + + + + Supported internal properties + Type + Information provided + Return value + + + SQLDNSCachingSupportedState + string + To indicate the IsSupported flag sent by the server for DNS Caching + "true", "false", "innerConnection is null!" + + + SQLDNSCachingSupportedStateBeforeRedirect + string + To indicate the IsSupported flag sent by the server for DNS Caching before redirection. + "true", "false", "innerConnection is null!" + + + + + + + Gets a string that contains the version of the instance of SQL Server to which the client is connected. + + + The version of the instance of SQL Server. + + + The version is of the form ##.##.####, where the first two digits are the major version, the next two digits are the minor version, and the last four digits are the release version. The string is of the form major.minor.build, where major and minor are exactly two digits and build is exactly four digits. was called while the returned Task was not completed and the connection was not opened after a call to . + + + + The following example creates a and displays the property. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace SqlConnection1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + CreateSqlConnection(connectionString); + Console.ReadLine(); + } + + private static void CreateSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + } + } + } + } + + + + The connection is closed. was called while the returned Task was not completed and the connection was not opened after a call to . + + + + + Gets the server process ID (SPID) of the active connection. + + + The server process ID (SPID) of the active connection. + + + Returns 0 if the connection is inactive on the client side. + + + + + Indicates the state of the during the most recent network operation performed on the connection. + + + An enumeration. + + + Returns an enumeration indicating the state of the . Closing and reopening the connection will refresh the value of . + + + + + When set to , enables statistics gathering for the current connection. + + + Returns if statistics gathering is enabled; otherwise . is the default. + + + Enabling statistics gathering has a minor, but measurable effect on performance and therefore should be enabled only when it is required. + + + + + Creates a new object that is a copy of the current instance. + + + A new object that is a copy of this instance. + + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + This member is only supported by the .NET Compact Framework. + + + + + + Gets a string that identifies the database client. + + + A string that identifies the database client. If not specified, the name of the client computer. If neither is specified, the value is an empty string. + + + The string typically contains the network name of the client. The property corresponds to the Workstation ID connection string property. + + + + The following example creates a and displays the property. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + + OpenSqlConnection(s); + Console.ReadLine(); + } + + private static void OpenSqlConnection(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("WorkstationId: {0}", connection.WorkstationId); + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI;"; + } + } + + + +
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionAttestationProtocol.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionAttestationProtocol.xml index db98ad4fdf..a2cbd38e2f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionAttestationProtocol.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionAttestationProtocol.xml @@ -1,25 +1,41 @@ - - - - - Specifies a value for Attestation Protocol. - - - - If the attestation protocol is not specified. Use this as default value. - 0 - - - Attestation portocol for Azure Attestation Service - 1 - - - Attestation protocol for no attestation. Only compatible with Virtualization-based security (VBS) enclaves. An Enclave Attestation Url is not required when using this protocol. - 2 - - - Attestation protocol for Host Guardian Service - 3 - - + + + + + Specifies a value for Attestation Protocol. + + + + + If the attestation protocol is not specified. Use this as default value. + + + 0 + + + + + Attestation protocol for Azure Attestation Service + + + 1 + + + + + Attestation protocol for no attestation. Only compatible with Virtualization-based security (VBS) enclaves. An Enclave Attestation Url is not required when using this protocol. + + + 2 + + + + + Attestation protocol for Host Guardian Service + + + 3 + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionColumnEncryptionSetting.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionColumnEncryptionSetting.xml index 7bb1126a6e..68dc82a65a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionColumnEncryptionSetting.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionColumnEncryptionSetting.xml @@ -1,15 +1,19 @@ - - - - - Note that these settings cannot be used to bypass encryption and gain access to plaintext data. For details, see Always Encrypted (Database Engine). - To be added. - - - Specifies the connection does not use Always Encrypted. Should be used if no queries sent over the connection access encrypted columns. - - - Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted. - - + + + + + Note that these settings cannot be used to bypass encryption and gain access to plaintext data. For details, see Always Encrypted (Database Engine). + + + + + Specifies the connection does not use Always Encrypted. Should be used if no queries sent over the connection access encrypted columns. + + + + + Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOption.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOption.xml index 35b8d24ab6..a582da8168 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOption.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOption.xml @@ -1,65 +1,79 @@ - - + - These options are used to control encryption behavior of the communication between the server and the client. + + These options are used to control encryption behavior of the communication between the server and the client. + - property. When converting from a boolean, a value of `true` converts to and a value of `false` converts to . When converting to a boolean, , , and `null` convert to `true` and converts `false`. - - ]]> + Implicit conversions have been added to maintain backwards compatibility with boolean behavior for the property. When converting from a boolean, a value of converts to and a value of converts to . When converting to a boolean, , , and convert to and converts . - Converts the specified string representation of a logical value to its equivalent. + Converts the specified string representation of a logical value to its equivalent. - A string containing the value to convert. + + A string containing the value to convert. + - An object that is equivalent to contained in . + An object that is equivalent to contained in . - Throws exception if provided is not convertible to type. + Throws exception if provided is not convertible to type. - Converts the specified string representation of a logical value to its equivalent and returns a value that indicates whether the conversion succeeded. + Converts the specified string representation of a logical value to its equivalent and returns a value that indicates whether the conversion succeeded. - A string containing the value to convert. + + A string containing the value to convert. + - An object that is equivalent to contained in . if conversion fails. + An object that is equivalent to contained in . if conversion fails. - if the parameter was converted successfully; otherwise, . + if the parameter was converted successfully; otherwise, . - This method does not throw an exception if conversion fails. + + This method does not throw an exception if conversion fails. + - Specifies that TLS encryption is optional when connecting to the server. If the server requires encryption, encryption will be negotiated. + + Specifies that TLS encryption is optional when connecting to the server. If the server requires encryption, encryption will be negotiated. + - Specifies that TLS encryption is required when connecting to the server. If the server doesn't support encryption, the connection will fail. + + Specifies that TLS encryption is required when connecting to the server. If the server doesn't support encryption, the connection will fail. + - Enables and requires TDS 8.0, TLS encryption to the server. If the server doesn't support TDS 8.0, TLS encryption, the connection will fail. + + Enables and requires TDS 8.0, TLS encryption to the server. If the server doesn't support TDS 8.0, TLS encryption, the connection will fail. + - The boolean value to be used for implicit comparison. + + The boolean value to be used for implicit comparison. + - Enables implicit converstion of a boolean to a . A value of converts to . A value of converts to . + Enables implicit conversion of a boolean to a . A value of converts to . A value of converts to . - The value to be used for implicit comparison. + + The value to be used for implicit comparison. + - Enables implicit converstion of a to a boolean. and convert to . converts to . + Enables implicit conversion of a to a boolean. and convert to . converts to . - Returns the string value of . + + Returns the string value of . + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml index e713cb776b..d806583ebc 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml @@ -1,40 +1,38 @@ - - - - - Specifies a value for IP address preference during a TCP connection. - - - - - - - - Specifies a value for IP address preference during a TCP connection. - - - - - - - Connects using IPv4 address(es) first. If the connection fails, try IPv6 address(es), if provided. This is the default value. - 0 - - - Connect using IPv6 address(es) first. If the connection fails, try IPv4 address(es), if available. - 1 - - - Connects with IP addresses in the order the underlying platform or operating system provides them. - 2 - - + + + + + Specifies a value for IP address preference during a TCP connection. + + + If Multi Subnet Failover or Transparent Network IP Resolution is set to true, this setting has no effect. + + + + + Specifies a value for IP address preference during a TCP connection. + + + If Multi Subnet Failover is set to true, this setting has no effect. + + + + + Connects using IPv4 address(es) first. If the connection fails, try IPv6 address(es), if provided. This is the default value. + + 0 + + + + Connect using IPv6 address(es) first. If the connection fails, try IPv4 address(es), if available. + + 1 + + + + Connects with IP addresses in the order the underlying platform or operating system provides them. + + 2 + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionOverrides.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionOverrides.xml index cf6c2afb93..8c563e08d3 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionOverrides.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionOverrides.xml @@ -1,17 +1,25 @@ - - - - - Specifies a value for Overrides. - - - - No overrides. - 0 - - - Disable transient fault handling during the initial SqlConnection Open attempt. - 1 - - + + + + + Specifies a value for Overrides. + + + + + No overrides. + + + 0 + + + + + Disable transient fault handling during the initial attempt. + + + 1 + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml index 82f7aa8ec9..406920d70a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml @@ -1,1117 +1,1921 @@ - - - - - Provides a simple way to create and manage the contents of connection strings used by the class. - - class to build and modify connection strings. The class also makes it easy to manage connection strings stored in an application configuration file. - - The performs checks for valid key/value pairs. Therefore, you cannot use this class to create invalid connection strings; trying to add invalid pairs will throw an exception. The class maintains a fixed collection of synonyms and can translate from a synonym to the corresponding well-known key name. - - For example, when you use the **Item** property to retrieve a value, you can specify a string that contains any synonym for the key you need. For example, you can specify "Network Address", "addr", or any other acceptable synonym for this key within a connection string when you use any member that requires a string that contains the key name, such as the **Item** property or the method. See the property for a full list of acceptable synonyms. - - The **Item** property handles tries to insert malicious entries. For example, the following code, using the default Item property (the indexer, in C#) correctly escapes the nested key/value pair: - -```vb -Dim builder As New Microsoft.Data.SqlClient.SqlConnectionStringBuilder -builder("Data Source") = "(local)" -builder("Integrated Security") = True -builder("Initial Catalog") = "AdventureWorks;NewValue=Bad" -Console.WriteLine(builder.ConnectionString) -``` - -```csharp -Microsoft.Data.SqlClient.SqlConnectionStringBuilder builder = - new Microsoft.Data.SqlClient.SqlConnectionStringBuilder(); -builder["Data Source"] = "(local)"; -builder["Integrated Security"] = true; -builder["Initial Catalog"] = "AdventureWorks;NewValue=Bad"; -Console.WriteLine(builder.ConnectionString); - -``` - - The result is the following connection string that handles the invalid value in a safe manner: - -``` -Source=(local);Initial Catalog="AdventureWorks;NewValue=Bad"; -Integrated Security=True -``` - - - -## Examples - The following console application builds connection strings for a SQL Server database. The code uses a class to create the connection string, and then passes the property of the instance to the constructor of the connection class. The example also parses an existing connection string and demonstrates various ways of manipulating the connection string's contents. - -> [!NOTE] -> This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. - - [!code-csharp[SqlConnectionStringBuilder#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder.cs#1)] - - ]]> - - - - Initializes a new instance of the class. - - - Initializes a new instance of the class. - To be added. - - - The basis for the object's internal connection information. Parsed into name/value pairs. Invalid key names raise . - Initializes a new instance of the class. The provided connection string provides the data for the instance's internal connection information. - - class provides a fixed internal collection of key/value pairs. Even if you supply only a small subset of the possible connection string values in the constructor, the object always provides default values for each key/value pair. When the `ConnectionString` property of the object is retrieved, the string contains only key/value pairs in which the value is not the default value for the item. - - - -## Examples - The following example supplies a simple SQL Server connection string in the object's constructor, and then iterates through all the key/value pairs within the object. Note that the collection provides default values for each item. Also note that the class converts synonyms for the well-known keys so that they are consistent with the well-known names. - -> [!NOTE] -> This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. - - [!code-csharp[SqlConnectionStringBuilder3#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder3.cs#1)] - - ]]> - - Invalid key name within the connection string. - Invalid value within the connection string (specifically, when a Boolean or numeric value was expected but not supplied). - The supplied is not valid. - - - Declares the application workload type when connecting to a database in an SQL Server Availability Group. You can set the value of this property with . For more information about SqlClient support for Always On Availability Groups, see [SqlClient Support for High Availability, Disaster Recovery](/sql/connect/ado-net/sql/sqlclient-support-high-availability-disaster-recovery). - Returns the current value of the property. - - - - Overview of the SqlClient driver - - - Gets or sets the name of the application associated with the connection string. - The name of the application. If no name has been supplied, "Framework Microsoft SqlClient Data Provider" when running on .NET Framework and "Core Microsoft SqlClient Data Provider" otherwise. - - and assigns a connection string in the object's constructor. The code displays the parsed and recreated version of the connection string, and then modifies the property of the object. Finally, the code displays the new connection string, including the new key/value pair. - - [!code-csharp[SqlConnectionStringBuilder.ApplicationName#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_ApplicationName.cs#1)] - - The sample displays the following text in the console window: - -``` -Original: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True -ApplicationName="Core Microsoft SqlClient Data Provider" -Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True;Application Name="My Application" -``` - - ]]> - - To set the value to null, use . - - - Gets or sets a string that contains the name of the primary data file. This includes the full path name of an attachable database. - The value of the property, or if no value has been supplied. - - instance, and sets the `AttachDBFilename` property in order to specify the name of an attached data file. - - [!code-csharp[DataWorks SqlConnectionStringBuilder_AttachDBFilename#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_AttachDBFilename.cs#1)] - - ]]> - - To set the value to null, use . - Working with Connection Strings - Overview of the SqlClient driver - - - Gets or sets the value of Attestation Protocol. - The attestation protocol. - - - Gets or sets the authentication method used for [Connecting to SQL Database By Using Azure Active Directory Authentication](https://azure.microsoft.com/documentation/articles/sql-database-aad-authentication/#7-connect-to-your-database-by-using-azure-active-directory-identities). - The authentication method of the connection string. - - - - - - Clears the contents of the instance. - - method removes all key/value pairs from the , and resets all corresponding properties. This includes setting the property to 0, and setting the property to an empty string. - - -## Examples - The following example demonstrates calling the method. This example populates the with some key/value pairs, and then calls the method and shows the results. - - [!code-csharp[DataWorks SqlConnectionStringBuilder_Clear#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_Clear.cs#1)] - - ]]> - - - - Gets or sets the column encryption settings for the connection string builder. - The column encryption settings for the connection string builder.This property enables or disables [Always Encrypted](/sql/relational-databases/security/encryption/always-encrypted-database-engine) functionality for the connection. - - - - The default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. - - - The time in seconds to wait for the command to execute. The default is 30 seconds. - - - connection string. - - Valid values are greater than or equal to 0 and less than or equal to 2147483647. - - ]]> - - The value set is less than 0. - - - Obsolete. Gets or sets a Boolean value that indicates whether the connection is reset when drawn from the connection pool. - The value of the property, or true if no value has been supplied. - - connection string, which has been removed from version 3.5 SP1 of the .NET Framework. - - ]]> - - - - The number of reconnections attempted after identifying that there was an idle connection failure. This must be an integer between 0 and 255. Default is 1. Set to 0 to disable reconnecting on idle connection failures. An will be thrown if set to a value outside of the allowed range. - The number of reconnections attempted after identifying that there was an idle connection failure. - - - connection string. - - ]]> - - - - - Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure. This must be an integer between 1 and 60. The default is 10 seconds. - Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure. - Value is outside of the allowed range. - - - connection string. - -This value is applied after the first reconnection attempt. When a broken connection is detected, the client immediately attempts to reconnect; this is the first reconnection attempt and only occurs if `ConnectRetryCount` is greater than 0. If the first reconnection attempt fails and `ConnectRetryCount` is greater than 1, the client waits `ConnectRetryInterval` to try the second and subsequent reconnection attempts. - - ]]> - - - - - Gets or sets the length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error. - The value of the property, or 15 seconds if no value has been supplied. - - property, and then displays the new connection string. - - [!code-csharp[SqlConnectionStringBuilder_ConnectTimeout#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_ConnectTimeout.cs#1)] - - ]]> - - - - The key to locate in the . - Determines whether the contains a specific key. - true if the contains an element that has the specified key; otherwise, false. - - contains a fixed-size collection of key/value pairs, the method determines only if a particular key name is valid. - - - -## Examples - The following example creates a instance, sets some of its properties, and then tries to determine whether various keys exist within the object by calling the **ContainsKey** method. - - [!code-csharp[SqlConnectionStringBuilder_ContainsKey#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_ContainsKey.cs#1)] - - The example displays the following output in the console window: - -``` -Connection string = Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True -True -True -True -False -``` - - ]]> - - - is null ( in Visual Basic) - - - Obsolete. Gets or sets a value that indicates whether a client/server or in-process connection to SQL Server should be made. - The value of the property, or if none has been supplied. - - [!NOTE] -> The property returns `null` if the connection string for the is "context connection=true". - - ]]> - - - - Gets or sets the language used for database server warning or error messages.. - The value of the property, or if no value has been supplied. - - - - To set the value to null, use . - - - Gets or sets the name or network address of the instance of SQL Server to connect to. - The value of the property, or if none has been supplied. - - \\ -- tcp:\,\ - -The TCP format must start with the prefix "tcp:" and is followed by the database instance, as specified by a host name and an instance name. This format is not applicable when connecting to Azure SQL Database. TCP is automatically selected for connections to Azure SQL Database when no protocol is specified. - -The host name MUST be specified in one of the following ways: -- NetBIOSName -- IPv4Address -- IPv6Address - -The instance name is used to resolve to a particular TCP/IP port number on which a database instance is hosted. Alternatively, specifying a TCP/IP port number directly is also allowed. If both instance name and port number are not present, the default database instance is used. - -The Named Pipes format is as follows: -- np:\\\\\pipe\\ - -The Named Pipes format MUST start with the prefix "np:" and is followed by a named pipe name. - -The host name MUST be specified in one of the following ways: - -- NetBIOSName -- IPv4Address -- IPv6Address - -The pipe name is used to identify the database instance to which the .NET application will connect. - -If the value of the **Network** key is specified, the prefixes "tcp:" and "np:" should not be specified. **Note:** You can force the use of TCP instead of shared memory, either by prefixing **tcp:** to the server name in the connection string, or by using **localhost**. - - -## Examples - The following example demonstrates that the class converts synonyms for the "Data Source" connection string key into the well-known key: - - [!code-csharp[SqlConnectionStringBuilder_DataSource#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_DataSource.cs#1)] - - ]]> - - To set the value to null, use . - - - Gets or sets the enclave attestation URL to be used with enclave based Always Encrypted. - The enclave attestation URL. - - - Gets or sets a value since version 5.0 or a value for the earlier versions that indicates whether TLS encryption is required for all data sent between the client and server. - The value of the property. - - , or `true`, the server name (or IP address) in a server's TLS certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. For information about support for certificates whose subject starts with a wildcard character (*), see [Enable encrypted connections to the Database Engine](/sql/database-engine/configure-windows/enable-encrypted-connections-to-the-database-engine#certificate-requirements). - -> [!NOTE] -> Starting from **version 4.0**, the default value of the property `Encrypt` is set to `true` while it is `false` for earlier versions. - -> [!NOTE] -> Starting from **version 5.0**, the data type is updated to , and the default value of the `Encrypt` property is set to . - - ]]> - - Working with Connection Strings - Overview of the SqlClient driver - - - Gets or sets a Boolean value that indicates whether the SQL Server connection pooler automatically enlists the connection in the creation thread's current transaction context. - The value of the property, or if none has been supplied. - - - - - - Gets or sets the name or address of the partner server to connect to if the primary server is down. - The value of the property, or if none has been supplied. - To set the value to null, use . - - - - - - Gets or sets the service principal name (SPN) of the failover partner for the connection. - - The value of the property, or if none has been supplied. - - - - [!NOTE] -> This property only applies when using Integrated Security mode, otherwise it is ignored. - - ]]> - - - - - Gets or sets the host name to use when validating the server certificate for the connection. When not specified, the server name from the `Data Source` is used for certificate validation. (Only available in v5.0+) - - The value of the property, or if none has been supplied. - - - - [!NOTE] -> This property only applies when using `Encrypt` in or mode, otherwise it is ignored. - - ]]> - - - - - To be added. - To be added. - To be added. - - - Gets or sets the name of the database associated with the connection. - The value of the property, or if none has been supplied. - - class to add the name of the database to the connection string. The code displays the contents of the property, just to verify that the class was able to convert from the synonym ("Database") to the appropriate property value. - - [!code-csharp[SqlConnectionStringBuilder_InitialCatalog#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_InitialCatalog.cs#1)] - - ]]> - - To set the value to null, use . - - - Gets or sets a Boolean value that indicates whether User ID and Password are specified in the connection (when ) or whether the current Windows account credentials are used for authentication (when ). - The value of the property, or if none has been supplied. - - is a more secure way to specify credentials for a connection that uses SQL Server Authentication (`Integrated Security=false`). - - -## Examples - The following example converts an existing connection string from using SQL Server Authentication to using integrated security. The example does its work by removing the user name and password from the connection string and then setting the property of the object. - -> [!NOTE] -> This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. - - [!code-csharp[SqlConnectionStringBuilder_IntegratedSecurity#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_IntegratedSecurity.cs#1)] - - ]]> - - - - Gets or sets the IP address family preference when establishing TCP connections. - Returns the IP address preference. - - - - - - Gets a value that indicates whether the has a fixed size. - - in every case, because the supplies a fixed-size collection of key/value pairs. - To be added. - Working with Connection Strings - Overview of the SqlClient driver - - - The key of the item to get or set. - Gets or sets the value associated with the specified key. In C#, this property is the indexer. - The value associated with the specified key. - - contains a fixed-size dictionary, trying to add a key that does not exist within the dictionary throws a . - - - -## Examples - The following code, in a console application, creates a new and adds key/value pairs to its connection string, using the property. - - [!code-csharp[SqlConnectionStringBuilder2#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder2.cs#1)] - - ]]> - - - is a null reference ( in Visual Basic). - Tried to add a key that does not exist within the available keys. - Invalid value within the connection string (specifically, a Boolean or numeric value was expected but not supplied). - - - Gets an that contains the keys in the . - An that contains the keys in the . - - is unspecified, but it is the same order as the associated values in the returned by the property. - - - -## Examples - The following console application example creates a new . The code loops through the returned by the property displaying the key/value pairs. - - [!code-csharp[SqlConnectionStringBuilder_Keys#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_Keys.cs#1)] - - ]]> - - - - - - Gets or sets the minimum time, in seconds, for the connection to live in the connection pool before being destroyed. - The value of the property, or 0 if none has been supplied. - - - - - - Gets or sets the maximum number of connections allowed in the connection pool for this specific connection string. - The value of the property, or 100 if none has been supplied. - - - - - - Gets or sets the minimum number of connections allowed in the connection pool for this specific connection string. - The value of the property, or 0 if none has been supplied. - - - - - - When true, an application can maintain multiple active result sets (MARS). When false, an application must process or cancel all result sets from one batch before it can execute any other batch on that connection. For more information, see [Multiple Active Result Sets (MARS)](https://msdn.microsoft.com//library/cfa084cz.aspx). - The value of the property, or if none has been supplied. - - - - - - If your application is connecting to an AlwaysOn availability group (AG) on different subnets, setting MultiSubnetFailover=true provides faster detection of and connection to the (currently) active server. For more information about SqlClient support for Always On Availability Groups, see [SqlClient Support for High Availability, Disaster Recovery](/sql/connect/ado-net/sql/sqlclient-support-high-availability-disaster-recovery). - Returns indicating the current value of the property. - - - - - - Gets or sets a string that contains the name of the network library used to establish a connection to the SQL Server. - The value of the property, or if none has been supplied. - - - - To set the value to null, use . - - - Gets or sets the size in bytes of the network packets used to communicate with an instance of SQL Server. - The value of the property, or 8000 if none has been supplied. - - - - - - Gets or sets the password for the SQL Server account. - The value of the property, or if none has been supplied. - - is a more secure way to specify credentials for a connection that uses SQL Server Authentication. - - If has not been set and you retrieve the value, the return value is . To reset the password for the connection string, pass null to the Item property. - -The password must be 128 characters or less. - - -## Examples - The following example shows how to set . - - [!code-csharp[SqlConnectionStringBuilder_Password#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_Password.cs#1)] - - ]]> - - The password was incorrectly set to null. See code sample below. - - - Gets or sets a Boolean value indicating if security-sensitive information, such as the password or access token, should be returned as part of the connection string on a connection created with this after that connection has ever been in an open state. This property should only be set to if your application has a specific need to read the password out of an already-opened database connection. The default value of is the more secure setting; using for this property opens your application to security risks such as accidentally logging or tracing the database password. - The value of the property, or if none has been supplied. - - - - - - The blocking period behavior for a connection pool. - The available blocking period settings. - - - enumeration for available settings. - - ]]> - - - - Gets or sets a Boolean value that indicates whether the connection will be pooled or explicitly opened every time that the connection is requested. - The value of the property, or if none has been supplied. - - - - - - The key of the key/value pair to be removed from the connection string in this . - Removes the entry with the specified key from the instance. - - if the key existed within the connection string and was removed; if the key did not exist. - - instance. Because the maintains a fixed-size collection of key/value pairs, calling the method simply resets the value of the key/value pair back to its default value. - - Because the collection of keys supported by the is fixed, every item within the collection has a known default value. The following table lists the keys, and the value for each when the is first initialized, or after the method has been called. - -|Key|Default value| -|---------|-------------------| -|Application Name|"Framework Microsoft SqlClient Data Provider" when running on .NET Framework. "Core Microsoft SqlClient Data Provider" otherwise.| -|AttachDBFilename|Empty string| -|Connection Timeout|15| -|Context Connection(Obsolete)|False| -|Current Language|Empty string| -|Data Source|Empty string| -|Encrypt|False in versions prior to 4.0, True in versions 4.0 and up| -|Enlist|True| -|Failover Partner|Empty string| -|Initial Catalog|Empty string| -|Integrated Security|False| -|Load Balance Timeout|0| -|Max Pool Size|100| -|Min Pool Size|0| -|MultipleActiveResultSets|False| -|Network Library|Empty string| -|Packet Size|8000| -|Password|Empty string| -|Persist Security Info|False| -|Pooling|True| -|Replication|False| -|Transaction Binding|Implicit Unbind| -|User ID|Empty string| -|User Instance|False| -|Workstation ID|Empty string| - - - -## Examples - The following example converts an existing connection string from using Windows Authentication to using integrated security. The example works by removing the user name and password from the connection string, and then setting the property of the object. - -> [!NOTE] -> This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. - - [!code-csharp[SqlConnectionStringBuilder_Remove#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_Remove.cs#1)] - - The example displays the following text in the console window: - -``` -Original: Data Source=(local);Initial Catalog=AdventureWorks;User ID=ab;Password= a1Pass@@11 -Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True -Database = AdventureWorks -``` - - ]]> - - - is null ( in Visual Basic) - - - Gets or sets a Boolean value that indicates whether replication is supported using the connection. - The value of the property, or false if none has been supplied. - - - - - - Gets or sets the path to a certificate file to match against the SQL Server TLS/SSL certificate for the connection. The accepted certificate formats are PEM, DER, and CER. If specified, the SQL Server certificate is checked by verifying if the `ServerCertificate` provided is an exact match. (Only available in v5.1+) - - The value of the property, or if none has been supplied. - - - - [!NOTE] -> This property only applies when using `Encrypt` in or mode, otherwise it is ignored. - - ]]> - - - - - Gets or sets the service principal name (SPN) of the data source. - - The value of the property, or if none has been supplied. - - - - [!NOTE] -> This property only applies when using Integrated Security mode, otherwise it is ignored. - - ]]> - - - - - The key to locate in the . - Indicates whether the specified key exists in this instance. - - if the contains an entry with the specified key; otherwise, . - - method. - - ]]> - - - - Gets or sets a string value that indicates how the connection maintains its association with an enlisted transaction. - The value of the property, or `Implicit Unbind` if none has been supplied. - - control how a binds to an enlisted . - - The following table shows the possible values for the property: - -|Value|Description| -|-----------|-----------------| -|Implicit Unbind|The default. Causes the connection to detach from the transaction when it ends. After detaching, additional requests on the connection are performed in autocommit mode. The property is not checked when executing requests while the transaction is active. After the transaction has ended, additional requests are performed in autocommit mode.| -|Explicit Unbind|Causes the connection to remain attached to the transaction until the connection is closed or until is called with a `null` (`Nothing` in Visual Basic) value. An is thrown if is not the enlisted transaction or if the enlisted transaction is not active. This behavior enforces the strict scoping rules required for support.| - - ]]> - - - - When the value of this key is set to , the application is required to retrieve all IP addresses for a particular DNS entry and attempt to connect with the first one in the list. If the connection is not established within 0.5 seconds, the application will try to connect to all others in parallel. When the first answers, the application will establish the connection with the respondent IP address. - A boolean value. - - - - - - Gets or sets a value that indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust. - A boolean. The default is `false`. - - - - - - The key of the item to retrieve. - The value corresponding to . - Retrieves a value corresponding to the supplied key from this . - - if was found within the connection string; otherwise, . - - method lets developers safely retrieve a value from a without needing to verify that the supplied key name is a valid key name. Because **TryGetValue** does not raise an exception when you call it, passing in a nonexistent key, you do not have to look for a key before retrieving its value. Calling **TryGetValue** with a nonexistent key will place the value null (`Nothing` in Visual Basic) in the `value` parameter. - -## Examples - The following example demonstrates the behavior of the **TryGetValue** method. - - [!code-csharp[SqlConnectionStringBuilder_TryGetValue#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_TryGetValue.cs#1)] - - The sample displays the following results: - -``` -Data Source=(local) -Trusted_Connection=True -Unable to retrieve value for 'InvalidKey' -Unable to retrieve value for null key. -``` - - ]]> - - - contains a null value ( in Visual Basic). - - - Gets or sets a string value that indicates the type system the application expects. - The following table shows the possible values for the property: - - Value - - Description - - SQL Server 2005 - - Uses the SQL Server 2005 type system. No conversions are made for the current version of ADO.NET. - - SQL Server 2008 - - Uses the SQL Server 2008 type system. - - Latest - - Use the latest version than this client-server pair can handle. This will automatically move forward as the client and server components are upgraded. - - - - - - - - Gets or sets the user ID to be used when connecting to SQL Server. - The value of the property, or if none has been supplied. - - is a more secure way to specify credentials for a connection that uses SQL Server Authentication. - - The user ID must be 128 characters or less. - - ]]> - - To set the value to null, use . - - - Gets or sets a value that indicates whether to redirect the connection from the default SQL Server Express instance to a runtime-initiated instance running under the account of the caller. - The value of the property, or if none has been supplied. - - [!NOTE] -> This feature is available only with the SQL Server Express Edition. For more information on user instances, see [SQL Server Express User Instances](/sql/connect/ado-net/sql/sql-server-express-user-instances). - - ]]> - - To set the value to null, use . - - - Gets an that contains the values in the . - An that contains the values in the . - - is unspecified, but it is the same order as the associated keys in the returned by the property. Because each instance of the always contains the same fixed set of keys, the property always returns the values corresponding to the fixed set of keys, in the same order as the keys. - - - -## Examples - The following example first creates a new , and then iterates through all the values within the object. - - [!code-csharp[SqlConnectionStringBuilder_Values#1](~/../sqlclient/doc/samples/SqlConnectionStringBuilder_Values.cs#1)] - - ]]> - - - - - Gets or sets the name of the workstation connecting to SQL Server. - The value of the property, or if none has been supplied. - - - - To set the value to null, use . - - + + + + + Provides a simple way to create and manage the contents of connection strings used by the class. + + + + The connection string builder lets developers programmatically create syntactically correct connection strings, and parse and rebuild existing connection strings, using properties and methods of the class. The connection string builder provides strongly typed properties corresponding to the known key/value pairs allowed by SQL Server. Developers needing to create connection strings as part of applications can use the class to build and modify connection strings. The class also makes it easy to manage connection strings stored in an application configuration file. + + + The performs checks for valid key/value pairs. Therefore, you cannot use this class to create invalid connection strings; trying to add invalid pairs will throw an exception. The class maintains a fixed collection of synonyms and can translate from a synonym to the corresponding well-known key name. + + + For example, when you use the property to retrieve a value, you can specify a string that contains any synonym for the key you need. For example, you can specify "Network Address", "addr", or any other acceptable synonym for this key within a connection string when you use any member that requires a string that contains the key name, such as the property or the method. See the property for a full list of acceptable synonyms. + + + The property handles tries to insert malicious entries. For example, the following code, using the default Item property (the indexer, in C#) correctly escapes the nested key/value pair: + + + Dim builder As New Microsoft.Data.SqlClient.SqlConnectionStringBuilder + builder("Data Source") = "(local)" + builder("Integrated Security") = True + builder("Initial Catalog") = "AdventureWorks;NewValue=Bad" + Console.WriteLine(builder.ConnectionString) + + + Microsoft.Data.SqlClient.SqlConnectionStringBuilder builder = + new Microsoft.Data.SqlClient.SqlConnectionStringBuilder(); + builder["Data Source"] = "(local)"; + builder["Integrated Security"] = true; + builder["Initial Catalog"] = "AdventureWorks;NewValue=Bad"; + Console.WriteLine(builder.ConnectionString); + + + The result is the following connection string that handles the invalid value in a safe manner: + + + Source=(local);Initial Catalog="AdventureWorks;NewValue=Bad"; Integrated Security=True + + + + + The following console application builds connection strings for a SQL Server database. The code uses a class to create the connection string, and then passes the property of the instance to the constructor of the connection class. The example also parses an existing connection string and demonstrates various ways of manipulating the connection string's contents. + + + This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + // Create a new SqlConnectionStringBuilder and + // initialize it with a few name/value pairs. + SqlConnectionStringBuilder builder = + new SqlConnectionStringBuilder(GetConnectionString()); + + // The input connection string used the + // Server key, but the new connection string uses + // the well-known Data Source key instead. + Console.WriteLine(builder.ConnectionString); + + // Pass the SqlConnectionStringBuilder an existing + // connection string, and you can retrieve and + // modify any of the elements. + builder.ConnectionString = "server=(local);user id=ab;" + + "password= a!Pass113;initial catalog=AdventureWorks"; + + // Now that the connection string has been parsed, + // you can work with individual items. + Console.WriteLine(builder.Password); + builder.Password = "new@1Password"; + + // You can refer to connection keys using strings, + // as well. When you use this technique (the default + // Item property in Visual Basic, or the indexer in C#), + // you can specify any synonym for the connection string key + // name. + builder["Server"] = "."; + builder["Connect Timeout"] = 1000; + builder["Trusted_Connection"] = true; + Console.WriteLine(builder.ConnectionString); + + Console.WriteLine("Press Enter to finish."); + Console.ReadLine(); + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Server=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + Initializes a new instance of the class. + + + + + The basis for the object's internal connection information. Parsed into name/value pairs. Invalid key names raise . + + + Initializes a new instance of the class. The provided connection string provides the data for the instance's internal connection information. + + + The class provides a fixed internal collection of key/value pairs. Even if you supply only a small subset of the possible connection string values in the constructor, the object always provides default values for each key/value pair. When the property of the object is retrieved, the string contains only key/value pairs in which the value is not the default value for the item. + + + + The following example supplies a simple SQL Server connection string in the object's constructor, and then iterates through all the key/value pairs within the object. Note that the collection provides default values for each item. Also note that the class converts synonyms for the well-known keys so that they are consistent with the well-known names. + + + This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = "Server=(local);Database=AdventureWorks;UID=ab;Pwd= a!Pass@@"; + Console.WriteLine("Original: " + connectString); + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Modified: " + builder.ConnectionString); + + foreach (string key in builder.Keys) + { + Console.WriteLine(key + "=" + builder[key].ToString()); + } + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + + } + catch (System.Collections.Generic.KeyNotFoundException ex) + { + Console.WriteLine("KeyNotFoundException: " + ex.Message); + } + catch (System.FormatException ex) + { + Console.WriteLine("Format exception: " + ex.Message); + } + } + } + + + + Invalid key name within the connection string. + + + Invalid value within the connection string (specifically, when a Boolean or numeric value was expected but not supplied). + + + The supplied is not valid. + + + + + Declares the application workload type when connecting to a database in an SQL Server Availability Group. You can set the value of this property with . For more information about SqlClient support for Always On Availability Groups, see SqlClient Support for High Availability, Disaster Recovery. + + + Returns the current value of the property. + + + + This property corresponds to the Application Intent and ApplicationIntent keys within the connection string. + + + The default value is ApplicationIntent.ReadWrite . + + + + Overview of the SqlClient driver + + + + + Gets or sets the name of the application associated with the connection string. + + + The name of the application. If no name has been supplied, "Framework Microsoft SqlClient Data Provider" when running on .NET Framework and "Core Microsoft SqlClient Data Provider" otherwise. + + + + This property corresponds to the "Application Name" and "app" keys within the connection string. + + + An application name can be 128 characters or fewer. + + + + + The following example creates a new and assigns a connection string in the object's constructor. The code displays the parsed and recreated version of the connection string, and then modifies the property of the object. Finally, the code displays the new connection string, including the new key/value pair. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = "Server=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=true"; + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + Console.WriteLine("ApplicationName={0}", builder.ApplicationName); + + builder.ApplicationName = "My Application"; + Console.WriteLine("Modified: " + builder.ConnectionString); + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } + + + The sample displays the following text in the console window: + + + Original: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True;ApplicationName="Core Microsoft SqlClient Data Provider" + Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True;Application Name="My Application" + + + + To set the value to null, use . + + + + + Gets or sets a string that contains the name of the primary data file. This includes the full path name of an attachable database. + + + The value of the property, or if no value has been supplied. + + + + This property corresponds to the "AttachDBFilename", "extended properties", and "initial file name" keys within the connection string. AttachDBFilename is only supported for primary data files with an .mdf extension. + + + If the value of the AttachDBFileName key is specified in the connection string, the database is attached and becomes the default database for the connection. If this key is not specified and if the database was previously attached, the database will not be reattached. The previously attached database will be used as the default database for the connection. If this key is specified together with the AttachDBFileName key, the value of this key will be used as the alias. However, if the name is already used in another attached database, the connection will fail. + + + The path may be absolute or relative by using the DataDirectory substitution string. If DataDirectory is used, the database file must exist within a subdirectory of the directory pointed to by the substitution string. Note: Remote server, HTTP, and UNC path names are not supported. + + + The database name must be specified with the keyword 'database' (or one of its aliases) as in the following: "AttachDbFileName=|DataDirectory|\data\YourDB.mdf;integrated security=true;database=YourDatabase" An error will be generated if a log file exists in the same directory as the data file and the 'database' keyword is used when attaching the primary data file. In this case, remove the log file. Once the database is attached, a new log file will be automatically generated based on the physical path. + + + + + The following example creates a new instance, and sets the AttachDBFilename property in order to specify the name of an attached data file. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = + "Server=(local);" + + "Integrated Security=true"; + SqlConnectionStringBuilder builder = + new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + Console.WriteLine("AttachDBFileName={0}", builder.AttachDBFilename); + + builder.AttachDBFilename = @"C:\MyDatabase.mdf"; + Console.WriteLine("Modified: " + builder.ConnectionString); + + using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) + { + connection.Open(); + // Now use the open connection. + Console.WriteLine("Database = " + connection.Database); + } + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } + + + + To set the value to null, use . + + + Working with Connection Strings + + + Overview of the SqlClient driver + + + + + Gets or sets the value of Attestation Protocol. + + + The attestation protocol. + + + When no value is specified, secure enclaves are disabled on the connection. + + + + + Gets or sets the authentication method used for Connecting to SQL Database By Using Azure Active Directory Authentication. + + + The authentication method of the connection string. + + + For more information, see Using Azure Active Directory authentication with SqlClient. + + + + + Clears the contents of the instance. + + + The method removes all key/value pairs from the , and resets all corresponding properties. This includes setting the property to 0, and setting the property to an empty string. + + + + The following example demonstrates calling the method. This example populates the with some key/value pairs, and then calls the method and shows the results. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder.DataSource = "(local)"; + builder.IntegratedSecurity = true; + builder.InitialCatalog = "AdventureWorks"; + Console.WriteLine("Initial connection string: " + builder.ConnectionString); + + builder.Clear(); + Console.WriteLine("After call to Clear, count = " + builder.Count); + Console.WriteLine("Cleared connection string: " + builder.ConnectionString); + Console.WriteLine(); + + Console.WriteLine("Press Enter to continue."); + Console.ReadLine(); + } + } + + + + + + Gets or sets the column encryption settings for the connection string builder. + + + The column encryption settings for the connection string builder.This property enables or disables Always Encrypted functionality for the connection. + + + + + The default wait time (in seconds) before terminating the attempt to execute a command and generating an error. The default is 30 seconds. + + + The time in seconds to wait for the command to execute. The default is 30 seconds. + + + + This property corresponds to the Command Timeout key within the connection string. + + + Valid values are greater than or equal to 0 and less than or equal to 2147483647. + + + + The value set is less than 0. + + + + + Obsolete. Gets or sets a Boolean value that indicates whether the connection is reset when drawn from the connection pool. + + + The value of the property, or true if no value has been supplied. + + + This property corresponds to the "Connection Reset" key within the connection string, which has been removed from version 3.5 SP1 of the .NET Framework. + + + + + The number of reconnections attempted after identifying that there was an idle connection failure. This must be an integer between 0 and 255. The default value for non Azure endpoints is 1. For Azure SQL endpoints, the default is 2. Starting in version 5.x, for Azure SQL serverless or on demand endpoints, the default is 5 to improve connection success for connections to an idle or paused instance. Set to 0 to disable reconnecting on idle connection failures. An will be thrown if set to a value outside the allowed range. + + + The number of reconnections attempted after identifying that there was an idle connection failure. + + + + This property corresponds to the Connect Retry Count key within the connection string. + + + Since version 5.x the default value for none Azure endpoints is 1 and for Azure SQL and Azure Synapse has increased to 2 and 5 to improve the recovery against on high demand Azure endpoints. It should be detected first, and Synapse could be detected as a regular Azure SQL DB endpoint. + + + + + + Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure. This must be an integer between 1 and 60. The default is 10 seconds. + + + Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure. + + + Value is outside the allowed range. + + + + This property corresponds to the "Connect Retry Interval" key within the connection string. + + + This value is applied after the first reconnection attempt. When a broken connection is detected, the client immediately attempts to reconnect; this is the first reconnection attempt and only occurs if is greater than 0. If the first reconnection attempt fails and is greater than 1, the client waits ConnectRetryInterval to try the second and subsequent reconnection attempts. + + + + + + Gets or sets the length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error. + + + The value of the property, or 15 seconds if no value has been supplied. + + + + This property corresponds to the "Connect Timeout", "connection timeout", and "timeout" keys within the connection string. + + + When opening a connection to a Azure SQL Database, set the connection timeout to 30 seconds. Valid values are greater than or equal to 0 and less than or equal to 2147483647. + + + + + The following example first displays the contents of a connection string that does not specify the "Connect Timeout" value, sets the property, and then displays the new connection string. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = + "Server=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=true"; + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + Console.WriteLine("ConnectTimeout={0}", + builder.ConnectTimeout); + builder.ConnectTimeout = 100; + Console.WriteLine("Modified: " + builder.ConnectionString); + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } + + + + + + The key to locate in the . + + + Determines whether the contains a specific key. + + + if the contains an element that has the specified key; otherwise, . + + + + Because the contains a fixed-size collection of key/value pairs, the method determines only if a particular key name is valid. + + + + + The following example creates a instance, sets some of its properties, and then tries to determine whether various keys exist within the object by calling the ContainsKey method. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(GetConnectionString()); + Console.WriteLine("Connection string = " + builder.ConnectionString); + + // Keys you have provided return true. + Console.WriteLine(builder.ContainsKey("Server")); + + // Comparison is case-insensitive, and synonyms + // are automatically converted to their "well-known" + // names. + Console.WriteLine(builder.ContainsKey("Database")); + + // Keys that are valid but have not been set return true. + Console.WriteLine(builder.ContainsKey("Max Pool Size")); + + // Keys that do not exist return false. + Console.WriteLine(builder.ContainsKey("MyKey")); + + Console.WriteLine("Press Enter to continue."); + Console.ReadLine(); + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Server=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"; + } + } + + + The example displays the following output in the console window: + + + Connection string = Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True + True + True + True + False + + + is null ( in Visual Basic) + + + + Obsolete. Gets or sets a value that indicates whether a client/server or in-process connection to SQL Server should be made. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Context Connection" key within the connection string. + + + The property returns if the connection string for the is "context connection=true". + + + + + + Gets or sets the language used for database server warning or error messages.. + + + The value of the property, or string.Empty if no value has been supplied. + + + + This property corresponds to the "Current Language" and "language" keys within the connection string. + + + The language name can be 128 characters or fewer. + + + + To set the value to null, use . + + + + + Gets or sets the name or network address of the instance of SQL Server to connect to. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Data Source", "server", "address", "addr", and "network address" keys within the connection string. Regardless of which of these values has been supplied within the supplied connection string, the connection string created by the SqlConnectionStringBuilder will use the well-known "Data Source" key. The port number can be specified after the server name: server=tcp:servername,portnumber . + + + When specifying a local instance, always use (local). To force a protocol, add one of the following prefixes: np:(local), tcp:(local), lpc:(local) . + + + You can also connect to a LocalDB database as follows: server=(localdb)\\myInstance . For more information about LocalDB, see SqlClient Support for LocalDB . Data Source must use the TCP format or the Named Pipes format. TCP format is as follows: + + + tcp:\<host name>\\<instance name> + tcp:\<host name>,\<TCP/IP port number> + + + The TCP format must start with the prefix "tcp:" and is followed by the database instance, as specified by a host name and an instance name. This format is not applicable when connecting to Azure SQL Database. TCP is automatically selected for connections to Azure SQL Database when no protocol is specified. + + + The host name MUST be specified in one of the following ways: + + + NetBIOSName + IPv4Address + IPv6Address + + + The instance name is used to resolve to a particular TCP/IP port number on which a database instance is hosted. Alternatively, specifying a TCP/IP port number directly is also allowed. If both instance name and port number are not present, the default database instance is used. + + + The Named Pipes format is as follows: - + + + np:\\\\<host name>\pipe\\<pipe name> + + + The Named Pipes format MUST start with the prefix "np:" and is followed by a named pipe name. + + + The host name MUST be specified in one of the following ways: + + + NetBIOSName + IPv4Address + IPv6Address + + + The pipe name is used to identify the database instance to which the .NET application will connect. + + + If the value of the Network key is specified, the prefixes "tcp:" and "np:" should not be specified. Note: You can force the use of TCP instead of shared memory, either by prefixing tcp: to the server name in the connection string, or by using localhost. + + + + + The following example demonstrates that the class converts synonyms for the "Data Source" connection string key into the well-known key: + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder( + "Network Address=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"); + + // Display the connection string, which should now + // contain the "Data Source" key, as opposed to the + // supplied "Network Address". + Console.WriteLine(builder.ConnectionString); + + // Retrieve the DataSource property. + Console.WriteLine("DataSource = " + builder.DataSource); + + Console.WriteLine("Press any key to continue."); + Console.ReadLine(); + } + } + + + + To set the value to null, use . + + + + + Gets or sets the enclave attestation URL to be used with enclave based Always Encrypted. + + + The enclave attestation URL. + + + + + Gets or sets a value since version 5.0 or a value for the earlier versions that indicates whether TLS encryption is required for all data sent between the client and server. + + + The value of the property. + + + + This property corresponds to the "Encrypt" key within the connection string. + + + When is and Encrypt is , or , the server name (or IP address) in a server's TLS certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. For information about support for certificates whose subject starts with a wildcard character (*), see Enable encrypted connections to the Database Engine . + + + Starting from version 4.0, the default value of the property Encrypt is set to while it is for earlier versions. + + + Starting from version 5.0, the data type is updated to , and the default value of the Encrypt property is set to . + + + + Working with Connection Strings + + + Overview of the SqlClient driver + + + + + Gets or sets a Boolean value that indicates whether the SQL Server connection pooler automatically enlists the connection in the creation thread's current transaction context. + + + The value of the property, or if none has been supplied. + + + This property corresponds to the "Enlist" key within the connection string. + + + + + Gets or sets the name or address of the partner server to connect to if the primary server is down. + + + The value of the property, or if none has been supplied. + + + To set the value to null, use . + + + + If the value of this key is "", then Initial Catalog must be present, and its value must not be "". + + + The server name can be 128 characters or fewer. + + + If you specify a failover partner but the failover partner server is not configured for database mirroring and the primary server (specified with the Server keyword) is not available, then the connection will fail. + + + If you specify a failover partner and the primary server is not configured for database mirroring, the connection to the primary server (specified with the Server keyword) will succeed if the primary server is available. + + + + + + Gets or sets the service principal name (SPN) of the failover partner for the connection. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "FailoverPartnerSPN" and "Failover Partner SPN" keys within the connection string. + + + This property only applies when using Integrated Security mode, otherwise it is ignored. + + + + + + Gets or sets the host name to use when validating the server certificate for the connection. When not specified, the server name from the Data Source is used for certificate validation. (Only available in v5.0+) + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "HostNameInCertificate" and "Host Name in Certificate" keys within the connection string. + + + This property only applies when using in or mode, otherwise it is ignored. + + + + + + Gets or sets the name of the database associated with the connection. + + + The value of the property, or string.Empty if none has been supplied. + + + + This property corresponds to the "Initial Catalog" and "database" keys within the connection string. + + + The database name can be 128 characters or fewer. + + + + + The following example creates a simple connection string and then uses the class to add the name of the database to the connection string. The code displays the contents of the property, just to verify that the class was able to convert from the synonym ("Database") to the appropriate property value. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = "Data Source=(local);" + + "Integrated Security=true"; + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + + // Normally, you could simply set the InitialCatalog + // property of the SqlConnectionStringBuilder object. This + // example uses the default Item property (the C# indexer) + // and the "Database" string, simply to demonstrate that + // setting the value in this way results in the same + // connection string: + builder["Database"] = "AdventureWorks"; + Console.WriteLine("builder.InitialCatalog = " + builder.InitialCatalog); + Console.WriteLine("Modified: " + builder.ConnectionString); + + using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) + { + connection.Open(); + // Now use the open connection. + Console.WriteLine("Database = " + connection.Database); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + } + + + + To set the value to null, use . + + + + + Gets or sets a Boolean value that indicates whether User ID and Password are specified in the connection (when ) or whether the current Windows account credentials are used for authentication (when ). + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Integrated Security" and "trusted_connection" keys within the connection string. + + + If User ID and Password are specified and Integrated Security is set to true, the User ID and Password will be ignored and Integrated Security will be used. is a more secure way to specify credentials for a connection that uses SQL Server Authentication ( Integrated Security=false ). + + + + + The following example converts an existing connection string from using SQL Server Authentication to using integrated security. The example does its work by removing the username and password from the connection string and then setting the property of the object. + + + This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = + "Data Source=(local);User ID=ab;Password=MyPassword;" + + "Initial Catalog=AdventureWorks"; + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + + // Use the Remove method + // in order to reset the user ID and password back to their + // default (empty string) values. Simply setting the + // associated property values to an empty string won't + // remove them from the connection string; you must + // call the Remove method. + builder.Remove("User ID"); + builder.Remove("Password"); + + // Turn on integrated security: + builder.IntegratedSecurity = true; + + Console.WriteLine("Modified: " + builder.ConnectionString); + + using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) + { + connection.Open(); + // Now use the open connection. + Console.WriteLine("Database = " + connection.Database); + } + + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + } + + + + + + Gets or sets the IP address family preference when establishing TCP connections. + + + Returns the IP address preference. + + + If Transparent Network IP Resolution (in .NET Framework) or Multi Subnet Failover is set to true, this setting has no effect. + + + + + Gets a value that indicates whether the has a fixed size. + + + in every case, because the supplies a fixed-size collection of key/value pairs. + + + Working with Connection Strings + + + Overview of the SqlClient driver + + + + + The key of the item to get or set. + + + Gets or sets the value associated with the specified key. In C#, this property is the indexer. + + + The value associated with the specified key. + + + Because the contains a fixed-size dictionary, trying to add a key that does not exist within the dictionary throws a . + + + + The following code, in a console application, creates a new and adds key/value pairs to its connection string, using the property. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder["Data Source"] = "(local)"; + builder["Integrated Security"] = true; + builder["Initial Catalog"] = "AdventureWorks"; + + // Overwrite the existing value for the Data Source value. + builder["Data Source"] = "."; + + Console.WriteLine(builder.ConnectionString); + Console.WriteLine(); + Console.WriteLine("Press Enter to continue."); + Console.ReadLine(); + } + } + + + + is a null reference ( in Visual Basic). + + + Tried to add a key that does not exist within the available keys. + + + Invalid value within the connection string (specifically, a Boolean or numeric value was expected but not supplied). + + + + + Gets an that contains the keys in the . + + + An that contains the keys in the . + + + The order of the values in the is unspecified, but it is the same order as the associated values in the returned by the property. + + + + The following console application example creates a new . The code loops through the returned by the property displaying the key/value pairs. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder.DataSource = "(local)"; + builder.IntegratedSecurity = true; + builder.InitialCatalog = "AdventureWorks"; + + // Loop through the collection of keys, displaying + // the key and value for each item: + foreach (string key in builder.Keys) + { + Console.WriteLine("{0}={1}", key, builder[key]); + } + + Console.WriteLine(); + Console.WriteLine("Press Enter to continue."); + Console.ReadLine(); + } + } + + + + + + + + Gets or sets the minimum time, in seconds, for the connection to live in the connection pool before being destroyed. + + + The value of the property, or 0 if none has been supplied. + + + + This property corresponds to the "Load Balance Timeout" and "connection lifetime" keys within the connection string. + + + When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by Connection Lifetime. This is useful in clustered configurations to force load balancing between a running server and a server just brought online. + + + A value of zero (0) causes pooled connections to have the maximum connection timeout. + + + + + + Gets or sets the maximum number of connections allowed in the connection pool for this specific connection string. + + + The value of the property, or 100 if none has been supplied. + + + This property corresponds to the "Max Pool Size" key within the connection string. + + + + + Gets or sets the minimum number of connections allowed in the connection pool for this specific connection string. + + + The value of the property, or 0 if none has been supplied. + + + This property corresponds to the "Min Pool Size" key within the connection string. + + + + + When true, an application can maintain multiple active result sets (MARS). When false, an application must process or cancel all result sets from one batch before it can execute any other batch on that connection. For more information, see Multiple Active Result Sets (MARS). + + + The value of the property, or if none has been supplied. + + + This property corresponds to the "Multiple Active Result Sets" key within the connection string. + + + + The following example explicitly enables the Multiple Active Result Sets feature. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder.DataSource = "(local)"; + builder.IntegratedSecurity = true; + builder.InitialCatalog = "AdventureWorks"; + + // The connection does not allow multiple active result sets + // by default, so this line of code explicitly + // enables this feature. Note that this feature is + // only available when programming against SQL Server 2005 + // or later. + builder.MultipleActiveResultSets = true; + + Console.WriteLine(builder.ConnectionString); + Console.WriteLine(); + + Console.WriteLine("Press Enter to continue."); + Console.ReadLine(); + } + } + + + + + + If your application is connecting to an AlwaysOn availability group (AG) on different subnets, setting MultiSubnetFailover=true provides faster detection of and connection to the (currently) active server. For more information about SqlClient support for Always On Availability Groups, see SqlClient Support for High Availability, Disaster Recovery. + + + Returns indicating the current value of the property. + + + Always specify multiSubnetFailover=True when connecting to the availability group listener of a SQL Server 2012 (or later) availability group or a SQL Server 2012 (or later) Failover Cluster Instance. + + + + + Gets or sets a string that contains the name of the network library used to establish a connection to the SQL Server. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Network Library", "network", and "net" keys within the connection string. Supported values for this property include: + + + dbnmpntw (Named Pipes) + dbmsrpcn (Multiprotocol) + dbmsadsn (AppleTalk) + dbmsgnet (VIA) + dbmslpcn (Shared Memory) + dbmsspxn (IPX/SPX) + dbmssocn (TCP/IP) + + + The corresponding network DLL must be installed on the system to which you connect. If you do not specify a network and you use a local server (for example, "." or "(local)"), Shared Memory is used. + + + + To set the value to null, use . + + + + + Gets or sets the size in bytes of the network packets used to communicate with an instance of SQL Server. + + + The value of the property, or 8000 if none has been supplied. + + + + This property corresponds to the "Packet Size" key within the connection string. + + + The packet size can be greater than or equal to 512 and less than or equal to 32768. + + + + + + Gets or sets the password for the SQL Server account. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Password" and "pwd" keys within the connection string. + + + Setting this property is not recommended. To maintain a high level of security, we strongly recommend that you use the Integrated Security or Trusted_Connection keyword instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication. + + + If has not been set, and you retrieve the value, the return value is . To reset the password for the connection string, pass null to the Item property. + + + The password must be 128 characters or fewer. + + + + + The following example shows how to set . + + + + using System; + using Microsoft.Data.SqlClient; + + class Program + { + public static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + + builder["Password"] = null; + string aa = builder.Password; + Console.WriteLine(aa.Length); + + builder["Password"] = "??????"; + aa = builder.Password; + Console.WriteLine(aa.Length); + + try + { + builder.Password = null; + } + catch (ArgumentNullException e) + { + Console.WriteLine("{0}", e); + } + } + } + + + + The password was incorrectly set to null. + + + + + Gets or sets a Boolean value indicating if security-sensitive information, such as the password or access token, should be returned as part of the connection string on a connection created with this after that connection has ever been in an open state. This property should only be set to if your application has a specific need to read the password out of an already-opened database connection. The default value of is the more secure setting; using for this property opens your application to security risks such as accidentally logging or tracing the database password. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Persist Security Info" and "persistsecurityinfo" keys within the connection string. + + + Resetting the connection string resets all connection string values including the password. + + + + + + The blocking period behavior for a connection pool. + + + The available blocking period settings. + + + + This property corresponds to the "Pool Blocking Period" key within the connection string. + + + When connection pooling is enabled and a timeout error or other login error occurs, an exception will be thrown and subsequent connection attempts will fail for the next five seconds, the "blocking period". If the application attempts to connect within the blocking period, the first exception will be thrown again. Subsequent failures after a blocking period ends will result in a new blocking period that is twice as long as the previous blocking period, up to a maximum of one minute. + + + Attempting to connect to Azure SQL databases can fail with transient errors which are typically recovered within a few seconds. However, with the connection pool blocking period behavior, you may not be able to reach your database for extensive periods even though the database is available. This is especially problematic for apps that need to render fast. The PoolBlockingPeriod enables you to select the blocking period best suited for your app. See the enumeration for available settings. + + + + + + Gets or sets a Boolean value that indicates whether the connection will be pooled or explicitly opened every time that the connection is requested. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "Pooling" key within the connection string. + + + Connections are considered the same if they have the same connection string. Different connections have different connection strings. + + + + + + The key of the key/value pair to be removed from the connection string in this . + + + Removes the entry with the specified key from the instance. + + + if the key existed within the connection string and was removed; if the key did not exist. + + + + Because the Remove method returns a value that indicates its success, it is not required to look for a key before trying to remove the key/value pair from the instance. Because the maintains a fixed-size collection of key/value pairs, calling the Remove method simply resets the value of the key/value pair back to its default value. + + + Because the collection of keys supported by the is fixed, every item within the collection has a known default value. The following table lists the keys, and the value for each when the is first initialized, or after the Remove method has been called. + + + + Key + Default value + + + Application Name + + "Framework Microsoft SqlClient Data Provider" when running on .NET Framework. "Core Microsoft SqlClient Data Provider" otherwise. + + + + AttachDBFilename + Empty string + + + Connection Timeout + 15 + + + Context Connection(Obsolete) + False + + + Current Language + Empty string + + + Data Source + Empty string + + + Encrypt + False in versions prior to 4.0, True in versions 4.0 and up + + + Enlist + True + + + Failover Partner + Empty string + + + Initial Catalog + Empty string + + + Integrated Security + False + + + Load Balance Timeout + 0 + + + Max Pool Size + 100 + + + Min Pool Size + 0 + + + MultipleActiveResultSets + False + + + Network Library + Empty string + + + Packet Size + 8000 + + + Password + Empty string + + + Persist Security Info + False + + + Pooling + True + + + Replication + False + + + Transaction Binding + Implicit Unbind + + + User ID + Empty string + + + User Instance + False + + + Workstation ID + Empty string + + + + + + The following example converts an existing connection string from using Windows Authentication to using integrated security. The example works by removing the username and password from the connection string, and then setting the property of the object. + + + This example includes a password to demonstrate how works with connection strings. In your applications, we recommend that you use Windows Authentication. If you must use a password, do not include a hard-coded password in your application. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + try + { + string connectString = + "Data Source=(local);User ID=ab;Password= a1Pass@@11;" + + "Initial Catalog=AdventureWorks"; + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); + Console.WriteLine("Original: " + builder.ConnectionString); + + // Use the Remove method + // in order to reset the user ID and password back to their + // default (empty string) values. + builder.Remove("User ID"); + builder.Remove("Password"); + + // Turn on integrated security: + builder.IntegratedSecurity = true; + + Console.WriteLine("Modified: " + builder.ConnectionString); + + using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) + { + connection.Open(); + // Now use the open connection. + Console.WriteLine("Database = " + connection.Database); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + Console.WriteLine("Press any key to finish."); + Console.ReadLine(); + } + } + + + The example displays the following text in the console window: + + + Original: Data Source=(local);Initial Catalog=AdventureWorks;User ID=ab;Password= a1Pass@@11 + Modified: Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True Database=AdventureWorks + + + + is null ( in Visual Basic) + + + + + Gets or sets a Boolean value that indicates whether replication is supported using the connection. + + + The value of the property, or false if none has been supplied. + + + This property corresponds to the "Replication" key within the connection string. + + + + + Gets or sets the path to a certificate file to match against the SQL Server TLS/SSL certificate for the connection. The accepted certificate formats are PEM, DER, and CER. If specified, the SQL Server certificate is checked by verifying if the `ServerCertificate` provided is an exact match. (Only available in v5.1+) + + + The value of the property, or string.Empty if none has been supplied. + + + + This property corresponds to the "ServerCertificate" and "Server Certificate" keys within the connection string. + + + This property only applies when using Encrypt in or mode, otherwise it is ignored. + + + + + + Gets or sets the service principal name (SPN) of the data source. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "ServerSPN" and "Server SPN" keys within the connection string. + + + This property only applies when using Integrated Security mode, otherwise it is ignored. + + + + + + The key to locate in the . + + + Indicates whether the specified key exists in this instance. + + if the contains an entry with the specified key; otherwise, . + + This method behaves identically to the method. + + + + + Gets or sets a string value that indicates how the connection maintains its association with an enlisted transaction. + + + The value of the property, or Implicit Unbind if none has been supplied. + + + + The Transaction Binding keywords in a control how a binds to an enlisted . + + + The following table shows the possible values for the property: + + + + Value + Description + + + Implicit Unbind + + The default. Causes the connection to detach from the transaction when it ends. After detaching, additional requests on the connection are performed in autocommit mode. The property is not checked when executing requests while the transaction is active. After the transaction has ended, additional requests are performed in autocommit mode. + + + + Explicit Unbind + + Causes the connection to remain attached to the transaction until the connection is closed or until is called with a (Nothing in Visual Basic) value. An is thrown if is not the enlisted transaction or if the enlisted transaction is not active. This behavior enforces the strict scoping rules required for support. + + + + + + + + When the value of this key is set to , the application is required to retrieve all IP addresses for a particular DNS entry and attempt to connect with the first one in the list. If the connection is not established within 0.5 seconds, the application will try to connect to all others in parallel. When the first answers, the application will establish the connection with the respondent IP address. + + + A boolean value. + + + + If the Multi Subnet Failover key is set to true, Transparent Network IP Resolution is ignored. + + + If the Failover Partner key is set, Transparent Network IP Resolution is ignored. + + + The value of this key must be true, false, yes, or no. + + + A value of yes is treated the same as a value of true. A value of no is treated the same as a value of false. + + + This key defaults to false when: + + + + Connecting to Azure SQL Database where the data source ends with: + + .database.chinacloudapi.cn + .database.usgovcloudapi.net + .database.cloudapi.de + .database.windows.net + + + + Authentication is 'Active Directory Password' or 'Active Directory Integrated' + + Otherwise it defaults to true. + + + + + + Gets or sets a value that indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust. + + + A boolean. The default is . + + + + This property corresponds to the "Trust Server Certificate" and "TrustServerCertificate" keys within the connection string. + + + When Trust Server Certificate is set to , the transport layer will use TLS to encrypt the channel and bypass walking the certificate chain to validate trust. If Trust Server Certificate is set to and encryption is enforced by target server, the encryption level specified on the server will be used even if Encrypt is set to . The connection will fail otherwise. + + + For more information, see Encryption Hierarchy and Using Encryption Without Validation. + + + + + + The key of the item to retrieve. + + + The value corresponding to . + + + Retrieves a value corresponding to the supplied key from this . + + + if was found within the connection string; otherwise, . + + + + The method lets developers safely retrieve a value from a without needing to verify that the supplied key name is a valid key name. Because TryGetValue does not raise an exception when you call it, passing in a nonexistent key, you do not have to look for a key before retrieving its value. Calling TryGetValue with a nonexistent key will place the value null (Nothing in Visual Basic) in the parameter. + + + + + The following example demonstrates the behavior of the TryGetValue method. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder.ConnectionString = GetConnectionString(); + + // Call TryGetValue method for multiple + // key names. Note that these keys are converted + // to well-known synonynms for data retrieval. + DisplayValue(builder, "Data Source"); + DisplayValue(builder, "Trusted_Connection"); + DisplayValue(builder, "InvalidKey"); + DisplayValue(builder, null); + + Console.WriteLine("Press any key to continue."); + Console.ReadLine(); + } + + private static void DisplayValue(SqlConnectionStringBuilder builder, string key) + { + object value = null; + + // Although TryGetValue handles missing keys, + // it doesn't handle passing in a null + // key. This example traps for that particular error, but + // passes any other unknown exceptions back out to the + // caller. + try + { + if (builder.TryGetValue(key, out value)) + { + Console.WriteLine("{0}='{1}'", key, value); + } + else + { + Console.WriteLine("Unable to retrieve value for '{0}'", key); + } + } + catch (ArgumentNullException) + { + Console.WriteLine("Unable to retrieve value for null key."); + } + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Server=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"; + } + } + + + The sample displays the following results: + + + Data Source=(local) + Trusted_Connection=True + Unable to retrieve value for 'InvalidKey' + Unable to retrieve value for null key. + + + + contains a null value ( in Visual Basic). + + + + + Gets or sets a string value that indicates the type system the application expects. + + + The following table shows the possible values for the property: + + + Value + Description + + + SQL Server 2005 + Uses the SQL Server 2005 type system. No conversions are made for the current version of ADO.NET. + + + SQL Server 2008 + Uses the SQL Server 2008 type system. + + + Latest + + Use the latest version than this client-server pair can handle. This will automatically move forward as the client and server components are upgraded. + + + + + + The TypeSystemVersion property can be used to specify a down-level version of SQL Server for applications written against that version. This avoids possible problems with incompatible types in a newer version of SQL Server that may cause the application to break. + + + + + Gets or sets the user ID to be used when connecting to SQL Server. + + + The value of the property, or string.Empty if none has been supplied. + + + + This property corresponds to the "User ID", "user", and "uid" keys within the connection string. + + + Setting this property is not recommended. To maintain a high level of security, we strongly recommend that you use the Integrated Security or Trusted_Connection keywords instead. is a more secure way to specify credentials for a connection that uses SQL Server Authentication. + + + The user ID must be 128 characters or fewer. + + + + To set the value to null, use . + + + + + Gets or sets a value that indicates whether to redirect the connection from the default SQL Server Express instance to a runtime-initiated instance running under the account of the caller. + + + The value of the property, or if none has been supplied. + + + + This property corresponds to the "User Instance" key within the connection string. + + + This feature is available only with the SQL Server Express Edition. For more information on user instances, see SQL Server Express User Instances. + + + + To set the value to null, use . + + + + + Gets an that contains the values in the . + + + An that contains the values in the . + + + The order of the values in the is unspecified, but it is the same order as the associated keys in the returned by the property. Because each instance of the always contains the same fixed set of keys, the property always returns the values corresponding to the fixed set of keys, in the same order as the keys. + + + + The following example first creates a new , and then iterates through all the values within the object. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(GetConnectionString()); + + // Loop through each of the values, displaying the contents. + foreach (object value in builder.Values) + { + Console.WriteLine(value); + } + + Console.WriteLine("Press any key to continue."); + Console.ReadLine(); + } + + private static string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Integrated Security=SSPI;" + + "Initial Catalog=AdventureWorks"; + } + } + + + + + + + Gets or sets the name of the workstation connecting to SQL Server. + + + The value of the property, or string.Empty if none has been supplied. + + + + This property corresponds to the "Workstation ID" and "wsid" keys within the connection string. + + + The ID must be 128 characters or fewer. + + + + To set the value to null, use . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCredential.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCredential.xml index 41caafa87f..c7a630eb1f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCredential.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCredential.xml @@ -1,86 +1,92 @@ - - - - - - provides a more secure way to specify the password for a login attempt using SQL Server Authentication. - - is comprised of a user id and a password that will be used for SQL Server Authentication. The password in a object is of type . - - cannot be inherited. - - Windows Authentication () remains the most secure way to log in to a SQL Server database. - - to get or set a connection's object. Use to change the password for a object. For information on how a object affects connection pool behavior, see [SQL Server Connection Pooling (ADO.NET)](/sql/connect/ado-net/sql-server-connection-pooling). - - An exception will be raised if a non-null object is used in a connection with any of the following connection string keywords: - -- `Integrated Security = true` - -- `Password` - -- `User ID` - - The following sample connects to a SQL Server database using : - -``` -// change connection string in the APP.CONFIG file - - - - -// then use the following snippet: -using System.Configuration; - -System.Windows.Controls.TextBox txtUserId = new System.Windows.Controls.TextBox(); -System.Windows.Controls.PasswordBox txtPwd = new System.Windows.Controls.PasswordBox(); - -Configuration config = Configuration.WebConfigurationManager.OpenWebConfiguration(Null); -ConnectionStringSettings connString = config.ConnectionStrings.ConnectionString["MyConnString"]; - -using (SqlConnection conn = new SqlConnection(connString.ConnectionString)) -{ - SecureString pwd = txtPwd.SecurePassword; - pwd.MakeReadOnly(); - SqlCredential cred = new SqlCredential(txtUserId.Text, pwd); - conn.Credential = cred; - conn.Open(); -} -``` - - ]]> - - - - The user id. - The password; a value marked as read-only. Passing a read/write parameter will raise an . - Creates an object of type . - - value is allowed. An attempt to pass a null parameter in the constructor will raise an exception. - - ]]> - - Overview of the SqlClient driver - - - Gets the password component of the object. - The password component of the object. - To be added. - Overview of the SqlClient driver - - - Gets the user ID component of the object. - The user ID component of the object. - To be added. - Overview of the SqlClient driver - - + + + + + provides a more secure way to specify the password for a login attempt using SQL Server Authentication. is comprised of a user id and a password that will be used for SQL Server Authentication. The password in a object is of type . cannot be inherited. Windows Authentication (Integrated Security = true) remains the most secure way to log in to a SQL Server database. + + + + Use to get or set a connection's object. Use to change the password for a object. For information on how a object affects connection pool behavior, see SQL Server Connection Pooling (ADO.NET). + + + An exception will be raised if a non-null object is used in a connection with any of the following connection string keywords: + + + Integrated Security = true + Password + User ID + + + + + The following sample connects to a SQL Server database using : + + change connection string in the APP.CONFIG file + + <connectionStrings> + <add name="MyConnString" connectionString="Initial Catalog=myDB;Server=myServer" providerName="Microsoft.Data.SqlClient" /> + </connectionStrings> + + Then use the following snippet: + + using System.Configuration; + + System.Windows.Controls.TextBox txtUserId = new System.Windows.Controls.TextBox(); + System.Windows.Controls.PasswordBox txtPwd = new System.Windows.Controls.PasswordBox(); + Configuration config = Configuration.WebConfigurationManager.OpenWebConfiguration(null); + ConnectionStringSettings connString = config.ConnectionStrings.ConnectionString["MyConnString"]; + + using (SqlConnection conn = new SqlConnection(connString.ConnectionString)) + { + SecureString pwd = txtPwd.SecurePassword; + pwd.MakeReadOnly(); + + SqlCredential cred = new SqlCredential(txtUserId.Text, pwd); + conn.Credential = cred; + + conn.Open(); + } + + + + + + The user id. + + + The password; a value marked as read-only. Passing a read/write parameter will raise an . + + + Creates an object of type . + + + The constructor does not accept null parameters. An string.Empty value is allowed. An attempt to pass a null parameter in the constructor will raise an exception. + + + Overview of the SqlClient driver + + + + + Gets the password component of the object. + + + The password component of the object. + + + Overview of the SqlClient driver + + + + + Gets the user ID component of the object. + + + The user ID component of the object. + + + Overview of the SqlClient driver + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlDataAdapter.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlDataAdapter.xml index 6fb16341ef..6921841825 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlDataAdapter.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlDataAdapter.xml @@ -1,501 +1,1374 @@ - - - - - Represents a set of data commands and a database connection that are used to fill the and update a SQL Server database. This class cannot be inherited. - - , serves as a bridge between a and SQL Server for retrieving and saving data. The provides this bridge by mapping , which changes the data in the to match the data in the data source, and , which changes the data in the data source to match the data in the , using the appropriate Transact-SQL statements against the data source. The update is performed on a by-row basis. For every inserted, modified, and deleted row, the method determines the type of change that has been performed on it (`Insert`, `Update`, or `Delete`). Depending on the type of change, the `Insert`, `Update`, or `Delete` command template executes to propagate the modified row to the data source. When the fills a , it creates the necessary tables and columns for the returned data if they do not already exist. However, primary key information is not included in the implicitly created schema unless the property is set to . You may also have the create the schema of the , including primary key information, before filling it with data using `FillSchema`. For more information, see [Adding Existing Constraints to a DataSet](/sql/connect/ado-net/add-existing-constraints-to-dataset). - - is used in conjunction with and to increase performance when connecting to a SQL Server database. - -> [!NOTE] -> If you are using SQL Server stored procedures to edit or delete data using a `DataAdapter`, make sure that you do not use SET NOCOUNT ON in the stored procedure definition. This causes the rows affected count returned to be zero, which the `DataAdapter` interprets as a concurrency conflict. In this event, a will be thrown. - - The also includes the , , , , and properties to facilitate the loading and updating of data. - - When an instance of is created, the read/write properties are set to initial values. For a list of these values, see the constructor. - - The , , and are generic templates that are automatically filled with individual values from every modified row through the parameters mechanism. - - For every column that you propagate to the data source on , a parameter should be added to the `InsertCommand`, `UpdateCommand`, or `DeleteCommand`. The property of the object should be set to the name of the column. This setting indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. - -> [!NOTE] -> An will occur if the method is called and the table contains a user-defined type that is not available on the client computer. For more information, see [CLR User-Defined Types](/sql/relational-databases/clr-integration-database-objects-user-defined-types/clr-user-defined-types). - - - -## Examples - The following example uses the , , and to select records from a database and populate a with the selected rows. The filled is then returned. To accomplish this, the method is passed an initialized , a connection string, and a query string that is a Transact-SQL SELECT statement. - - [!code-csharp[SqlDataAdapter_SelectCommand Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_SelectCommand.cs#1)] - - ]]> - - - - Initializes a new instance of the class. - - - Initializes a new instance of the class. - - is created, the following read/write properties are set to the following initial values. - -|Properties|Initial value| -|----------------|-------------------| -||`MissingMappingAction.Passthrough`| -||`MissingSchemaAction.Add`| - - You can change the value of any of these properties through a separate call to the property. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlDataAdapter.SqlDataAdapter Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_SqlDataAdapter.cs#1)] - - ]]> - - - - A that is a Transact-SQL SELECT statement or stored procedure and is set as the property of the . - Initializes a new instance of the class with the specified as the property. - - constructor sets the property to the value specified in the `selectCommand` parameter. - - When an instance of is created, the following read/write properties are set to the following initial values. - -|Properties|Initial value| -|----------------|-------------------| -||`MissingMappingAction.Passthrough`| -||`MissingSchemaAction.Add`| - - You can change the value of any of these properties through a separate call to the property. - - When (or any of the other command properties) is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlDataAdapter_SqlDataAdapter1 Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_SqlDataAdapter1.cs#1)] - - ]]> - - - - A that is a Transact-SQL SELECT statement or stored procedure to be used by the property of the . - A that represents the connection. If your connection string does not use , you can use to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - Initializes a new instance of the class with a and a object. - - opens and closes a if it is not already open. This can be useful in an application that must call the method for two or more objects. If the is already open, you must explicitly call **Close** or **Dispose** to close it. - - When an instance of is created, the following read/write properties are set to the following initial values. - -|Properties|Initial value| -|----------------|-------------------| -||`MissingMappingAction.Passthrough`| -||`MissingSchemaAction.Add`| - - You can change the value of either of these properties through a separate call to the property. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlDataAdapter_SqlDataAdapter3 Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_SqlDataAdapter3.cs#1)] - - ]]> - - - - A that is a Transact-SQL SELECT statement or stored procedure to be used by the property of the . - The connection string. If your connection string does not use , you can use and to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. - Initializes a new instance of the class with a and a connection string. - - constructor uses the `selectCommandText` parameter to set the property. The will create and maintain the connection created with the `selectConnectionString` parameter. - - When an instance of is created, the following read/write properties are set to the following initial values. - -|Properties|Initial value| -|----------------|-------------------| -||`MissingMappingAction.Passthrough`| -||`MissingSchemaAction.Add`| - - You can change the value of any of these properties through a separate call to the property. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlDataAdapter_SqlDataAdapter2 Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_SqlDataAdapter2.cs#1)] - - ]]> - - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - To be added. - To be added. - To be added. - - - Gets or sets a Transact-SQL statement or stored procedure to delete records from the data set. - A used during to delete records in the database that correspond to deleted rows in the . - - , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - - When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. - - For every column that you propagate to the data source on , a parameter should be added to the `InsertCommand`, `UpdateCommand`, or `DeleteCommand`. The `SourceColumn` property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. - - - -## Examples - The following example creates a and sets the , , , and properties. It assumes you have already created a object. - - [!code-csharp[SqlDataAdapter#1](~/../sqlclient/doc/samples/SqlDataAdapter.cs#1)] - - ]]> - - - - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - - - Gets or sets a Transact-SQL statement or stored procedure to insert new records into the data source. - A used during to insert records into the database that correspond to new rows in the . - - , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - - When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. - - If execution of this command returns rows, these rows can be added to the depending on how you set the **UpdatedRowSource** property of the object. - - For every column that you propagate to the data source on , a parameter should be added to `InsertCommand`, `UpdateCommand`, or `DeleteCommand`. The `SourceColumn` property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. - - - -## Examples - The following example creates a and sets the , , , and properties. It assumes you have already created a object. - - [!code-csharp[SqlDataAdapter#1](~/../sqlclient/doc/samples/SqlDataAdapter.cs#1)] - - ]]> - - - - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - - - Occurs during after a command is executed against the data source. The attempt to update is made, so the event fires. - - , there are two events that occur per data row updated. The order of execution is as follows: - -1. The values in the are moved to the parameter values. - -2. The event is raised. - -3. The command executes. - -4. If the command is set to `FirstReturnedRecord`, the first returned result is placed in the . - -5. If there are output parameters, they are placed in the . - -6. The event is raised. - -7. is called. - - - -## Examples - The following example shows how to use both the and events. - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) - - [!code-csharp[SqlDataAdapter_RowUpdated Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_RowUpdated.cs#1)] - - ]]> - - - - Occurs during before a command is executed against the data source. The attempt to update is made, so the event fires. - - , there are two events that occur per data row updated. The order of execution is as follows: - -1. The values in the are moved to the parameter values. - -2. The event is raised. - -3. The command executes. - -4. If the command is set to `FirstReturnedRecord`, the first returned result is placed in the . - -5. If there are output parameters, they are placed in the . - -6. The event is raised. - -7. is called. - - - -## Examples - The following example shows how to use both the and events. - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) - - [!code-csharp[SqlDataAdapter_RowUpdated Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_RowUpdated.cs#1)] - - ]]> - - - - Gets or sets a Transact-SQL statement or stored procedure used to select records in the data source. - A used during to select records from the database for placement in the . - - is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. - - If the does not return any rows, no tables are added to the , and no exception is raised. - - - -## Examples - The following example creates a and sets the , , , and properties. It assumes you have already created a object. - - [!code-csharp[SqlDataAdapter#1](~/../sqlclient/doc/samples/SqlDataAdapter.cs#1)] - - ]]> - - - - For a description of this member, see . - An that is used during to delete records in the data source for deleted rows in the data set. - - instance is cast to an interface. - - ]]> - - - - For a description of this member, see . - An that is used during to insert records in the data source for new rows in the data set. - - instance is cast to an interface. - - ]]> - - - - For a description of this member, see . - An that is used during to select records from data source for placement in the data set. - - instance is cast to an interface. - - ]]> - - - - For a description of this member, see . - An that is used during to update records in the data source for modified rows in the data set. - - instance is cast to an interface. - - ]]> - - - - For a description of this member, see . - A new object that is a copy of the current instance. - - instance is cast to an interface. - - ]]> - - - - To be added. - To be added. - - - Gets or sets the number of rows that are processed in each round-trip to the server. - The number of rows to process per-batch. - - Value is - - Effect - - 0 - - There is no limit on the batch size. - - 1 - - Disables batch updating. - - >1 - - Changes are sent using batches of operations at a time. - - + + + + + Represents a set of data commands and a database connection that are used to fill the and update a SQL Server database. This class cannot be inherited. + + + + The , serves as a bridge between a and SQL Server for retrieving and saving data. The provides this bridge by mapping , which changes the data in the to match the data in the data source, and , which changes the data in the data source to match the data in the , using the appropriate Transact-SQL statements against the data source. The update is performed on a by-row basis. For every inserted, modified, and deleted row, the method determines the type of change that has been performed on it (Insert, Update, or Delete). Depending on the type of change, the Insert, Update, or Delete command template executes to propagate the modified row to the data source. When the fills a , it creates the necessary tables and columns for the returned data if they do not already exist. However, primary key information is not included in the implicitly created schema unless the property is set to . You may also have the create the schema of the , including primary key information, before filling it with data using FillSchema. For more information, see Adding Existing Constraints to a DataSet. is used in conjunction with and to increase performance when connecting to a SQL Server database. + + + If you are using SQL Server stored procedures to edit or delete data using a DataAdapter, make sure that you do not use SET NOCOUNT ON in the stored procedure definition. This causes the rows affected count returned to be zero, which the DataAdapter interprets as a concurrency conflict. In this event, a will be thrown. + + + The also includes the , , , , and properties to facilitate the loading and updating of data. + + + When an instance of is created, the read/write properties are set to initial values. For a list of these values, see the constructor. + + + The , , and are generic templates that are automatically filled with individual values from every modified row through the parameters mechanism. + + + For every column that you propagate to the data source on , a parameter should be added to the InsertCommand, UpdateCommand, or DeleteCommand. The property of the object should be set to the name of the column. This setting indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. + + + An will occur if the method is called and the table contains a user-defined type that is not available on the client computer. For more information, see CLR User-Defined Types. + + + + + The following example uses the , , and to select records from a database and populate a with the selected rows. The filled is then returned. To accomplish this, the method is passed an initialized , a connection string, and a query string that is a Transact-SQL SELECT statement. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + + private static DataSet SelectRows(DataSet dataset, + string connectionString, string queryString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + adapter.SelectCommand = new SqlCommand( + queryString, connection); + adapter.Fill(dataset); + return dataset; + } + } + } + + + + + + Initializes a new instance of the class. + + + + When an instance of is created, the following read/write properties are set to the following initial values. + + + + + Properties + + + Initial value + + + + + + + + + + + + + You can change the value of these properties through a separate call to the property. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } - When setting this to a value other than 1, all the commands associated with the have to have their **UpdatedRowSource** property set to or . An exception is thrown otherwise. - - property to update a data source with changes from a . This can increase application performance by reducing the number of round-trips to the server. - - Executing an extremely large batch could decrease performance. Therefore, you should test for the optimum batch size setting before implementing your application. - - An is thrown if the value is set to a number less than zero. - - ]]> - - - - Gets or sets a Transact-SQL statement or stored procedure used to update records in the data source. - A used during to update records in the database that correspond to modified rows in the . - - , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see [Generating Commands with CommandBuilders](/sql/connect/ado-net/generate-commands-with-commandbuilders). - - When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. - -> [!NOTE] -> If execution of this command returns rows, the updated rows may be merged with the depending on how you set the **UpdatedRowSource** property of the object. - - For every column that you propagate to the data source on , a parameter should be added to `InsertCommand`, `UpdateCommand`, or `DeleteCommand`. - - The `SourceColumn` property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but taken from the particular column in the currently processed row. - - - -## Examples - The following example creates a and sets the , , and properties. It assumes you have already created a object. - - [!code-csharp[SqlDataAdapter#1](~/../sqlclient/doc/samples/SqlDataAdapter.cs#1)] - - ]]> - - - + public static SqlDataAdapter CreateSqlDataAdapter(SqlConnection connection) + { + // Assumes that connection is a valid SqlConnection object + SqlDataAdapter adapter = new SqlDataAdapter(); + adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + // Create the commands. + adapter.SelectCommand = new SqlCommand( + "SELECT CustomerID, CompanyName FROM CUSTOMERS", connection); + adapter.InsertCommand = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + adapter.UpdateCommand = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + adapter.DeleteCommand = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Create the parameters. + adapter.InsertCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.InsertCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + + adapter.UpdateCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.UpdateCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + adapter.UpdateCommand.Parameters.Add( + "@oldCustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + return adapter; + } + + public static SqlDataAdapter CustomerUpdateCommand(SqlDataAdapter adapter) + { + // Assumes that connection is a valid SqlAdapter object + adapter.UpdateCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 15, + "CompanyName"); + SqlParameter parameter = adapter.UpdateCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + return adapter; + } + } + + + + + + A that is a Transact-SQL SELECT statement or stored procedure and is set as the property of the . + + + Initializes a new instance of the class with the specified as the property. + + + + This implementation of the constructor sets the property to the value specified in the parameter. When an instance of is created, the following read/write properties are set to the following initial values. + + + + Properties + Initial value + + + + + + + + + + + + You can change the value of these properties through a separate call to the property. + + + When (or any of the other command properties) is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateSqlDataAdapter(SqlCommand selectCommand, SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(selectCommand); + adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + // Create the other commands. + adapter.InsertCommand = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + adapter.UpdateCommand = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + adapter.DeleteCommand = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Create the parameters. + adapter.InsertCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.InsertCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + + adapter.UpdateCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.UpdateCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + adapter.UpdateCommand.Parameters.Add( + "@oldCustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + return adapter; + } + } + + + + + + A that is a Transact-SQL SELECT statement or stored procedure to be used by the property of the . + + + A that represents the connection. If your connection string does not use , you can use to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + Initializes a new instance of the class with a and a object. + + + + This implementation of the opens and closes a if it is not already open. This can be useful in an application that must call the method for two or more objects. If the is already open, you must explicitly call or to close it. + + + When an instance of is created, the following read/write properties are set to the following initial values. + + + + + Properties + + + Initial value + + + + + + + + + + + + + You can change the value of either of these properties through a separate call to the property. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateSqlDataAdapter(string commandText, SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(commandText, connection); + + adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + // Create the other commands. + adapter.InsertCommand = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)"); + + adapter.UpdateCommand = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID"); + + adapter.DeleteCommand = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID"); + + // Create the parameters. + adapter.InsertCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.InsertCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + + adapter.UpdateCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.UpdateCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + adapter.UpdateCommand.Parameters.Add( + "@oldCustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + return adapter; + } + } + + + + + + A that is a Transact-SQL SELECT statement or stored procedure to be used by the property of the . + + + The connection string. If your connection string does not use , you can use and to pass the user ID and password more securely than by specifying the user ID and password as text in the connection string. + + + Initializes a new instance of the class with a and a connection string. + + + + This overload of the constructor uses the parameter to set the property. The will create and maintain the connection created with the parameter. + + + When an instance of is created, the following read/write properties are set to the following initial values. + + + + + Properties + + + Initial value + + + + + + + + + + + + + You can change the value of these properties through a separate call to the property. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateSqlDataAdapter(string commandText, string connectionString) + { + SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString); + SqlConnection connection = adapter.SelectCommand.Connection; + + adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + // Create the commands. + adapter.InsertCommand = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + adapter.UpdateCommand = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + adapter.DeleteCommand = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Create the parameters. + adapter.InsertCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.InsertCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + + adapter.UpdateCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID"); + adapter.UpdateCommand.Parameters.Add( + "@CompanyName", + SqlDbType.VarChar, + 40, + "CompanyName"); + adapter.UpdateCommand.Parameters.Add( + "@oldCustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand.Parameters.Add( + "@CustomerID", + SqlDbType.Char, + 5, + "CustomerID" + ).SourceVersion = DataRowVersion.Original; + + return adapter; + } + } + + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Gets or sets a Transact-SQL statement or stored procedure to delete records from the data set. + + + A used during to delete records in the database that correspond to deleted rows in the . + + + + During , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see Generating Commands with CommandBuilders. + + + When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. + + + For every column that you propagate to the data source on , a parameter should be added to the , , or DeleteCommand. The SourceColumn property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. + + + + + The following example creates a and sets the , , , and properties. It assumes you have already created a object. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateCustomerAdapter(SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + + // Create the SelectCommand. + SqlCommand command = new SqlCommand("SELECT * FROM Customers " + + "WHERE Country = @Country AND City = @City", connection); + + // Add the parameters for the SelectCommand. + command.Parameters.Add("@Country", SqlDbType.NVarChar, 15); + command.Parameters.Add("@City", SqlDbType.NVarChar, 15); + + adapter.SelectCommand = command; + + // Create the InsertCommand. + command = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + // Add the parameters for the InsertCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + + adapter.InsertCommand = command; + + // Create the UpdateCommand. + command = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + // Add the parameters for the UpdateCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + SqlParameter parameter = command.Parameters.Add( + "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.UpdateCommand = command; + + // Create the DeleteCommand. + command = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Add the parameters for the DeleteCommand. + parameter = command.Parameters.Add( + "@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand = command; + + return adapter; + } + } + + + + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + + + Gets or sets a Transact-SQL statement or stored procedure to insert new records into the data source. + + + A used during to insert records into the database that correspond to new rows in the . + + + + During , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see Generating Commands with CommandBuilders. + + + When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. + + + If execution of this command returns rows, these rows can be added to the depending on how you set the UpdatedRowSource property of the object. + + + For every column that you propagate to the data source on , a parameter should be added to InsertCommand, , or . The SourceColumn property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but is taken from the particular column in the currently processed row. + + + + + The following example creates a and sets the , , , and properties. It assumes you have already created a object. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateCustomerAdapter(SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + + // Create the SelectCommand. + SqlCommand command = new SqlCommand("SELECT * FROM Customers " + + "WHERE Country = @Country AND City = @City", connection); + + // Add the parameters for the SelectCommand. + command.Parameters.Add("@Country", SqlDbType.NVarChar, 15); + command.Parameters.Add("@City", SqlDbType.NVarChar, 15); + + adapter.SelectCommand = command; + + // Create the InsertCommand. + command = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + // Add the parameters for the InsertCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + + adapter.InsertCommand = command; + + // Create the UpdateCommand. + command = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + // Add the parameters for the UpdateCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + SqlParameter parameter = command.Parameters.Add( + "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.UpdateCommand = command; + + // Create the DeleteCommand. + command = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Add the parameters for the DeleteCommand. + parameter = command.Parameters.Add( + "@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand = command; + + return adapter; + } + } + + + + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Occurs during after a command is executed against the data source. The attempt to update is made, so the event fires. + + + + When using , there are two events that occur per data row updated. The order of execution is as follows: + + + The values in the are moved to the parameter values. + The event is raised. + The command executes. + If the command is set to FirstReturnedRecord, the first returned result is placed in the . + If there are output parameters, they are placed in the . + The event is raised. + is called. + + + + + The following example shows how to use both the and events. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + private DataSet DataSet1; + private DataGrid dataGrid1; + + // handler for RowUpdating event + private static void OnRowUpdating(object sender, SqlRowUpdatingEventArgs e) + { + PrintEventArgs(e); + } + + // handler for RowUpdated event + private static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) + { + PrintEventArgs(e); + } + + public static int Main() + { + const string connectionString = "Integrated Security=SSPI;database=Northwind;server=MSSQL1"; + const string queryString = "SELECT * FROMProducts"; + + // create DataAdapter + SqlDataAdapter adapter = new SqlDataAdapter(queryString, connectionString); + SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + + // Create and fill DataSet (select only first 5 rows) + DataSet dataSet = new DataSet(); + adapter.Fill(dataSet, 0, 5, "Table"); + + // Modify DataSet + DataTable table = dataSet.Tables["Table"]; + table.Rows[0][1] = "new product"; + + // add handlers + adapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); + + // update, this operation fires two events + // (RowUpdating/RowUpdated) per changed row + adapter.Update(dataSet, "Table"); + + // remove handlers + adapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated); + return 0; + } + + private static void PrintEventArgs(SqlRowUpdatingEventArgs args) + { + Console.WriteLine("OnRowUpdating"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " status=" + args.Status + ")"); + } + + private static void PrintEventArgs(SqlRowUpdatedEventArgs args) + { + Console.WriteLine("OnRowUpdated"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " recordsAffected=" + args.RecordsAffected + + " status=" + args.Status + ")"); + } + } + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) + + + + + + Occurs during before a command is executed against the data source. The attempt to update is made, so the event fires. + + + + When using , there are two events that occur per data row updated. The order of execution is as follows: + + + The values in the are moved to the parameter values. + The event is raised. + The command executes. + If the command is set to FirstReturnedRecord, the first returned result is placed in the . + If there are output parameters, they are placed in the . + The event is raised. + is called. + + + + + The following example shows how to use both the and events. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + private DataSet DataSet1; + private DataGrid dataGrid1; + + // handler for RowUpdating event + private static void OnRowUpdating(object sender, SqlRowUpdatingEventArgs e) + { + PrintEventArgs(e); + } + + // handler for RowUpdated event + private static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) + { + PrintEventArgs(e); + } + + public static int Main() + { + const string connectionString = "Integrated Security=SSPI;database=Northwind;server=MSSQL1"; + const string queryString = "SELECT * FROMProducts"; + + // create DataAdapter + SqlDataAdapter adapter = new SqlDataAdapter(queryString, connectionString); + SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + + // Create and fill DataSet (select only first 5 rows) + DataSet dataSet = new DataSet(); + adapter.Fill(dataSet, 0, 5, "Table"); + + // Modify DataSet + DataTable table = dataSet.Tables["Table"]; + table.Rows[0][1] = "new product"; + + // add handlers + adapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); + + // update, this operation fires two events + // (RowUpdating/RowUpdated) per changed row + adapter.Update(dataSet, "Table"); + + // remove handlers + adapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated); + return 0; + } + + private static void PrintEventArgs(SqlRowUpdatingEventArgs args) + { + Console.WriteLine("OnRowUpdating"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " status=" + args.Status + ")"); + } + + private static void PrintEventArgs(SqlRowUpdatedEventArgs args) + { + Console.WriteLine("OnRowUpdated"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " recordsAffected=" + args.RecordsAffected + + " status=" + args.Status + ")"); + } + } + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) + + + + + + Gets or sets a Transact-SQL statement or stored procedure used to select records in the data source. + + + A used during to select records from the database for placement in the . + + + + When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. + + + If the does not return any rows, no tables are added to the , and no exception is raised. + + + + + The following example creates a and sets the , , , and properties. It assumes you have already created a object. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateCustomerAdapter(SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + + // Create the SelectCommand. + SqlCommand command = new SqlCommand("SELECT * FROM Customers " + + "WHERE Country = @Country AND City = @City", connection); + + // Add the parameters for the SelectCommand. + command.Parameters.Add("@Country", SqlDbType.NVarChar, 15); + command.Parameters.Add("@City", SqlDbType.NVarChar, 15); + + adapter.SelectCommand = command; + + // Create the InsertCommand. + command = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + // Add the parameters for the InsertCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + + adapter.InsertCommand = command; + + // Create the UpdateCommand. + command = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + // Add the parameters for the UpdateCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + SqlParameter parameter = command.Parameters.Add( + "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.UpdateCommand = command; + + // Create the DeleteCommand. + command = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Add the parameters for the DeleteCommand. + parameter = command.Parameters.Add( + "@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand = command; + + return adapter; + } + } + + + + + + For a description of this member, see . + + + An that is used during to delete records in the data source for deleted rows in the data set. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + For a description of this member, see . + + + An that is used during to insert records in the data source for new rows in the data set. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + For a description of this member, see . + + + An that is used during to select records from data source for placement in the data set. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + For a description of this member, see . + + + An that is used during to update records in the data source for modified rows in the data set. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + For a description of this member, see . + + + A new object that is a copy of the current instance. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + To be added. + + + To be added. + + + + + Gets or sets the number of rows that are processed in each round-trip to the server. + + + + The number of rows to process per-batch. + + + + When value is + Effect + + + 0 + There is no limit on the batch size. + + + 1 + Disables batch updating. + + + >1 + + Changes are sent using batches of operations at a time. + + + + + When setting this to a value other than 1, all the commands associated with the have to have their property set to or . An exception is thrown otherwise. + + + + + Gets or sets a value that enables or disables batch processing support, and specifies the number of commands that can be executed in a batch. + + + Use the property to update a data source with changes from a . This can increase application performance by reducing the number of round-trips to the server. + + + Executing an extremely large batch could decrease performance. Therefore, you should test for the optimum batch size setting before implementing your application. + + + An is thrown if the value is set to a number less than zero. + + + + + + Gets or sets a Transact-SQL statement or stored procedure used to update records in the data source. + + + A used during to update records in the database that correspond to modified rows in the . + + + + During , if this property is not set and primary key information is present in the , the can be generated automatically if you set the property and use the . Then, any additional commands that you do not set are generated by the . This generation logic requires key column information to be present in the . For more information, see Generating Commands with CommandBuilders. + + + When is assigned to a previously created , the is not cloned. The maintains a reference to the previously created object. + + + If execution of this command returns rows, the updated rows may be merged with the depending on how you set the property of the object. + + + For every column that you propagate to the data source on , a parameter should be added to , UpdateCommand, or . + + + The SourceColumn property of the parameter should be set to the name of the column. This indicates that the value of the parameter is not set manually, but taken from the particular column in the currently processed row. + + + + + The following example creates a and sets the , , and properties. It assumes you have already created a object. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + } + + public static SqlDataAdapter CreateCustomerAdapter(SqlConnection connection) + { + SqlDataAdapter adapter = new SqlDataAdapter(); + + // Create the SelectCommand. + SqlCommand command = new SqlCommand("SELECT * FROM Customers " + + "WHERE Country = @Country AND City = @City", connection); + + // Add the parameters for the SelectCommand. + command.Parameters.Add("@Country", SqlDbType.NVarChar, 15); + command.Parameters.Add("@City", SqlDbType.NVarChar, 15); + + adapter.SelectCommand = command; + + // Create the InsertCommand. + command = new SqlCommand( + "INSERT INTO Customers (CustomerID, CompanyName) " + + "VALUES (@CustomerID, @CompanyName)", connection); + + // Add the parameters for the InsertCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + + adapter.InsertCommand = command; + + // Create the UpdateCommand. + command = new SqlCommand( + "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " + + "WHERE CustomerID = @oldCustomerID", connection); + + // Add the parameters for the UpdateCommand. + command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName"); + SqlParameter parameter = command.Parameters.Add( + "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.UpdateCommand = command; + + // Create the DeleteCommand. + command = new SqlCommand( + "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection); + + // Add the parameters for the DeleteCommand. + parameter = command.Parameters.Add( + "@CustomerID", SqlDbType.NChar, 5, "CustomerID"); + parameter.SourceVersion = DataRowVersion.Original; + + adapter.DeleteCommand = command; + + return adapter; + } + } + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml index 89aa86664e..7e64c9180c 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml @@ -1,1235 +1,1936 @@ - - - - - Provides a way of reading a forward-only stream of rows from a SQL Server database. This class cannot be inherited. - - , you must call the method of the object, instead of directly using a constructor. - - While the is being used, the associated is busy serving the , and no other operations can be performed on the other than closing it. This is the case until the method of the is called. For example, you cannot retrieve output parameters until after you call . - - Changes made to a result set by another process or thread while data is being read may be visible to the user of the `SqlDataReader`. However, the precise behavior is timing dependent. - - and are the only properties that you can call after the is closed. Although the property may be accessed while the exists, always call before returning the value of to guarantee an accurate return value. - - When using sequential access (), an will be raised if the position is advanced and another read operation is attempted on the previous column. - -> [!NOTE] -> For optimal performance, avoids creating unnecessary objects or making unnecessary copies of data. Therefore, multiple calls to methods such as return a reference to the same object. Use caution if you are modifying the underlying value of the objects returned by methods such as . - - - -## Examples - The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the `using` code block. - - [!code-csharp[SqlDataReader_Read Example#1](~/../sqlclient/doc/samples/SqlDataReader_Read.cs#1)] - - ]]> - - - - Closes the object. - - method is called when you are through using the before using the associated for any other purpose. The `Close` method may either be called directly or through the `Dispose` method, disposing directly or in the context of [the using statement](/dotnet/csharp/language-reference/language-specification/statements#the-using-statement) block. - - The `Close` method populates the values for output parameters, return values and `RecordsAffected` on the by consuming any pending results. This may be a long operation depending on the amount of data to be consumed. If output values, return values, and `RecordsAffected` are not important to your application, the time to close may be shortened by calling the method of the associated object before the `Close` method is called. - -> [!CAUTION] -> Do not call `Close` or `Dispose` on a Connection, a DataReader, or any other managed object in the `Finalize` method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a `Finalize` method in your class definition. For more information, see [Garbage Collection](/dotnet/standard/garbage-collection/). - - - -## Examples - The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the `using` code block. - - [!code-csharp[SqlDataReader_Close Example#1](~/../sqlclient/doc/samples/SqlDataReader_Close.cs#1)] - - ]]> - - - - Gets the associated with the . - The associated with the . - To be added. - - - Gets the information with the . - The associated with the . - To be added. - - - Gets a value that indicates the depth of nesting for the current row. - The depth of nesting for the current row. - - - - - - To be added. - To be added. - To be added. - - - to release managed and unmanaged resources; to release only unmanaged resources. - Releases the unmanaged resources used by the and optionally releases the managed resources. - - . - - ]]> - - - - Gets the number of columns in the current row. - When not positioned in a valid recordset, 0; otherwise the number of columns in the current row. The default is -1. - - to 0. However. this should not be confused with a query that returns 0 rows (such as SELECT * FROM *table* WHERE 1 = 2) in which case returns the number of columns in the table, including hidden fields. Use to exclude hidden fields. - - ]]> - - There is no current connection to an instance of SQL Server. - - - The zero-based column ordinal. - Gets the value of the specified column as a Boolean. - The value of the column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a byte. - The value of the specified column as a byte. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - The index within the field from which to begin the read operation. - The buffer into which to read the stream of bytes. - The index within the where the write operation is to start. - The maximum length to copy into the buffer. - Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset. - The actual number of bytes read. - - returns the number of available bytes in the field. Most of the time this is the exact length of the field. However, the number returned may be less than the true length of the field if `GetBytes` has already been used to obtain bytes from the field. This may be the case, for example, if the is reading a large data structure into a buffer. For more information, see the `SequentialAccess` setting for . - - If you pass a buffer that is `null`, returns the length of the entire field in bytes, not the remaining size based on the buffer offset parameter. - - No conversions are performed; therefore, the data retrieved must already be a byte array. - - ]]> - - - - The zero-based column ordinal. - Gets the value of the specified column as a single character. - The value of the specified column. - - . - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - The index within the field from which to begin the read operation. - The buffer into which to read the stream of bytes. - The index within the where the write operation is to start. - The maximum length to copy into the buffer. - Reads a stream of characters from the specified column offset into the buffer as an array starting at the given buffer offset. - The actual number of characters read. - - returns the number of available characters in the field. Frequently this is the exact length of the field. However, the number returned may be less than the true length of the field if `GetChars` has already been used to obtain characters from the field. This may be the case, for example, if the is reading a large data structure into a buffer. For more information, see the `SequentialAccess` setting for . - - The actual number of characters read can be less than the requested length, if the end of the field is reached. If you pass a buffer that is `null`, returns the length of the entire field in characters, not the remaining size based on the buffer offset parameter. - - No conversions are performed; therefore. the data retrieved must already be a character array. - -> [!NOTE] -> The method returns 0 when `dataIndex` is negative. - - ]]> - - - - Gets the read-only column schema collection. - The read-only column schema collection). - - method, which enables the use of the interface to populate the schema metadata without using a . - - ]]> - - - - - A column ordinal. - Returns an for the specified column ordinal. - The instance for the specified column ordinal. - To be added. - - - The zero-based ordinal position of the column to find. - Gets a string representing the data type of the specified column. - The string representing the data type of the specified column. - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a object. - The value of the specified column. - - object. - - Call to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Retrieves the value of the specified column as a object. - The value of the specified column. - - object. - - Call to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a object. - The value of the specified column. - - object. - - Call to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a double-precision floating point number. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - Returns an that iterates through the . - An for the . - - - - - - The zero-based column ordinal. - Gets the that is the data type of the object. - The that is the data type of the object. If the type does not exist on the client, in the case of a User-Defined Type (UDT) returned from the database, **GetFieldType** returns null. - To be added. - - - The type of the value to be returned. - The column to be retrieved. - Synchronously gets the value of the specified column as a type. is the asynchronous version of this method. - The returned type object. - - - .| - - For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Tried to read a previously-read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. - Trying to read a column that does not exist. - The value of the column was null ( == ), retrieving a non-SQL type. - - doesn't match the type returned by SQL Server or cannot be cast. - - - The type of the value to be returned. - The column to be retrieved. - The cancellation instruction, which propagates a notification that operations should be canceled. This does not guarantee the cancellation. A setting of makes this method equivalent to . The returned task must be marked as cancelled. - Asynchronously gets the value of the specified column as a type. is the synchronous version of this method. - The returned type object. - - - .| - - For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Tried to read a previously-read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. - Trying to read a column that does not exist. - The value of the column was null ( == ), retrieving a non-SQL type. - - doesn't match the type returned by SQL Server or cannot be cast. - - - The zero-based column ordinal. - Gets the value of the specified column as a single-precision floating point number. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a globally unique identifier (GUID). - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a 16-bit signed integer. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a 32-bit signed integer. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column as a 64-bit signed integer. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the name of the specified column. - The name of the specified column. - To be added. - - - The name of the column. - Gets the column ordinal, given the name of the column. - The zero-based column ordinal. - - method. - - [!code-csharp[SqlDataReader_GetOrdinal#1](~/../sqlclient/doc/samples/SqlDataReader_GetOrdinal.cs#1)] - - ]]> - - The name specified is not a valid column name. - - - An representing the column ordinal. - Gets an that is a representation of the underlying provider-specific field type. - Gets an that is a representation of the underlying provider-specific field type. - To be added. - - - An representing the column ordinal. - Gets an that is a representation of the underlying provider specific value. - An that is a representation of the underlying provider specific value. - To be added. - - - An array of into which to copy the column values. - Gets an array of objects that are a representation of the underlying provider specific values. - The array of objects that are a representation of the underlying provider specific values. - To be added. - - - Returns a that describes the column metadata of the . - A that describes the column metadata. - - method returns the following metadata about each column: - -|DataReader column|Description| -|-----------------------|-----------------| -|AllowDBNull|Set if the consumer can set the column to a null value or if the provider cannot determine whether the consumer can set the column to a null value. Otherwise, not set. A column may contain null values, even if it cannot be set to a null value.| -|BaseCatalogName|The name of the catalog in the data store that contains the column. NULL if the base catalog name cannot be determined. The default of this column is a null value.| -|BaseColumnName|The name of the column in the data store. This might be different than the column name returned in the ColumnName column if an alias was used. A null value if the base column name cannot be determined or if the rowset column is derived, but not identical to, a column in the data store. The default of this column is a null value.| -|BaseSchemaName|The name of the schema in the data store that contains the column. A null value if the base schema name cannot be determined. The default of this column is a null value.| -|BaseServerName|The name of the instance of Microsoft SQL Server used by the .| -|BaseTableName|The name of the table or view in the data store that contains the column. A null value if the base table name cannot be determined. The default of this column is a null value.| -|ColumnName|The name of the column; this might not be unique. If this cannot be determined, a null value is returned. This name always reflects the most recent renaming of the column in the current view or command text.| -|ColumnOrdinal|The zero-based ordinal of the column. This column cannot contain a null value.| -|ColumnSize|The maximum possible length of a value in the column. For columns that use a fixed-length data type, this is the size of the data type. For `nvarchar(MAX)`, `varchar(MAX)`, and `varbinary(MAX)` columns stored in a SQL Server database, the maximum size is 2GB. If these columns are stored and accessed as files, the limit on maximum size is imposed by the file system. This value changes when using the `Type System Version` keyword in the connection string. For new types they are represented as downlevel types. The MAX data types return the normal 4k for `nvarchar` and 8000 for `varchar`. For more information, see the [Transact-SQL reference](/sql/t-sql/language-reference).| -|DataTypeName|Returns a string representing the data type of the specified column.| -|IsAliased|`true`: The column name is an alias.

`false`: The column name is not an alias.| -|IsAutoIncrement|`true`: The column assigns values to new rows in fixed increments.

`false`: The column does not assign values to new rows in fixed increments. The default of this column is `false`.| -|IsColumnSet|`true`: The column is a sparse column that is a member of a column set.| -|IsExpression|`true`: The column is an expression.

`false`: The column is not an expression.| -|IsHidden|`true`: The column is hidden.

`false`: The column is not hidden.| -|IsIdentity|`true`: The column is an identity column.

`false`: The column is not an identity column.| -|IsKey|`true`: The column is one of a set of columns in the rowset that, taken together, uniquely identify the row. The set of columns with `IsKey` set to `true` must uniquely identify a row in the rowset. There is no requirement that this set of columns is a minimal set of columns. This set of columns may be generated from a base table primary key, a unique constraint or a unique index.

`false`: The column is not required to uniquely identify the row.| -|IsLong|`true`: The column contains a Binary Long Object (BLOB) that contains very long data. The definition of very long data is provider-specific.

`false`: The column does not contain a Binary Long Object (BLOB) that contains very long data.| -|IsReadOnly|`true`: The column cannot be modified.

`false`: The column can be modified.| -|IsRowVersion|`true`: The column contains a persistent row identifier that cannot be written to, and has no meaningful value except to identity the row.

`false`: The column does not contain a persistent row identifier that cannot be written to, and has no meaningful value except to identity the row.| -|IsUnique|`true`: Column is of type `timestamp`.

`false`: Column is not of type `timestamp`.| -|NonVersionedProviderType|The type of the column irrespective of the current `Type System Version` specified in the connection string. The returned value is from the enumeration.| -|NumericPrecision|If `ProviderType` is a numeric data type, this is the maximum precision of the column. The precision depends on the definition of the column. If `ProviderType` is not a numeric data type, this is 255.| -|NumericScale|If `ProviderType` is DBTYPE_DECIMAL or DBTYPE_NUMERIC, the number of digits to the right of the decimal point. Otherwise, this is 255.| -|ProviderSpecificDataType|Returns the provider-specific data type of the column based on the `Type System Version` keyword in the connection string.| -|ProviderType|The indicator of the column's data type. If the data type of the column varies from row to row, this must be Object. This column cannot contain a null value.| -|UdtAssemblyQualifiedName|If the column is a user-defined type (UDT), this is the qualified name of the UDT's assembly as per . If the column is not a UDT, this is null.| -|XmlSchemaCollectionDatabase|The name of the database where the schema collection for this XML instance is located, if the row contains information about an XML column. This value is `null` (`Nothing` in Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case the `XmlSchemaCollectionName` and `XmlSchemaCollectionOwningSchema` columns are also null.| -|XmlSchemaCollectionName|The name of the schema collection for this XML instance, if the row contains information about an XML column. This value is `null` (`Nothing` in Visual Basic) if there is no associated schema collection. If the value is null, the `XmlSchemaCollectionDatabase` and `XmlSchemaCollectionOwningSchema` columns are also null.| -|XmlSchemaCollectionOwningSchema|The owning relational schema where the schema collection for this XML instance is located, if the row contains information about an XML column. This value is `null` (`Nothing` in Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case the `XmlSchemaCollectionDatabase` and `XmlSchemaCollectionName` columns are also null.| - -> [!NOTE] -> To make sure that metadata columns return the correct information, you must call with the `behavior` parameter set to `KeyInfo`. Otherwise, some of the columns in the schema table may return default, null, or incorrect data. - - ]]>
-
- The is closed. -
- - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column. - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as . - The value of the column expressed as a . - To be added. - - - The zero-based column ordinal. - Gets the value of the specified column as . - The value of the column expressed as a . - To be added. - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Gets the value of the specified column as a . - The value of the column expressed as a . - - - - - - The zero-based column ordinal. - Returns the data value in the specified column as a SQL Server type. - The value of the column expressed as a . - - returns data using the native SQL Server types. To retrieve data using the .NET Framework types, see . - - ]]> - - - - An array of into which to copy the values. The column values are expressed as SQL Server types. - Fills an array of that contains the values for all the columns in the record, expressed as SQL Server types. - An integer indicating the number of columns copied. - - array does not need to match the number of columns in the record. You can pass an array that contains fewer than the number of columns contained in the record. Only the amount of data the array holds is copied to the array, starting at the column with ordinal 0. You can also pass an array whose length is more than the number of columns contained in the resulting row. Any remaining columns are untouched. - - ]]> - - - is null. - - - The zero-based column ordinal. - Gets the value of the specified column as an XML value. - A value that contains the XML stored within the corresponding field. - - to check for null values before calling this method. - - ]]> - - The index passed was outside the range of 0 to - 1 - An attempt was made to read or access columns in a closed . - The retrieved data is not compatible with the type. - - - The zero-based column ordinal. - Retrieves binary, image, varbinary, UDT, and variant data types as a . - A stream object. - - defaults to the value of ; but you can modify via . - - Null values will be returned as an empty (zero bytes) . - - will raise an exception when used on an object returned by when is in effect. - - exceptions raised from are thrown as exceptions; check the inner exception for the . - - The following members are not available for objects returned by : - -- BeginWrite - -- EndWrite - -- Length - -- Position - -- Seek - -- SetLength - -- Write - -- WriteByte - -- WriteTimeout - - For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Tried to read a previously-read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. - Trying to read a column that does not exist. - The returned type was not one of the types below: - -- binary - -- image - -- varbinary - -- udt - - - The zero-based column ordinal. - Gets the value of the specified column as a string. - The value of the specified column. - - to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The column to be retrieved. - Retrieves Char, NChar, NText, NVarChar, text, varChar, and Variant data types as a . - The returned object. - - exceptions raised from are thrown as exceptions; check the inner exception for the . - - Null values will be returned as an empty (zero bytes) . - - will raise an exception when used on an object returned by when is in effect. - - For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Tried to read a previously-read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. - Trying to read a column that does not exist. - The returned type was not one of the types below: - -- char - -- nchar - -- ntext - -- nvarchar - -- text - -- varchar - - - The zero-based column ordinal. - Retrieves the value of the specified column as a object. - The value of the specified column. - - object. - - Call to check for null values before calling this method. - - ]]> - - The specified cast is not valid. - - - The zero-based column ordinal. - Gets the value of the specified column in its native format. - This method returns for null database columns. - - returns data using the .NET Framework types. - - ]]> - - - - An array of into which to copy the attribute columns. - Populates an array of objects with the column values of the current row. - The number of instances of in the array. - - array that contains fewer than the number of columns contained in the resulting row. Only the amount of data the array holds is copied to the array. You can also pass an array whose length is more than the number of columns contained in the resulting row. - - This method returns for null database columns. - - - -## Examples - The following example demonstrates using a correctly sized array to read all values from the current row in the supplied . In addition, the sample demonstrates using a fixed-sized array that could be either smaller or larger than the number of available columns. - - [!code-csharp[DataTableReader_GetValues#2](~/../sqlclient/doc/samples/DataTableReader_GetValues.cs#2)] - - ]]> - - - - The value of the specified column. - Retrieves data of type XML as an . - The returned object. - - object returned by does not support asynchronous operations. If you require asynchronous operations on an , cast the XML column to an NVARCHAR(MAX) on the server and use with . - - exceptions raised from are thrown as exceptions; check the inner exception for the . - - will raise an exception when used on an object returned by when is in effect. - - For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Trying to read a previously read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. - Trying to read a column that does not exist. - The returned type was not xml. - - - Gets a value that indicates whether the contains one or more rows. - - if the contains one or more rows; otherwise . - To be added. - - - Retrieves a Boolean value that indicates whether the specified instance has been closed. - - if the specified instance is closed; otherwise . - - instance that is closed. - - ]]> - - - - A enumeration. - Determines whether the specified matches that of the . - - if the specified is true, otherwise. - - - - - - The zero-based column ordinal. - Gets a value that indicates whether the column contains non-existent or missing values. - - if the specified column value is equivalent to ; otherwise . - - , , and so on) to avoid raising an error. - - [!code-csharp[SqlDataReader_IsDBNull#1](~/../sqlclient/doc/samples/SqlDataReader_IsDBNull.cs#1)] - - ]]> - - - - The zero-based column to be retrieved. - The cancellation instruction, which propagates a notification that operations should be canceled. This does not guarantee the cancellation. A setting of makes this method equivalent to . The returned task must be marked as cancelled. - An asynchronous version of , which gets a value that indicates whether the column contains non-existent or missing values. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - - if the specified column value is equivalent to otherwise . - - - - The connection drops or is closed during the data retrieval. - - The is closed during the data retrieval. - - There is no data ready to be read (for example, the first hasn't been called, or returned false). - - Trying to read a previously read column in sequential mode. - - There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + + Provides a way of reading a forward-only stream of rows from a SQL Server database. This class cannot be inherited. + + + + To create a , you must call the method of the object, instead of directly using a constructor. + + + While the is being used, the associated is busy serving the , and no other operations can be performed on the other than closing it. This is the case until the method of the is called. For example, you cannot retrieve output parameters until after you call . + + + Changes made to a result set by another process or thread while data is being read may be visible to the user of the SqlDataReader. However, the precise behavior is timing dependent. and are the only properties that you can call after the is closed. Although the property may be accessed while the exists, always call before returning the value of to guarantee an accurate return value. + + + When using sequential access (), an will be raised if the position is advanced and another read operation is attempted on the previous column. + + + For optimal performance, avoids creating unnecessary objects or making unnecessary copies of data. Therefore, multiple calls to methods such as return a reference to the same object. Use caution if you are modifying the underlying value of the objects returned by methods such as . + + + + + The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the using code block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + ReadOrderData(str); + } + + private static void ReadOrderData(string connectionString) + { + string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + + using (SqlConnection connection = + new SqlConnection(connectionString)) + { + SqlCommand command = + new SqlCommand(queryString, connection); + connection.Open(); + + SqlDataReader reader = command.ExecuteReader(); + + // Call Read before accessing data. + while (reader.Read()) + { + ReadSingleRow((IDataRecord)reader); + } + + // Call Close when done reading. + reader.Close(); + } + } + + private static void ReadSingleRow(IDataRecord record) + { + Console.WriteLine(String.Format("{0}, {1}", record[0], record[1])); + } + } + + + + + + Closes the object. + + + + You must ensure the method is called when you are through using the before using the associated for any other purpose. The Close method may either be called directly or through the method, disposing directly or in the context of + the using statement + block. + + + The Close method populates the values for output parameters, return values and on the by consuming any pending results. This may be a long operation depending on the amount of data to be consumed. If output values, return values, and are not important to your application, the time to close may be shortened by calling the method of the associated object before the Close method is called. + + + Do not call Close or on a Connection, a DataReader, or any other managed object in the finalizer method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a finalizer method in your class definition. For more information, see Garbage Collection. + + + + + The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the using code block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + ReadOrderData(str); + } + + private static void ReadOrderData(string connectionString) + { + string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + using (SqlCommand command = new SqlCommand(queryString, connection)) + { + using (SqlDataReader reader = command.ExecuteReader()) + { + // Call Read before accessing data. + while (reader.Read()) + { + Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1])); + } + + // Call Close when done reading. + reader.Close(); + } + } + } + } + } + + + + + + Gets the associated with the . + + + The associated with the . + + + + + Gets a value that indicates the depth of nesting for the current row. + + + The depth of nesting for the current row. + + + The outermost table has a depth of zero. The .NET Framework Data Provider for SQL Server does not support nesting and always returns zero. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets the number of columns in the current row. + + + When not positioned in a valid recordset, 0; otherwise the number of columns in the current row. The default is -1. + + + Executing a query that, by its nature, does not return rows (such as a DELETE query), sets to 0. However. this should not be confused with a query that returns 0 rows (such as SELECT * FROM <table> WHERE 1 = 2) in which case returns the number of columns in the table, including hidden fields. Use to exclude hidden fields. + + + There is no current connection to an instance of SQL Server. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a Boolean. + + + The value of the column. + + + + No conversions are performed; therefore, the data retrieved must already be a Boolean, or an exception is generated. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a byte. + + + The value of the specified column as a byte. + + + + No conversions are performed; therefore, the data retrieved must already be a byte. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + The index within the field from which to begin the read operation. + + + The buffer into which to read the stream of bytes. + + + The index within the where the write operation is to start. + + + The maximum length to copy into the buffer. + + + Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset. + + + The actual number of bytes read. + + + + GetBytes returns the number of available bytes in the field. Most of the time this is the exact length of the field. However, the number returned may be less than the true length of the field if GetBytes has already been used to obtain bytes from the field. This may be the case, for example, if the is reading a large data structure into a buffer. For more information, see the setting for . + + + If you pass a buffer that is , GetBytes returns the length of the entire field in bytes, not the remaining size based on the buffer offset parameter. + + + No conversions are performed; therefore, the data retrieved must already be a byte array. + + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a single character. + + + The value of the specified column. + + + Not supported for . + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + The index within the field from which to begin the read operation. + + + The buffer into which to read the stream of bytes. + + + The index within the where the write operation is to start. + + + The maximum length to copy into the buffer. + + + Reads a stream of characters from the specified column offset into the buffer as an array starting at the given buffer offset. + + + The actual number of characters read. + + + + GetChars returns the number of available characters in the field. Frequently this is the exact length of the field. However, the number returned may be less than the true length of the field if GetChars has already been used to obtain characters from the field. This may be the case, for example, if the is reading a large data structure into a buffer. For more information, see the setting for . + + + The actual number of characters read can be less than the requested length, if the end of the field is reached. If you pass a buffer that is , GetChars returns the length of the entire field in characters, not the remaining size based on the buffer offset parameter. + + + No conversions are performed; therefore. the data retrieved must already be a character array. + + + The GetChars method returns 0 when is negative. + + + + + + Gets the read-only column schema collection. + + + The read-only column schema collection). + + + This method is an implementation of method, which enables the use of the interface to populate the schema metadata without using a . + + + + + A column ordinal. + + + Returns an for the specified column ordinal. + + + The instance for the specified column ordinal. + + + + + The zero-based ordinal position of the column to find. + + + Gets a string representing the data type of the specified column. + + + The string representing the data type of the specified column. + + + Returns the name of the back-end data type. numeric is a synonym in SQL Server for the decimal data type. GetDataTypeName will return "decimal" for a column defined as either decimal or numeric. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a object. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a object. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Retrieves the value of the specified column as a object. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a object. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a object. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a object. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a double-precision floating point number. + + + The value of the specified column. + + + + No conversions are performed. Therefore, the data retrieved must already be a double-precision floating point number. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + Returns an that iterates through the . + + + An for the . + + + Although you can use this method to retrieve an explicit enumerator, in languages that support a foreach construct, it is simpler to use the looping construct directly in order to iterate through the rows in the data reader. + + + + + The zero-based column ordinal. + + + Gets the that is the data type of the object. + + + The that is the data type of the object. If the type does not exist on the client, in the case of a User-Defined Type (UDT) returned from the database, GetFieldType returns null. + + + + + The type of the value to be returned. + + + The column to be retrieved. + + + Synchronously gets the value of the specified column as a type. is the asynchronous version of this method. + + + The returned type object. + + + + can be one of the following types: + + + Boolean (bool) + Byte + Char + DateOnly (.NET 6 or later) + DateTime + DateTimeOffset + Decimal + Double + Single (float) + Guid + Int16 (short) + Int32 (int) + Int64 (long) + SqlBoolean + SqlByte + SqlDateTime + SqlDecimal + SqlDouble + SqlGuid + SqlInt16 + SqlInt32 + SqlInt64 + SqlMoney + SqlSingle + SqlString + Stream + String + TextReader + TimeOnly (.NET 6 or later) + XmlReader + UDT, which can be any CLR type marked with . + + + For more information, see SqlClient Streaming Support. + + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Tried to read a previously-read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + The value of the column was null ( == ), retrieving a non-SQL type. + + doesn't match the type returned by SQL Server or cannot be cast. + + + + The type of the value to be returned. + + + The column to be retrieved. + + + The cancellation instruction, which propagates a notification that operations should be canceled. This does not guarantee the cancellation. A setting of makes this method equivalent to . The returned task must be marked as cancelled. + + + Asynchronously gets the value of the specified column as a type. is the synchronous version of this method. + + + The returned type object. + + + + can be one of the following types: + + + Boolean (bool) + Byte + Char + DateOnly (.NET 6 or later) + DateTime + DateTimeOffset + Decimal + Double + Single (float) + Guid + Int16 (short) + Int32 (int) + Int64 (long) + SqlBoolean + SqlByte + SqlDateTime + SqlDecimal + SqlDouble + SqlGuid + SqlInt16 + SqlInt32 + SqlInt64 + SqlMoney + SqlSingle + SqlString + Stream + String + TextReader + TimeOnly (.NET 6 or later) + XmlReader + UDT, which can be any CLR type marked with . + + + For more information, see SqlClient Streaming Support. + + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Tried to read a previously-read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + The value of the column was null ( == ), retrieving a non-SQL type. + + doesn't match the type returned by SQL Server or cannot be cast. + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a single-precision floating point number. + + + The value of the specified column. + + + + No conversions are performed. Therefore, the data retrieved must already be a single-precision floating point number. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a globally unique identifier (GUID). + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a GUID. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a 16-bit signed integer. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a 16-bit signed integer. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a 32-bit signed integer. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a 32-bit signed integer. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a 64-bit signed integer. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a 64-bit signed integer. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the name of the specified column. + + + The name of the specified column. + + + + + The name of the column. + + + Gets the column ordinal, given the name of the column. + + + The zero-based column ordinal. + + + + GetOrdinal performs a case-sensitive lookup first. If it fails, a second, case-insensitive search occurs (a case-insensitive comparison is done using the database collation). Unexpected results can occur when comparisons are affected by culture-specific casing rules. For example, in Turkish, the following example yields the wrong results because the file system in Turkish does not use linguistic casing rules for the letter 'i' in "file". The method throws an exception if the zero-based column ordinal is not found. GetOrdinal is kana-width insensitive. + + + Because ordinal-based lookups are more efficient than named lookups, it is inefficient to call GetOrdinal within a loop. Save time by calling GetOrdinal once and assigning the results to an integer variable for use within the loop. + + + + + The following example demonstrates how to use the method. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + ReadGetOrdinal(str); + } + + private static void ReadGetOrdinal(string connectionString) + { + string queryString = "SELECT DISTINCT CustomerID FROM dbo.Orders;"; + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + connection.Open(); + + SqlDataReader reader = command.ExecuteReader(); + + // Call GetOrdinal and assign value to variable. + int customerID = reader.GetOrdinal("CustomerID"); + + // Use variable with GetString inside of loop. + while (reader.Read()) + { + Console.WriteLine("CustomerID={0}", reader.GetString(customerID)); + } + + // Call Close when done reading. + reader.Close(); + } + } + } + + + + The name specified is not a valid column name. + + + + + An representing the column ordinal. + + + Gets an that is a representation of the underlying provider-specific field type. + + + Gets an that is a representation of the underlying provider-specific field type. + + + + + An representing the column ordinal. + + + Gets an that is a representation of the underlying provider specific value. + + + An that is a representation of the underlying provider specific value. + + + + + An array of into which to copy the column values. + + + Gets an array of objects that are a representation of the underlying provider specific values. + + + The array of objects that are a representation of the underlying provider specific values. + + + + + Returns a that describes the column metadata of the . + + + A that describes the column metadata. + + + + The method returns the following metadata about each column: + + + + DataReader column + Description + + + AllowDBNull + + Set if the consumer can set the column to a null value or if the provider cannot determine whether the consumer can set the column to a null value. Otherwise, not set. A column may contain null values, even if it cannot be set to a null value. + + + + BaseCatalogName + + The name of the catalog in the data store that contains the column. NULL if the base catalog name cannot be determined. The default of this column is a null value. + + + + BaseColumnName + + The name of the column in the data store. This might be different than the column name returned in the ColumnName column if an alias was used. A null value if the base column name cannot be determined or if the rowset column is derived, but not identical to, a column in the data store. The default of this column is a null value. + + + + BaseSchemaName + + The name of the schema in the data store that contains the column. A null value if the base schema name cannot be determined. The default of this column is a null value. + + + + BaseServerName + + The name of the instance of Microsoft SQL Server used by the . + + + + BaseTableName + + The name of the table or view in the data store that contains the column. A null value if the base table name cannot be determined. The default of this column is a null value. + + + + ColumnName + + The name of the column; this might not be unique. If this cannot be determined, a null value is returned. This name always reflects the most recent renaming of the column in the current view or command text. + + + + ColumnOrdinal + + The zero-based ordinal of the column. This column cannot contain a null value. + + + + ColumnSize + + + The maximum possible length of a value in the column. For columns that use a fixed-length data type, this is the size of the data type. For nvarchar(MAX), varchar(MAX), and varbinary(MAX) columns stored in a SQL Server database, the maximum size is 2GB. If these columns are stored and accessed as files, the limit on maximum size is imposed by the file system. This value changes when using the Type System Version keyword in the connection string. + + + For new types they are represented as downlevel types. The MAX data types return the normal 4k for nvarchar and 8000 for varchar. For more information, see the Transact-SQL reference. + + + + + DataTypeName + + Returns a string representing the data type of the specified column. + + + + IsAliased + + + : The column name is an alias. + + + : The column name is not an alias. + + + + + IsAutoIncrement + + + : The column assigns values to new rows in fixed increments. + + + : The column does not assign values to new rows in fixed increments. The default of this column is + + + + + IsColumnSet + + : The column is a sparse column that is a member of a column set. + + + + IsExpression + + + : The column is an expression. + + + : The column is not an expression. + + + + + IsHidden + + + : The column is hidden. + + + : The column is not hidden. + + + + + IsIdentity + + + : The column is an identity column. + + + : The column is not an identity column. + + + + + IsKey + + + : The column is one of a set of columns in the rowset that, taken together, uniquely identify the row. The set of columns with IsKey set to must uniquely identify a row in the rowset. There is no requirement that this set of columns is a minimal set of columns. This set of columns may be generated from a base table primary key, a unique constraint or a unique index. + + + : The column is not required to uniquely identify the row. + + + + + IsLong + + + : The column contains a Binary Long Object (BLOB) that contains very long data. The definition of very long data is provider-specific. + + + : The column does not contain a Binary Long Object (BLOB) that contains very long data. + + + + + IsReadOnly + + + : The column cannot be modified. + + + : The column can be modified. + + + + + IsRowVersion + + + : The column contains a persistent row identifier that cannot be written to, and has no meaningful value except to identity the row. + + + : The column does not contain a persistent row identifier that cannot be written to, and has no meaningful value except to identity the row. + + + + + IsUnique + + + : Column is of type timestamp. + + + : Column is not of type timestamp. + + + + + NonVersionedProviderType + + The type of the column irrespective of the current Type System Version specified in the connection string. The returned value is from the enumeration. + + + + NumericPrecision + + If ProviderType is a numeric data type, this is the maximum precision of the column. The precision depends on the definition of the column. If ProviderType is not a numeric data type, this is 255. + + + + NumericScale + + If ProviderType is DBTYPE_DECIMAL or DBTYPE_NUMERIC, the number of digits to the right of the decimal point. Otherwise, this is 255. + + + + ProviderSpecificDataType + + Returns the provider-specific data type of the column based on the Type System Version keyword in the connection string. + + + + ProviderType + + The indicator of the column's data type. If the data type of the column varies from row to row, this must be Object. This column cannot contain a null value. + + + + UdtAssemblyQualifiedName + + If the column is a user-defined type (UDT), this is the qualified name of the UDT's assembly as per . If the column is not a UDT, this is null. + + + + XmlSchemaCollectionDatabase + + The name of the database where the schema collection for this XML instance is located, if the row contains information about an XML column. This value is null (Nothing in Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case the XmlSchemaCollectionName and XmlSchemaCollectionOwningSchema columns are also null. + + + + XmlSchemaCollectionName + + The name of the schema collection for this XML instance, if the row contains information about an XML column. This value is null (Nothing in Visual Basic) if there is no associated schema collection. If the value is null, the XmlSchemaCollectionDatabase and XmlSchemaCollectionOwningSchema columns are also null. + + + + XmlSchemaCollectionOwningSchema + + The owning relational schema where the schema collection for this XML instance is located, if the row contains information about an XML column. This value is null (Nothing in Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case the XmlSchemaCollectionDatabase and XmlSchemaCollectionName columns are also null. + + + + + To make sure that metadata columns return the correct information, you must call with the behavior parameter set to KeyInfo. Otherwise, some of the columns in the schema table may return default, null, or incorrect data. + + + + The is closed. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore the data retrieved must already be a binary structure or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column. + + + No conversions are performed; therefore, the data retrieved must already be a Boolean or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore the data retrieved must already be a byte, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as . + + + The value of the column expressed as a . + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as . + + + The value of the column expressed as a . + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a date/time value, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a decimal value, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a double-precision floating-point number, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a GUID, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a 16-bit signed integer, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore the data retrieved must already be a 32-bit signed integer, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a 64-bit signed integer, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a decimal value, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a single precision floating point number, or an exception is generated. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a . + + + The value of the column expressed as a . + + + No conversions are performed; therefore, the data retrieved must already be a string, or an exception is generated. + + + + + The zero-based column ordinal. + + + Returns the data value in the specified column as a SQL Server type. + + + The value of the column expressed as a . + + + returns data using the native SQL Server types. To retrieve data using the .NET Framework types, see . + + + + + An array of into which to copy the values. The column values are expressed as SQL Server types. + + + Fills an array of that contains the values for all the columns in the record, expressed as SQL Server types. + + + An integer indicating the number of columns copied. + + + Returns the values for all the columns in the record in a single call, using the SQL type system instead of the CLR type system. The length of the array does not need to match the number of columns in the record. You can pass an array that contains fewer than the number of columns contained in the record. Only the amount of data the array holds is copied to the array, starting at the column with ordinal 0. You can also pass an array whose length is more than the number of columns contained in the resulting row. Any remaining columns are untouched. + + is null. + + + + The zero-based column ordinal. + + + Gets the value of the specified column as an XML value. + + + A value that contains the XML stored within the corresponding field. + + + + No conversions are performed; therefore, the data retrieved must already be an XML value. + + + Call to check for null values before calling this method. + + + + The index passed was outside the range of 0 to - 1 + + + An attempt was made to read or access columns in a closed . + + + The retrieved data is not compatible with the type. + + + + + The zero-based column ordinal. + + + Retrieves binary, image, varbinary, UDT, and variant data types as a . + + + A stream object. + + + + defaults to the value of ; but you can modify via GetStream. + + + Null values will be returned as an empty (zero bytes) . will raise an exception when used on an object returned by GetStream when is in effect. exceptions raised from are thrown as exceptions; check the inner exception for the . + + + The following members are not available for objects returned by GetStream: + + + BeginWrite + EndWrite + Length + Position + Seek + SetLength + Write + WriteByte + WriteTimeout + + + For more information, see SqlClient Streaming Support + + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Tried to read a previously-read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + + The returned type was not one of the types below: + + + binary + image + varbinary + udt + + + + + + The zero-based column ordinal. + + + Gets the value of the specified column as a string. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a string. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The column to be retrieved. + + + Retrieves Char, NChar, NText, NVarChar, text, varChar, and Variant data types as a . + + + The returned object. + + + + exceptions raised from are thrown as exceptions; check the inner exception for the . + + + Null values will be returned as an empty (zero bytes) . will raise an exception when used on an object returned by when is in effect. + + + For more information, see SqlClient Streaming Support. + + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Tried to read a previously-read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + The returned type was not one of the types below: + + char + nchar + ntext + nvarchar + text + varchar + + + + + + The zero-based column ordinal. + + + Retrieves the value of the specified column as a object. + + + The value of the specified column. + + + + No conversions are performed; therefore, the data retrieved must already be a object. + + + Call to check for null values before calling this method. + + + + The specified cast is not valid. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column in its native format. + + + This method returns for null database columns. + + + GetValue returns data using the .NET Framework types. + + + + + An array of into which to copy the attribute columns. + + + Populates an array of objects with the column values of the current row. + + + The number of instances of in the array. + + + + For most applications, this method provides an efficient means for retrieving all columns, instead of retrieving each column individually. + + + You can pass an array that contains fewer than the number of columns contained in the resulting row. Only the amount of data the array holds is copied to the array. You can also pass an array whose length is more than the number of columns contained in the resulting row. + + + This method returns for null database columns. + + + + + The following example demonstrates using a correctly sized array to read all values from the current row in the supplied . In addition, the sample demonstrates using a fixed-sized array that could be either smaller or larger than the number of available columns. + + + + // using Microsoft.Data.SqlClient; + private static void TestGetValues(SqlDataReader reader) + { + // Given a SqlDataReader, use the GetValues + // method to retrieve a full row of data. + // Test the GetValues method, passing in an array large + // enough for all the columns. + Object[] values = new Object[reader.FieldCount]; + int fieldCount = reader.GetValues(values); + + Console.WriteLine("reader.GetValues retrieved {0} columns.", + fieldCount); + for (int i = 0; i < fieldCount; i++) + { + Console.WriteLine(values[i]); + } + + Console.WriteLine(); + + // Now repeat, using an array that may contain a different + // number of columns than the original data. This should work correctly, + // whether the size of the array is larger or smaller than + // the number of columns. + + // Attempt to retrieve three columns of data. + values = new Object[3]; + fieldCount = reader.GetValues(values); + Console.WriteLine("reader.GetValues retrieved {0} columns.", fieldCount); + for (int i = 0; i < fieldCount; i++) + { + Console.WriteLine(values[i]); + } + } + + + + + + The value of the specified column. + + + Retrieves data of type XML as an . + + + The returned object. + + + + The object returned by does not support asynchronous operations. If you require asynchronous operations on an , cast the XML column to an NVARCHAR(MAX) on the server and use with . exceptions raised from are thrown as exceptions; check the inner exception for the . will raise an exception when used on an object returned by when is in effect. + + + For more information, see SqlClient Streaming Support. + + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Trying to read a previously read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + The returned type was not xml. + + + + + Gets a value that indicates whether the contains one or more rows. + + if the contains one or more rows; otherwise . + + + + + Retrieves a Boolean value that indicates whether the specified instance has been closed. + + + if the specified instance is closed; otherwise . + + + It is not possible to read from a instance that is closed. + + + + + A enumeration. + + + Determines whether the specified matches that of the . + + + if the specified is true, otherwise. + + + This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. + + + + + The zero-based column ordinal. + + + Gets a value that indicates whether the column contains non-existent or missing values. + + + if the specified column value is equivalent to ; otherwise . + + + Call this method to check for null column values before calling the typed get methods (for example, , , and so on) to avoid raising an error. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main(string[] args) + { + using (var connection = new SqlConnection(@"Data Source=(local);Initial Catalog=AdventureWorks2012;Integrated Security=SSPI")) + { + var command = new SqlCommand("SELECT p.FirstName, p.MiddleName, p.LastName FROM HumanResources.Employee AS e" + + " JOIN Person.Person AS p ON e.BusinessEntityID = p.BusinessEntityID;", connection); + connection.Open(); + var reader = command.ExecuteReader(); + while (reader.Read()) + { + Console.Write(reader.GetString(reader.GetOrdinal("FirstName"))); + // display middle name only of not null + if (!reader.IsDBNull(reader.GetOrdinal("MiddleName"))) + { + Console.Write(" {0}", reader.GetString(reader.GetOrdinal("MiddleName"))); + } + Console.WriteLine(" {0}", reader.GetString(reader.GetOrdinal("LastName"))); + } + connection.Close(); + } + } + } + + + + + + The zero-based column to be retrieved. + + + The cancellation instruction, which propagates a notification that operations should be canceled. This does not guarantee the cancellation. A setting of makes this method equivalent to . The returned task must be marked as cancelled. + + + + An asynchronous version of , which gets a value that indicates whether the column contains non-existent or missing values. + + + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + if the specified column value is equivalent to otherwise . + + For more information, see SqlClient Streaming Support. + + + + The connection drops or is closed during the data retrieval. + The is closed during the data retrieval. + There is no data ready to be read (for example, the first hasn't been called, or returned false). + Trying to read a previously read column in sequential mode. + There was an asynchronous operation in progress. This applies to all Get* methods when running in sequential mode, as they could be called while reading a stream. + + + + Trying to read a column that does not exist. + + + + + The zero-based column ordinal. + + + Gets the value of the specified column in its native format given the column ordinal. + + + The value of the specified column in its native format. + + + The index passed was outside the range of 0 through . + + + + + The column name. + + + Gets the value of the specified column in its native format given the column name. + + + The value of the specified column in its native format. + + + + A case-sensitive lookup is performed first. If it fails, a second case-insensitive search is made (a case-insensitive comparison is done using the database collation). Unexpected results can occur when comparisons are affected by culture-specific casing rules. For example, in Turkish, the following example yields the wrong results because the file system in Turkish does not use linguistic casing rules for the letter 'i' in "file". + + + This method is kana-width insensitive. + + + + No column with the specified name was found. + + + + + Advances the data reader to the next result, when reading the results of batch Transact-SQL statements. + + if there are more result sets; otherwise . + + + Used to process multiple results, which can be generated by executing batch Transact-SQL statements. + + + By default, the data reader is positioned on the first result. + + + + + + The cancellation instruction. + + + + An asynchronous version of , which advances the data reader to the next result, when reading the results of batch Transact-SQL statements. + + + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + + A task representing the asynchronous operation. + + + For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + Calling more than once for the same instance before task completion. + + + SQL Server returned an error while executing the command text. + + + + + Advances the to the next record. + + if there are more rows; otherwise + + + The default position of the is before the first record. Therefore, you must call to begin accessing any data. + + + Only one per associated may be open at a time, and any attempt to open another will fail until the first one is closed. Similarly, while the is being used, the associated is busy serving it until you call . + + + + + The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the using code block. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; - Trying to read a column that does not exist. - - - Gets the value of a column in its native format. - - - The zero-based column ordinal. - Gets the value of the specified column in its native format given the column ordinal. - The value of the specified column in its native format. - To be added. - The index passed was outside the range of 0 through . - - - The column name. - Gets the value of the specified column in its native format given the column name. - The value of the specified column in its native format. - - - - No column with the specified name was found. - - - Advances the data reader to the next result, when reading the results of batch Transact-SQL statements. - - if there are more result sets; otherwise . - - - - - - The cancellation instruction. - An asynchronous version of , which advances the data reader to the next result, when reading the results of batch Transact-SQL statements. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - A task representing the asynchronous operation. - - - - Calling more than once for the same instance before task completion. - SQL Server returned an error while executing the command text. - - - Advances the to the next record. - - if there are more rows; otherwise . - - is before the first record. Therefore, you must call to begin accessing any data. - - Only one `SqlDataReader` per associated may be open at a time, and any attempt to open another will fail until the first one is closed. Similarly, while the `SqlDataReader` is being used, the associated `SqlConnection` is busy serving it until you call . - - - -## Examples - The following example creates a , a , and a . The example reads through the data, writing it out to the console window. The code then closes the . The is closed automatically at the end of the `using` code block. - - [!code-csharp[SqlDataReader_Read Example#1](~/../sqlclient/doc/samples/SqlDataReader_Read.cs#1)] - - ]]> - - SQL Server returned an error while executing the command text. - - - The cancellation instruction. - An asynchronous version of , which advances the to the next record. - - The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. - A task representing the asynchronous operation. - - is set to `Default`, reads the entire row before returning the Task. - - For more information, including code samples, about asynchronous programming in the .NET Framework Data Provider for SQL Server, see [Asynchronous Programming](/sql/connect/ado-net/asynchronous-programming). + class Program + { + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI"; + ReadOrderData(str); + } -> [!NOTE] -> When reading large data (binary/text), it is recommended to use for optimal performance. + private static void ReadOrderData(string connectionString) + { + string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"; - - ]]> - - Calling more than once for the same instance before task completion. - SQL Server returned an error while executing the command text. - - - Gets the number of rows changed, inserted, or deleted by execution of the Transact-SQL statement. - The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements. - - and are the only properties that you can call after the is closed. - - ]]> - - - - Returns an enumerator that can be used to iterate through the item collection. - The enumerator that can be used to iterate through the item collection. - To be added. - - - A column ordinal. - Returns an for the specified column ordinal. - The instance for the specified column ordinal. - - instance is cast to an interface. - - ]]> - - - - Releases all resources that are used by the data reader. - To be added. - - - Gets the number of fields in the that are not hidden. - The number of fields that are not hidden. - - are visible. For example, a SELECT on a partial primary key returns the remaining parts of the key as hidden fields. The hidden fields are always appended behind the visible fields. - - ]]> - - -
+ using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + connection.Open(); + + SqlDataReader reader = command.ExecuteReader(); + + // Call Read before accessing data. + while (reader.Read()) + { + ReadSingleRow((IDataRecord)reader); + } + + // Call Close when done reading. + reader.Close(); + } + } + + private static void ReadSingleRow(IDataRecord record) + { + Console.WriteLine(String.Format("{0}, {1}", record[0], record[1])); + } + } + + + + SQL Server returned an error while executing the command text. + + + + + The cancellation instruction. + + + + An asynchronous version of , which advances the to the next record. + + + The cancellation token can be used to request that the operation be abandoned before the command timeout elapses. Exceptions will be reported via the returned Task object. + + + + A task representing the asynchronous operation. + + + + If the behavior parameter of is set to Default, ReadAsync reads the entire row before returning the Task. + + + For more information, including code samples, about asynchronous programming in the .NET Framework Data Provider for SQL Server, see Asynchronous Programming. + + + When reading large data (binary/text), it is recommended to use for optimal performance. + + + + Calling more than once for the same instance before task completion. + + + SQL Server returned an error while executing the command text. + + + + + Gets the number of rows changed, inserted, or deleted by execution of the Transact-SQL statement. + + + The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements. + + + The value of this property is cumulative. For example, if two records are inserted in batch mode, the value of RecordsAffected will be two. and are the only properties that you can call after the is closed. + + + + + Gets the information with the . + + + The associated with the . + + + + + A column ordinal. + + + Returns an for the specified column ordinal. + + + The instance for the specified column ordinal. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + Gets the number of fields in the that are not hidden. + + + The number of fields that are not hidden. + + + This value is used to determine how many fields in the are visible. For example, a SELECT on a partial primary key returns the remaining parts of the key as hidden fields. The hidden fields are always appended behind the visible fields. + + +
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlDependency.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlDependency.xml index 379fb5c930..09e44bb0e8 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlDependency.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlDependency.xml @@ -1,257 +1,305 @@ - - - - - The object represents a query notification dependency between an application and an instance of SQL Server. An application can create a object and register to receive notifications via the event handler. - - is ideal for caching scenarios, where your ASP.NET application or middle-tier service needs to keep certain information cached in memory. allows you to receive notifications when the original data in the database changes so that the cache can be refreshed. - - To set up a dependency, you need to associate a object to one or more objects. To receive notifications, you need to subscribe to the event. For more information about the requirements for creating queries for notifications, see [Working with Query Notifications](/sql/relational-databases/native-client/features/working-with-query-notifications). - -> [!NOTE] -> was designed to be used in ASP.NET or middle-tier services where there is a relatively small number of servers having dependencies active against the database. It was not designed for use in client applications, where hundreds or thousands of client computers would have objects set up for a single database server. If you are developing an application where you need reliable sub-second notifications when data changes, review the sections [Planning an Efficient Query Notifications Strategy](https://docs.microsoft.com/previous-versions/sql/sql-server-2008-r2/ms187528(v=sql.105)#planning-an-efficient-query-notifications-strategy) and [Alternatives to Query Notifications](https://docs.microsoft.com/previous-versions/sql/sql-server-2008-r2/ms187528(v=sql.105)#alternatives-to-query-notifications) in the [Planning for Notifications](https://docs.microsoft.com/previous-versions/sql/sql-server-2008-r2/ms187528(v%3dsql.105)) article. - - For more information, see [Query Notifications in SQL Server](/sql/connect/ado-net/sql/query-notifications-sql-server) and [Building Notification Solutions](https://docs.microsoft.com/previous-versions/sql/sql-server-2005/ms171065(v%3dsql.90)). - -> [!NOTE] -> The event may be generated on a different thread from the thread that initiated command execution. - - Query notifications are supported only for SELECT statements that meet a list of specific requirements. - - ]]> - - - - Creates a new instance of the class. - - - Creates a new instance of the class with the default settings. - - object using the default Service Broker service name and time-out. At some point after construction, you must use the method to associate one or more commands to this object. - - Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see [SQL Server Service Broker](/sql/database-engine/configure-windows/sql-server-service-broker) and [Working with Query Notifications](/sql/connect/oledb/features/working-with-query-notifications). - ]]> - - - - The object to associate with this object. The constructor will set up a object and bind it to the command. - Creates a new instance of the class and associates it with the parameter. - - class, and binds it to a object. - - Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see [SQL Server Service Broker](/sql/database-engine/configure-windows/sql-server-service-broker) and [Working with Query Notifications](/sql/connect/oledb/features/working-with-query-notifications). - - ]]> - - The parameter is NULL. - The object already has a object assigned to its property, and that is not associated with this dependency. - - - The object to associate with this object. The constructor sets up a object and bind it to the command. - The notification request options to be used by this dependency. to use the default service. - The time-out for this notification in seconds. The default is 0, indicating that the server's time-out should be used. - Creates a new instance of the class, associates it with the parameter, and specifies notification options and a time-out value. - - - - The parameter is NULL. - The time-out value is less than zero. - The object already has a object assigned to its property and that is not associated with this dependency. - - An attempt was made to create a **SqlDependency** instance from within SQLCLR. - - - A object containing a statement that is valid for notifications. - Associates a object with this instance. - - - - The parameter is null. - The object already has a object assigned to its property, and that is not associated with this dependency. - - - Gets a value that indicates whether one of the result sets associated with the dependency has changed. - A Boolean value indicating whether one of the result sets has changed. - - event, you can check the property to determine if the query results have changed. - - The property does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate a change event. - - ]]> - - - - Gets a value that uniquely identifies this instance of the class. - A string representation of a GUID that is generated for each instance of the class. - - property is used to uniquely identify a given instance. - - ]]> - - - - Occurs when a notification is received for any of the commands associated with this object. - - occurs when the results for the associated command change. If you are not using , you can check the property to determine whether the query results have changed. - - The event does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate . - - ]]> - - - - Starts the listener for receiving dependency change notifications. - - listener will restart when an error occurs in the SQL Server connection. - - Multiple calls to the method can be made, subject to the following restrictions: - -- Multiple calls with identical parameters (the same connection string and Windows credentials in the calling thread) are valid. - -- Multiple calls with different connection strings are valid as long as: - - - Each connection string specifies a different database, or - - - Each connection string specifies a different user, or - - - The calls come from different application domains. - - You can make the work correctly for applications that use multiple threads to represent different user credentials without giving the dbo role to the group, because different users can subscribe and listen (using or ) to a notification queue created by an administrator. When the relevant application domain starts, call Start with the (Windows) credentials of a user that has permission to initialize a service/queue (the CREATE QUEUE and CREATE SERVICE permissions for the database). Ensure that Start is only called once per AppDomain, otherwise an ambiguity exception is raised. The user thread must have permission to subscribe to the notification (the SUBSCRIBE QUERY NOTIFICATIONS permission for the database). will associate the subscription request of a non-administrator user to the service/queue created by the administrator. - - ]]> - - - - The connection string for the instance of SQL Server from which to obtain change notifications. - Starts the listener for receiving dependency change notifications from the instance of SQL Server specified by the connection string. - - if the listener initialized successfully; if a compatible listener already exists. - - for receiving dependency notifications from the instance of SQL Server specified by the `connectionString` parameter. This method may be called more than once with different connection strings for multiple servers. - - For additional remarks, see . - - ]]> - - The parameter is NULL. - The parameter is the same as a previous call to this method, but the parameters are different. - - The method was called from within the CLR. - The caller does not have the required code access security (CAS) permission. - A subsequent call to the method has been made with an equivalent parameter with a different user, or a user that does not default to the same schema. - - Also, any underlying **SqlClient** exceptions. - - - - The connection string for the instance of SQL Server from which to obtain change notifications. - An existing SQL Server Service Broker queue to be used. If , the default queue is used. - Starts the listener for receiving dependency change notifications from the instance of SQL Server specified by the connection string using the specified SQL Server Service Broker queue. - - if the listener initialized successfully; if a compatible listener already exists. - - for receiving dependency notifications from the instance of SQL Server specified by the `connectionString` parameter. This method may be called more than once with different connection strings for multiple servers. - - If no queue name is specified, creates a temporary queue and service in the server that is used for the entire process, even if the process involves more than one . The queue and service are automatically removed upon application shutdown. - - For additional remarks, see . - - ]]> - - The parameter is NULL. - The parameter is the same as a previous call to this method, but the parameters are different. - - The method was called from within the CLR. - The caller does not have the required code access security (CAS) permission. - A subsequent call to the method has been made with an equivalent parameter but a different user, or a user that does not default to the same schema. - - Also, any underlying **SqlClient** exceptions. - - - - Stops a listener for a connection specified in a previous call. - - listener will restart when an error occurs in the SQL Server connection. - - ]]> - - - - Connection string for the instance of SQL Server that was used in a previous call. - Stops a listener for a connection specified in a previous call. - - if the listener was completely stopped; if the was unbound from the listener, but there are is at least one other using the same listener. - - method must be called for each call. A given listener only shuts down fully when it receives the same number of requests as requests. - - ]]> - - The parameter is NULL. - The method was called from within SQLCLR. - The caller does not have the required code access security (CAS) permission. - An underlying **SqlClient** exception occurred. - - - Connection string for the instance of SQL Server that was used in a previous call. - The SQL Server Service Broker queue that was used in a previous call. - Stops a listener for a connection specified in a previous call. - - if the listener was completely stopped; if the was unbound from the listener, but there is at least one other using the same listener. - - method must be called for each call. A given listener only shuts down fully when it receives the same number of requests as requests. - - ]]> - - The parameter is NULL. - The method was called from within SQLCLR. - The caller does not have the required code access security (CAS) permission. - And underlying **SqlClient** exception occurred. - - + + + + + The object represents a query notification dependency between an application and an instance of SQL Server. An application can create a object and register to receive notifications via the event handler. + + + + is ideal for caching scenarios, where your ASP.NET application or middle-tier service needs to keep certain information cached in memory. allows you to receive notifications when the original data in the database changes so that the cache can be refreshed. + + + To set up a dependency, you need to associate a object to one or more objects. To receive notifications, you need to subscribe to the event. For more information about the requirements for creating queries for notifications, see Working with Query Notifications. + + + was designed to be used in ASP.NET or middle-tier services where there is a relatively small number of servers having dependencies active against the database. It was not designed for use in client applications, where hundreds or thousands of client computers would have objects set up for a single database server. If you are developing an application where you need reliable sub-second notifications when data changes, review the sections Planning an Effective Query Notifications Strategy and Alternatives to Query Notifications in the article + + + For more information, see Query Notifications in SQL Server and Building Notification Solutions. + + + The event may be generated on a different thread from the thread that initiated command execution. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. + + + + + + Creates a new instance of the class with the default settings. + + + + The constructor initializes the object using the default Service Broker service name and time-out. At some point after construction, you must use the method to associate one or more commands to this object. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see SQL Server Service Broker and Working with Query Notifications. + + + + + + The object to associate with this object. The constructor will set up a object and bind it to the command. + + + Creates a new instance of the class and associates it with the parameter. + + + + Internally, this constructor creates an instance of the class, and binds it to a object. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see SQL Server Service Broker and Working with Query Notifications. + + + + The parameter is NULL. + + + The object already has a object assigned to its property, and that is not associated with this dependency. + + + + + The object to associate with this object. The constructor sets up a object and bind it to the command. + + + The notification request options to be used by this dependency. to use the default service. + + + The time-out for this notification in seconds. The default is 0, indicating that the server's time-out should be used. + + + Creates a new instance of the class, associates it with the parameter, and specifies notification options and a time-out value. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see SQL Server Service Broker and Working with Query Notifications. + + + The parameter is NULL. + + + The time-out value is less than zero. + + + + + The object already has a object assigned to its property and that is not associated with this dependency. + + + An attempt was made to create a instance from within SQLCLR. + + + + + + + A object containing a statement that is valid for notifications. + + + Associates a object with this instance. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see SQL Server Service Broker and Working with Query Notifications. + + + The parameter is null. + + + The object already has a object assigned to its property, and that is not associated with this dependency. + + + + + Gets a value that indicates whether one of the result sets associated with the dependency has changed. + + + A Boolean value indicating whether one of the result sets has changed. + + + + If you are not using the event, you can check the property to determine if the query results have changed. + + + The property does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate a change event. + + + + + + Gets a value that uniquely identifies this instance of the class. + + + A string representation of a GUID that is generated for each instance of the class. + + + The property is used to uniquely identify a given instance. + + + + + Occurs when a notification is received for any of the commands associated with this object. + + + + occurs when the results for the associated command change. If you are not using , you can check the property to determine whether the query results have changed. + + + The event does not necessarily imply a change in the data. Other circumstances, such as time-out expired and failure to set the notification request, also generate . + + + + + + The connection string for the instance of SQL Server from which to obtain change notifications. + + + Starts the listener for receiving dependency change notifications from the instance of SQL Server specified by the connection string. + + if the listener initialized successfully; if a compatible listener already exists. + + + This method starts the listener for the for receiving dependency notifications from the instance of SQL Server specified by the parameter. This method may be called more than once with different connection strings for multiple servers. + + + Multiple calls to the method can be made, subject to the following restrictions: + + + Multiple calls with identical parameters (the same connection string and Windows credentials in the calling thread) are valid. + + Multiple calls with different connection strings are valid as long as: + + Each connection string specifies a different database, or + Each connection string specifies a different user, or + The calls come from different application domains. + + + + + You can make the work correctly for applications that use multiple threads to represent different user credentials without giving the dbo role to the group, because different users can subscribe and listen (using or ) to a notification queue created by an administrator. When the relevant application domain starts, call Start with the (Windows) credentials of a user that has permission to initialize a service/queue (the CREATE QUEUE and CREATE SERVICE permissions for the database). Ensure that Start is only called once per AppDomain, otherwise an ambiguity exception is raised. The user thread must have permission to subscribe to the notification (the SUBSCRIBE QUERY NOTIFICATIONS permission for the database). will associate the subscription request of a non-administrator user to the service/queue created by the administrator. + + + + The parameter is NULL. + + + + The parameter is the same as a previous call to this method, but the parameters are different. + The method was called from within the CLR. + + + + The caller does not have the required code access security (CAS) permission. + + + A subsequent call to the method has been made with an equivalent parameter with a different user, or a user that does not default to the same schema. Also, any underlying SqlClient exceptions. + + + + + + The connection string for the instance of SQL Server from which to obtain change notifications. + + + An existing SQL Server Service Broker queue to be used. If , the default queue is used. + + + Starts the listener for receiving dependency change notifications from the instance of SQL Server specified by the connection string using the specified SQL Server Service Broker queue. + + if the listener initialized successfully; if a compatible listener already exists. + + + This method starts the listener for the for receiving dependency notifications from the instance of SQL Server specified by the parameter. This method may be called more than once with different connection strings for multiple servers. + + + If no queue name is specified, creates a temporary queue and service in the server that is used for the entire process, even if the process involves more than one . The queue and service are automatically removed upon application shutdown. + + + Multiple calls to the method can be made, subject to the following restrictions: + + + Multiple calls with identical parameters (the same connection string and Windows credentials in the calling thread) are valid. + + Multiple calls with different connection strings are valid as long as: + + Each connection string specifies a different database, or + Each connection string specifies a different user, or + The calls come from different application domains. + + + + + You can make the work correctly for applications that use multiple threads to represent different user credentials without giving the dbo role to the group, because different users can subscribe and listen (using or ) to a notification queue created by an administrator. When the relevant application domain starts, call Start with the (Windows) credentials of a user that has permission to initialize a service/queue (the CREATE QUEUE and CREATE SERVICE permissions for the database). Ensure that Start is only called once per AppDomain, otherwise an ambiguity exception is raised. The user thread must have permission to subscribe to the notification (the SUBSCRIBE QUERY NOTIFICATIONS permission for the database). will associate the subscription request of a non-administrator user to the service/queue created by the administrator. + + + + The parameter is NULL. + + + + The parameter is the same as a previous call to this method, but the parameters are different. + The method was called from within the CLR. + + + + The caller does not have the required code access security (CAS) permission. + + + A subsequent call to the method has been made with an equivalent parameter but a different user, or a user that does not default to the same schema. Also, any underlying SqlClient exceptions. + + + + + + Connection string for the instance of SQL Server that was used in a previous call. + + + Stops a listener for a connection specified in a previous call. + + if the listener was completely stopped; if the was unbound from the listener, but there are is at least one other using the same listener. + + The Stop method must be called for each call. A given listener only shuts down fully when it receives the same number of Stop requests as requests. + + + The parameter is NULL. + + + The method was called from within SQLCLR. + + + The caller does not have the required code access security (CAS) permission. + + + An underlying SqlClient exception occurred. + + + + + Connection string for the instance of SQL Server that was used in a previous call. + + + The SQL Server Service Broker queue that was used in a previous call. + + + Stops a listener for a connection specified in a previous call. + + if the listener was completely stopped; if the was unbound from the listener, but there is at least one other using the same listener. + + The Stop method must be called for each call. A given listener only shuts down fully when it receives the same number of Stop requests as requests. + + + The parameter is NULL. + + + The method was called from within SQLCLR. + + + The caller does not have the required code access security (CAS) permission. + + + And underlying SqlClient exception occurred. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveAttestationParameters.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveAttestationParameters.xml index 295d8b25e8..7fc434fdf6 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveAttestationParameters.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveAttestationParameters.xml @@ -1,33 +1,48 @@ - - - - - Encapsulates the information SqlClient sends to SQL Server to initiate the process of attesting and creating a secure session with the enclave, SQL Server uses for computations on columns protected using Always Encrypted. - To be added. - - - The enclave attestation protocol. - The input of the enclave attestation protocol. - A Diffie-Hellman algorithm that encapsulates a client-side key pair. - Initializes a new instance of the class. - To be added. - - is . - - - Gets a Diffie-Hellman algorithm that encapsulates a key pair that SqlClient uses to establish a secure session with the enclave. - The Diffie-Hellman algorithm. - To be added. - - - Gets the information used to initiate the process of attesting the enclave. The format and the content of this information is specific to the attestation protocol. - The information required by SQL Server to execute attestation protocol identified by EnclaveAttestationProtocols. - To be added. - - - Gets the enclave attestation protocol identifier. - The enclave attestation protocol identifier. - To be added. - - + + + + + Encapsulates the information SqlClient sends to SQL Server to initiate the process of attesting and creating a secure session with the enclave, SQL Server uses for computations on columns protected using Always Encrypted. + + + + + The enclave attestation protocol. + + + The input of the enclave attestation protocol. + + + A Diffie-Hellman algorithm that encapsulates a client-side key pair. + + + Initializes a new instance of the class. + + is . + + + + Gets a Diffie-Hellman algorithm that encapsulates a key pair that SqlClient uses to establish a secure session with the enclave. + + + The Diffie-Hellman algorithm. + + + + + Gets the information used to initiate the process of attesting the enclave. The format and the content of this information is specific to the attestation protocol. + + + The information required by SQL Server to execute attestation protocol identified by EnclaveAttestationProtocols. + + + + + Gets the enclave attestation protocol identifier. + + + The enclave attestation protocol identifier. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveSession.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveSession.xml index 504e996459..4accad38fc 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveSession.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlEnclaveSession.xml @@ -1,29 +1,38 @@ - - - - - Encapsulates the state of a secure session between SqlClient and an enclave inside SQL Server, which can be used for computations on encrypted columns protected with Always Encrypted. - To be added. - - - The symmetric key used to encrypt all the information sent using the session. - The session ID. - Instantiates a new instance of the class. - To be added. - - is . - - has zero length. - - - Gets the symmetric key that SqlClient uses to encrypt all the information it sends to the enclave using the session. - The symmetric key. - To be added. - - - Gets the session ID. - The session ID. - To be added. - - + + + + + Encapsulates the state of a secure session between SqlClient and an enclave inside SQL Server, which can be used for computations on encrypted columns protected with Always Encrypted. + + + + + The symmetric key used to encrypt all the information sent using the session. + + + The session ID. + + + Instantiates a new instance of the class. + + is . + has zero length. + + + + Gets the symmetric key that SqlClient uses to encrypt all the information it sends to the enclave using the session. + + + The symmetric key. + + + + + Gets the session ID. + + + The session ID. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlError.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlError.xml index b164cdae13..2ebeb40480 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlError.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlError.xml @@ -1,207 +1,658 @@ - - - - - Collects information relevant to a warning or error returned by SQL Server. - - is created and managed by the , which in turn is created by the class. - - Messages with a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. - - The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server usually closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. - - For more information on errors generated by SQL Server, see [Cause and Resolution of Database Engine Errors](https://msdn.microsoft.com/library/ms365262.aspx). For more information about severity levels, see [Database Engine Error Severities](https://msdn.microsoft.com/library/ms164086.aspx). - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - - - - - Gets the severity level of the error returned from SQL Server. - A value from 1 to 25 that indicates the severity level of the error. The default is 0. - - remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server usually closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. - - For more information on errors generated by SQL Server, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError_State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets the line number within the Transact-SQL command batch or stored procedure that contains the error. - The line number within the Transact-SQL command batch or stored procedure that contains the error. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets the text describing the error. - The text describing the error. For more information on errors generated by SQL Server, see Database Engine Events and Errors. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets a number that identifies the type of error. - The number that identifies the type of error. - -
This number corresponds to an entry in the `master.dbo.sysmessages` table.|Typically greater than 0|No| -|Connection timeout|-2|0|Yes (Number = 258)| -|Communication error (non-LocalDB)|Win32 error code|0|Yes (Number = Win32 error code)| -|Communication error (LocalDB)|Win32 error code|0|No| -|Encryption capability mismatch|20|0|No| -|Failed to start LocalDB|Win32 error code|0|No| -|Read-only routing failure|0|0|No| -|Server had severe error processing query|0|0|No| -|Processed cancellation while parsing results|0|0|No| -|Failed to create user instance|0|0|No| - - For more information on errors generated by SQL Server, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]>
-
-
- - Gets the name of the stored procedure or remote procedure call (RPC) that generated the error. - The name of the stored procedure or RPC. For more information on errors generated by SQL Server, see Database Engine Events and Errors. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets the name of the instance of SQL Server that generated the error. - The name of the instance of SQL Server. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets the name of the provider that generated the error. - The name of the provider that generated the error. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Some error messages can be raised at multiple points in the code for the Database Engine. For example, an 1105 error can be raised for several different conditions. Each specific condition that raises an error assigns a unique state code. - The state code. - - within the collection. - - [!code-csharp[SqlError.State Example#1](~/../sqlclient/doc/samples/SqlError_State.cs#1)] - - ]]> - - - - Gets the complete text of the error message. - The complete text of the error. - - , and the stack trace. For example: - - SqlError:UserId or Password not valid. \ - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - -
+ + + + + Collects information relevant to a warning or error returned by SQL Server. + + + + This class is created by the .NET Framework Data Provider for SQL Server when an error occurs. An instance of is created and managed by the , which in turn is created by the class. + + + Messages with a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. + + + The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server usually closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. + + + For more information on errors generated by SQL Server, see Cause and Resolution of Database Engine Errors. For more information about severity levels, see Database Engine Error Severities. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + Constructs a new instance of the class. + + + + Gets the severity level of the error returned from SQL Server. + + + A value from 1 to 25 that indicates the severity level of the error. The default is 0. + + + + Messages with a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. + + + The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server usually closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. + + + For more information on errors generated by SQL Server, see Database Engine Events and Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the line number within the Transact-SQL command batch or stored procedure that contains the error. + + + The line number within the Transact-SQL command batch or stored procedure that contains the error. + + + + Line numbering starts at 1. If the value is 0, the line number is not applicable. + + + For more information on errors generated by SQL Server, see Database Engine Events and Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the text describing the error. + + + The text describing the error. For more information on errors generated by SQL Server, see + Database Engine Events and Errors + . + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets a number that identifies the type of error. + + + The number that identifies the type of error. + + + + The following table describes the possible values for this property: + + + + Source of Error + SqlError.Number + SqlError.State + SqlException has inner Win32Exception (beginning with.NET Framework 4.5) + + + Error from server + + + Server error code + + + This number corresponds to an entry in the master.dbo.sysmessages table. + + + Typically greater than 0 + No + + + Connection timeout + -2 + 0 + Yes (Number = 258) + + + Communication error (non-LocalDB) + Win32 error code + 0 + Yes (Number = Win32 error code) + + + Communication error (LocalDB) + Win32 error code + 0 + No + + + Encryption capability mismatch + 20 + 0 + No + + + Failed to start LocalDB + Win32 error code + 0 + No + + + Read-only routing failure + 0 + 0 + No + + + Server had severe error processing query + 0 + 0 + No + + + Processed cancellation while parsing results + 0 + 0 + No + + + Failed to create user instance + 0 + 0 + No + + + + For more information on errors generated by SQL Server, see Database Engine Events and Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the name of the stored procedure or remote procedure call (RPC) that generated the error. + + + The name of the stored procedure or RPC. For more information on errors generated by SQL Server, see Database Engine Events and Errors. + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the name of the instance of SQL Server that generated the error. + + + The name of the instance of SQL Server. + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the name of the provider that generated the error. + + + The name of the provider that generated the error. + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Some error messages can be raised at multiple points in the code for the Database Engine. For example, an 1105 error can be raised for several different conditions. Each specific condition that raises an error assigns a unique state code. + + + The state code. + + + + State is only set for errors that are received from the server. + + + For more information on errors generated by SQL Server, see Understanding Database Engine Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Data.SqlClient; + + namespace Classic_WebData_SqlError.StateCS + { + class Program + { + static void Main() + { + //DisplaySqlErrors(); + } + + public void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Source: " + exception.Errors[i].Source + "\n" + + "Number: " + exception.Errors[i].Number.ToString() + "\n" + + "State: " + exception.Errors[i].State.ToString() + "\n" + + "Class: " + exception.Errors[i].Class.ToString() + "\n" + + "Server: " + exception.Errors[i].Server + "\n" + + "Message: " + exception.Errors[i].Message + "\n" + + "Procedure: " + exception.Errors[i].Procedure + "\n" + + "LineNumber: " + exception.Errors[i].LineNumber.ToString()); + } + Console.ReadLine(); + } + } + } + + + + + + Gets the complete text of the error message. + + + The complete text of the error. + + + + The string is in the form "SqlError:", followed by the , and the stack trace. For example: + + + SqlError:UserId or Password not valid. \<stack trace> + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlErrorCollection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlErrorCollection.xml index 6c3133384c..9330ec6005 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlErrorCollection.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlErrorCollection.xml @@ -1,114 +1,290 @@ - - - - - Collects all errors generated by the .NET Framework Data Provider for SQL Server. This class cannot be inherited. - - to collect instances of the class. always contains at least one instance of the class. - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - - - - - Copies the elements of the collection. - - - The to copy elements into. - The index from which to start copying into the parameter. - Copies the elements of the collection into an , starting at the specified index. - To be added. - The sum of and the number of elements in the collection is greater than the of the . - The is . - The is not valid for . - - - The to copy the elements into. - The index from which to start copying into the parameter. - Copies the elements of the collection into a , starting at the specified index. - To be added. - The sum of and the number of elements in the collection is greater than the length of the . - The is . - The is not valid for . - - - Gets the number of errors in the collection. - The total number of errors in the collection. - - within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - - - Returns an enumerator that iterates through the . - An for the . - - - - - - The zero-based index of the error to retrieve. - Gets the error at the specified index. - A that contains the error at the specified index. - - within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - Index parameter is outside array bounds. - - - - For a description of this member, see . - - if access to the is synchronized (thread safe); otherwise, . - - instance is cast to an interface. - - ]]> - - - - For a description of this member, see . - An object that can be used to synchronize access to the . - - instance is cast to an interface. - - ]]> - - - + + + + Constructs and initializes a new instance of the class. + + + + Collects all errors generated by the .NET Framework Data Provider for SQL Server. This class cannot be inherited. + + + This class is created by to collect instances of the class. always contains at least one instance of the class. + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + The to copy elements into. + + + The index from which to start copying into the parameter. + + + Copies the elements of the collection into an , starting at the specified index. + + + The sum of and the number of elements in the collection is greater than the of the . + + + The is . + + + The is not valid for . + + + + + The to copy the elements into. + + + The index from which to start copying into the parameter. + + + Copies the elements of the collection into a , starting at the specified index. + + + The sum of and the number of elements in the collection is greater than the length of the . + + + The is . + + + The is not valid for . + + + + + Gets the number of errors in the collection. + + + The total number of errors in the collection. + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + Returns an enumerator that iterates through the . + + + An for the . + + + Enumerators can be used to read the data in a collection, but they cannot be used to modify the underlying collection. + + + + + The zero-based index of the error to retrieve. + + + Gets the error at the specified index. + + + A that contains the error at the specified index. + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + Index parameter is outside array bounds. + + + + + + For a description of this member, see . + + + if access to the is synchronized (thread safe); otherwise, . + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + For a description of this member, see . + + + An object that can be used to synchronize access to the . + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml index 9bb1ef18f3..7fe2e2e6b9 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml @@ -1,377 +1,892 @@ - - - - - The exception that is thrown when SQL Server returns a warning or error. This class cannot be inherited. - - always contains at least one instance of . - - Messages that have a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. - - The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. - - For information about the warning and informational messages sent by SQL Server, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). The class maps to SQL Server severity. - - The following is general information on handling exceptions. Your code should catch exceptions to prevent the application from crashing and to allow displaying a relevant error message to the user. You can use database transactions to ensure that the data is consistent regardless of what happens in the client application (including a crash). Features like System.Transaction.TransactionScope or the BeginTransaction method (in System.Data.OleDb.OleDbConnection, System.Data.ODBC.ODBCConnection, and Microsoft.Data.SqlClient.SqlConnection) ensure consistent data regardless of exceptions raised by a provider. Transactions can fail, so catch failures and retry the transaction. - - Note that beginning with .NET Framework 4.5, can return an inner . - - The exception class of a .NET Framework data provider reports provider-specific errors. For example System.Data.Odbc has OdbcException, System.Data.OleDb has OleDbException, and Microsoft.Data.SqlClient has SqlException. For the best level of error detail, catch these exceptions and use the members of these exception classes to get details of the error. - - In addition to the provider-specific errors, .NET Framework data provider types can raise .NET Framework exceptions such as System.OutOfMemoryException and System.Threading.ThreadAbortException. Recovery from these exceptions may not be possible. - - Bad input can cause a .NET Framework data provider type to raise an exception such as System.ArgumentException or System.IndexOutOfRangeException. Calling a method at the wrong time can raise System.InvalidOperationException. - - So, in general, write an exception handler that catches any provider specific exceptions as well as exceptions from the common language runtime. These can be layered as follows: - -```csharp -try { - // code here -} -catch (SqlException odbcEx) { - // Handle more specific SqlException exception here. -} -catch (Exception ex) { - // Handle generic ones here. -} - -``` - - Or: - -```csharp -try { - // code here -} -catch (Exception ex) { - if (ex is SqlException) { - // Handle more specific SqlException exception here. - } - else { - // Handle generic ones here. - } -} - -``` - - It is also possible for a .NET Framework data provider method call to fail on a thread pool thread with no user code on the stack. In this case, and when using asynchronous method calls, you must register the event to handle those exceptions and avoid application crash. - - - -## Examples - The following example generates a and then displays the exception. - - [!code-csharp[SqlException_Errors1 Example#1](~/../sqlclient/doc/samples/SqlException_Errors1.cs#1)] - - ]]> - - - - - - Gets the severity level of the error returned from the .NET Framework Data Provider for SQL Server. - A value from 1 to 25 that indicates the severity level of the error. - - remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. - - For information about the warning and informational messages sent by SQL Server, see the Troubleshooting section of the SQL Server documentation. - - This is a wrapper for the property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned. - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Represents the client connection ID. For more information, see Data Tracing in ADO.NET. - The client connection ID. - - . - - ]]> - - - - Gets a collection of one or more objects that give detailed information about exceptions generated by the .NET Framework Data Provider for SQL Server. - The collected instances of the class. - - class always contains at least one instance of the class. - - This is a wrapper for . For more information on SQL Server engine errors, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlError_ToString Example#1](~/../sqlclient/doc/samples/SqlError_ToString.cs#1)] - - ]]> - - - - - - The that holds the serialized object data about the exception being thrown. - The that contains contextual information about the source or destination. - Sets the with information about the exception. - - - - The parameter is a null reference ( in Visual Basic). - - - Gets the line number within the Transact-SQL command batch or stored procedure that generated the error. - The line number within the Transact-SQL command batch or stored procedure that generated the error. - - property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `int` is returned. - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Gets the text describing the error. - The text describing the error. - To be added. - - - Gets a number that identifies the type of error. - The number that identifies the type of error. - - property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `int` is returned. - - For more information on SQL Server engine errors, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). - - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Gets the name of the stored procedure or remote procedure call (RPC) that generated the error. - The name of the stored procedure or RPC. - - property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned. - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Gets the name of the computer that is running an instance of SQL Server that generated the error. - The name of the computer running an instance of SQL Server. - - property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned. - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Gets the name of the provider that generated the error. - The name of the provider that generated the error. - - property of the first in the property. - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Gets a numeric error code from SQL Server that represents an error, warning or "no data found" message. For more information about how to decode these values, see Database Engine Events and Errors. - The number representing the error code. - - property of the first in the property. - - If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned. - - -## Examples - The following example displays each within the collection. - - [!code-csharp[SqlException_Errors2 Example#1](~/../sqlclient/doc/samples/SqlException_Errors2.cs#1)] - - ]]> - - - - - - - - - - Returns a string that represents the current object, and includes the client connection ID (for more information, see ). - A string that represents the current object.. - - , which includes the client connection ID: - -```csharp -using Microsoft.Data.SqlClient; -using System; - -public class A { - public static void Main() { - SqlConnection connection = new SqlConnection(); - connection.ConnectionString = "Data Source=a_valid_server;Initial Catalog=Northwinda;Integrated Security=true"; - try { - connection.Open(); - } - catch (SqlException p) { - Console.WriteLine("{0}", p.ClientConnectionId); - Console.WriteLine("{0}", p.ToString()); - } - connection.Close(); - } -} -``` - - The following Visual Basic sample is functionally equivalent to the previous (C#) sample: - -```vb -Imports Microsoft.Data.SqlClient -Imports System - -Module Module1 - - Sub Main() - Dim connection As New SqlConnection() - connection.ConnectionString = "Data Source=a_valid_server;Initial Catalog=Northwinda;Integrated Security=true" - Try - connection.Open() - Catch p As SqlException - Console.WriteLine("{0}", p.ClientConnectionId) - Console.WriteLine("{0}", p.ToString()) - End Try - connection.Close() - End Sub - -End Module -``` - - ]]> - - - + + + + + The exception that is thrown when SQL Server returns a warning or error. This class cannot be inherited. + + + + This class is created whenever the .NET Framework Data Provider for SQL Server encounters an error generated from the server. (Client side errors are thrown as standard common language runtime exceptions.) always contains at least one instance of . + + + Messages that have a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. + + + The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. + + + For information about the warning and informational messages sent by SQL Server, see Database Engine Events and Errors. The class maps to SQL Server severity. + + + The following is general information on handling exceptions. Your code should catch exceptions to prevent the application from crashing and to allow displaying a relevant error message to the user. You can use database transactions to ensure that the data is consistent regardless of what happens in the client application (including a crash). Features like or the ensure consistent data regardless of exceptions raised by a provider. Transactions can fail, so catch failures and retry the transaction. + + + Note that beginning with .NET Framework 4.5, can return an inner . + + + The exception class of a .NET Framework data provider reports provider-specific errors. For example System.Data.Odbc has , System.Data.OleDb has , and Microsoft.Data.SqlClient has SqlException. For the best level of error detail, catch these exceptions and use the members of these exception classes to get details of the error. + + + Bad input can cause a .NET Framework data provider type to raise an exception such as System.ArgumentException or System.IndexOutOfRangeException. Calling a method at the wrong time can raise System.InvalidOperationException. + + + So, in general, write an exception handler that catches any provider specific exceptions as well as exceptions from the common language runtime. These can be layered as follows: + + + try +' { + // code here + } + catch (SqlException sqlEx) + { + // Handle more specific SqlException exception here. + } + catch (Exception ex) + { + // Handle generic ones here. + } + + Or: + + try + { + // code here + } + catch (Exception ex) + { + if (ex is SqlException) + { + // Handle more specific SqlException exception here. + } + else + { + // Handle generic ones here. + } + } + + + It is also possible for a .NET Framework data provider method call to fail on a thread pool thread with no user code on the stack. In this case, and when using asynchronous method calls, you must register the event to handle those exceptions and avoid application crash. + + + + + The following example generates a and then displays the exception. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + Gets the severity level of the error returned from the .NET Framework Data Provider for SQL Server. + + + A value from 1 to 25 that indicates the severity level of the error. + + + + Messages that have a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement. + + + The remains open when the severity level is 19 or less. When the severity level is 20 or greater, the server ordinarily closes the . However, the user can reopen the connection and continue. In both cases, a is generated by the method executing the command. + + + For information about the warning and informational messages sent by SQL Server, see the Troubleshooting section of the SQL Server documentation. + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for byte is returned. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using System.Text; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistantStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Represents the client connection ID. For more information, see Data Tracing in ADO.NET. + + + The client connection ID. + + + For a code sample, see . + + + + + Gets a collection of one or more objects that give detailed information about exceptions generated by the .NET Framework Data Provider for SQL Server. + + + The collected instances of the class. + + + + The class always contains at least one instance of the class. + + + This is a wrapper for . For more information on SQL Server engine errors, see Database Engine Events and Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + DisplaySqlErrors(ex); + } + } + } + + private static void DisplaySqlErrors(SqlException exception) + { + for (int i = 0; i < exception.Errors.Count; i++) + { + Console.WriteLine("Index #" + i + "\n" + + "Error: " + exception.Errors[i].ToString() + "\n"); + } + Console.ReadLine(); + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + To be added + + + + Gets the line number within the Transact-SQL command batch or stored procedure that generated the error. + + + The line number within the Transact-SQL command batch or stored procedure that generated the error. + + + + The line numbering starts at 1; if 0 is returned, the line number is not applicable. + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for int is returned. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Gets the text describing the error. + + + The text describing the error. + + + + + Gets a number that identifies the type of error. + + + The number that identifies the type of error. + + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for int is returned. + + + For more information on SQL Server engine errors, see Database Engine Events and Errors. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Gets the name of the stored procedure or remote procedure call (RPC) that generated the error. + + + The name of the stored procedure or RPC. + + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for string is returned. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Gets the name of the computer that is running an instance of SQL Server that generated the error. + + + The name of the computer running an instance of SQL Server. + + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for string is returned. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Gets the name of the provider that generated the error. + + + The name of the provider that generated the error. + + + This is a wrapper for the property of the first in the property. + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Gets the instance that generated the error or if the exception was not raised from a batch. + + + A object or + + + + + + + + + + + If this was thrown when executing a , references the specific which triggered the exception. + + + The specific which triggered the exception. + + + If this wasn't thrown when executing a , the value is . + + + + + Gets a numeric error code from SQL Server that represents an error, warning or "no data found" message. For more information about how to decode these values, see Database Engine Events and Errors. + + + The number representing the error code. + + + + This is a wrapper for the property of the first in the property. + + + If is , the default value for byte is returned. + + + + + The following example displays each within the collection. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + using System.Text; + + class Program + { + static void Main() + { + string s = GetConnectionString(); + ShowSqlException(s); + Console.ReadLine(); + } + + public static void ShowSqlException(string connectionString) + { + string queryString = "EXECUTE NonExistentStoredProcedure"; + StringBuilder errorMessages = new StringBuilder(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(queryString, connection); + try + { + command.Connection.Open(); + command.ExecuteNonQuery(); + } + catch (SqlException ex) + { + for (int i = 0; i < ex.Errors.Count; i++) + { + errorMessages.Append("Index #" + i + "\n" + + "Message: " + ex.Errors[i].Message + "\n" + + "Error Number: " + ex.Errors[i].Number + "\n" + + "LineNumber: " + ex.Errors[i].LineNumber + "\n" + + "Source: " + ex.Errors[i].Source + "\n" + + "Procedure: " + ex.Errors[i].Procedure + "\n"); + } + Console.WriteLine(errorMessages.ToString()); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + + + + + + + Returns a string that represents the current object, and includes the client connection ID (for more information, see ). + + + A string that represents the current object. . + + + + The following example shows how a connection attempt to a valid server but non-existent database causes a , which includes the client connection ID: + + + using System; + using Microsoft.Data.SqlClient; + + public class A + { + public static void Main() + { + SqlConnection connection = new SqlConnection(); + connection.ConnectionString = "Data Source=a_valid_server;Initial Catalog=Northwinda;Integrated Security=true"; + + try + { + connection.Open(); + } + catch (SqlException p) + { + Console.WriteLine("{0}", p.ClientConnectionId); + Console.WriteLine("{0}", p.ToString()); + } + + connection.Close(); + } + } + + + Imports System + Imports Microsoft.Data.SqlClient + + Module Module1 + Sub Main() + Dim connection As New SqlConnection() + connection.ConnectionString = "Data Source=a_valid_server;Initial Catalog=Northwinda;Integrated Security=true" + + Try + connection.Open() + Catch p As SqlException + Console.WriteLine("{0}", p.ClientConnectionId) + Console.WriteLine("{0}", p.ToString()) + End Try + + connection.Close() + End Sub + End Module + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventArgs.xml index f7965a43cd..8dbbaa6f8a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventArgs.xml @@ -1,52 +1,60 @@ - - - - - Provides data for the event. - - event contains a collection which contains the warnings sent from the server. - - An event is generated when a SQL Server message with a severity level of 10 or less occurs. - - ]]> - - - - Gets the collection of warnings sent from the server. - The collection of warnings sent from the server. - To be added. - - - Gets the full text of the error sent from the database. - The full text of the error. - - property of the first in the collection. - - ]]> - - - - Gets the name of the object that generated the error. - The name of the object that generated the error. - - property of the first in the collection. - - ]]> - - - - Retrieves a string representation of the event. - A string representing the event. - To be added. - - + + + + + Provides data for the event. + + + + The event contains a collection which contains the warnings sent from the server. + + + An event is generated when a SQL Server message with a severity level of 10 or less occurs. + + + + + + Constructs and initializes a new instance of + + + + + Gets the collection of warnings sent from the server. + + + The collection of warnings sent from the server. + + + + + Gets the full text of the error sent from the database. + + + The full text of the error. + + + This is a wrapper for the property of the first in the collection. + + + + + Gets the name of the object that generated the error. + + + The name of the object that generated the error. + + + This is a wrapper for the property of the first in the collection. + + + + + Retrieves a string representation of the event. + + + A string representing the event. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventHandler.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventHandler.xml index 884b18fb68..80bcd95be0 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventHandler.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlInfoMessageEventHandler.xml @@ -1,18 +1,18 @@ - - - - - The source of the event. - A object that contains the event data. - Represents the method that will handle the event of a . - - delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see [Handling and Raising Events](/dotnet/standard/events/). - - ]]> - - - + + + + + The source of the event. + + + A object that contains the event data. + + + Represents the method that will handle the event of a . + + + When you create a delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see Handling and Raising Events. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationEventArgs.xml index 0e8a69c33b..55b739d5e1 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationEventArgs.xml @@ -1,41 +1,50 @@ - - - - - Represents the set of arguments passed to the notification event handler. - To be added. - - - - value that indicates whether this notification is generated because of an actual change, or by the subscription. - - value that indicates the reason for the notification event. This may occur because the data in the store actually changed, or the notification became invalid (for example, it timed out). - - value that indicates the source that generated the notification. - Creates a new instance of the object. - To be added. - - - Gets a value that indicates the reason for the notification event, such as a row in the database being modified or a table being truncated. - The notification event reason. - - - - - - Gets a value that indicates the source that generated the notification, such as a change to the query data or the database's state. - The source of the notification. - To be added. - - - Gets a value that indicates whether this notification is generated because of an actual change, or by the subscription. - A value indicating whether the notification was generated by a change or a subscription. - To be added. - - + + + + + Represents the set of arguments passed to the notification event handler. + + + + + value that indicates whether this notification is generated because of an actual change, or by the subscription. + + + value that indicates the reason for the notification event. This may occur because the data in the store actually changed, or the notification became invalid (for example, it timed out). + + + value that indicates the source that generated the notification. + + + Creates a new instance of the object. + + + + + Gets a value that indicates the reason for the notification event, such as a row in the database being modified or a table being truncated. + + + The notification event reason. + + + This event may occur because the data in the store actually changed, or the notification is no longer valid (for example, it timed out). + + + + + Gets a value that indicates the source that generated the notification, such as a change to the query data or the database's state. + + + The source of the notification. + + + + + Gets a value that indicates whether this notification is generated because of an actual change, or by the subscription. + + + A value indicating whether the notification was generated by a change or a subscription. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationInfo.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationInfo.xml index 979682d203..9d18d58528 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationInfo.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationInfo.xml @@ -1,73 +1,107 @@ - - - - - This enumeration provides additional information about the different notifications that can be received by the dependency event handler. - - enumeration is referenced by an instance of the class. - - ]]> - - - - The object already fired, and new commands cannot be added to it. - - - An underlying server object related to the query was modified. - - - Data was changed by a DELETE statement. - - - An underlying object related to the query was dropped. - - - An internal server error occurred. - - - The object has expired. - - - Data was changed by an INSERT statement. - - - A statement was provided that cannot be notified (for example, an UPDATE statement). - - - The statement was executed under an isolation mode that was not valid (for example, Snapshot). - - - Used to distinguish the server-side cause for a query notification firing. - - - The SET options were not set appropriately at subscription time. - - - A previous statement has caused query notifications to fire under the current transaction. - - - A SELECT statement that cannot be notified or was provided. - - - Fires as a result of server resource pressure. - - - The server was restarted (notifications are sent during restart.). - - - The subscribing query causes the number of templates on one of the target tables to exceed the maximum allowable limit. - - - One or more tables were truncated. - - - Used when the info option sent by the server was not recognized by the client. - - - Data was changed by an UPDATE statement. - - + + + + + This enumeration provides additional information about the different notifications that can be received by the dependency event handler. + + + The enumeration is referenced by an instance of the class. + + + + + The object already fired, and new commands cannot be added to it. + + + + + An underlying server object related to the query was modified. + + + + + Data was changed by a DELETE statement. + + + + + An underlying object related to the query was dropped. + + + + + An internal server error occurred. + + + + + The object has expired. + + + + + Data was changed by an INSERT statement. + + + + + A statement was provided that cannot be notified (for example, an UPDATE statement). + + + + + The statement was executed under an isolation mode that was not valid (for example, Snapshot). + + + + + Used to distinguish the server-side cause for a query notification firing. + + + + + The SET options were not set appropriately at subscription time. + + + + + A previous statement has caused query notifications to fire under the current transaction. + + + + + A SELECT statement that cannot be notified or was provided. + + + + + Fires as a result of server resource pressure. + + + + + The server was restarted (notifications are sent during restart.). + + + + + The subscribing query causes the number of templates on one of the target tables to exceed the maximum allowable limit. + + + + + One or more tables were truncated. + + + + + Used when the info option sent by the server was not recognized by the client. + + + + + Data was changed by an UPDATE statement. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationSource.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationSource.xml index 95719bd6c2..ec5c5ef6ff 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationSource.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationSource.xml @@ -1,51 +1,73 @@ - + - - - Indicates the source of the notification received by the dependency event handler. - - class. - - Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see [SQL Server Service Broker](/sql/database-engine/configure-windows/sql-server-service-broker) and [Working with Query Notifications](/sql/connect/oledb/features/working-with-query-notifications). - - ]]> - - - - A client-initiated notification occurred, such as a client-side time-out or as a result of attempting to add a command to a dependency that has already fired. - - - Data has changed; for example, an insert, update, delete, or truncate operation occurred. - - - The database state changed; for example, the database related to the query was dropped or detached. - - - The run-time environment was not compatible with notifications; for example, the isolation level was set to snapshot, or one or more SET options are not compatible. - - - A run-time error occurred during execution. - - - A database object changed; for example, an underlying object related to the query was dropped or modified. - - - Internal only; not intended to be used in your code. - - - The Transact-SQL statement is not valid for notifications; for example, a SELECT statement that could not be notified or a non-SELECT statement was executed. - - - A system-related event occurred. For example, there was an internal error, the server was restarted, or resource pressure caused the invalidation. - - - The subscription time-out expired. - - - Used when the source option sent by the server was not recognized by the client. - - + + + + Indicates the source of the notification received by the dependency event handler. + + + + The SqlNotificationSource enumeration is referenced by an instance of the class. + + + Query notifications are supported only for SELECT statements that meet a list of specific requirements. For more information, see SQL Server Service Broker and Working with Query Notifications. + + + + + + A client-initiated notification occurred, such as a client-side time-out or as a result of attempting to add a command to a dependency that has already fired. + + + + + Data has changed; for example, an INSERT, UPDATE, DELETE, or TRUNCATE operation occurred. + + + + + The database state changed; for example, the database related to the query was dropped or detached. + + + + + The run-time environment was not compatible with notifications; for example, the isolation level was set to snapshot, or one or more SET options are not compatible. + + + + + A run-time error occurred during execution. + + + + + A database object changed; for example, an underlying object related to the query was dropped or modified. + + + + + Internal only; not intended to be used in your code. + + + + + The Transact-SQL statement is not valid for notifications; for example, a SELECT statement that could not be notified or a non-SELECT statement was executed. + + + + + A system-related event occurred. For example, there was an internal error, the server was restarted, or resource pressure caused the invalidation. + + + + + The subscription time-out expired. + + + + + Used when the source option sent by the server was not recognized by the client. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationType.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationType.xml index ce1afde79e..2b022f2bea 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationType.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlNotificationType.xml @@ -1,25 +1,27 @@ - - - - - Describes the different notification types that can be received by an event handler through the parameter. - - enumeration is referenced by an instance of the class. This information is provided when a notification event is fired with the class. - - ]]> - - - - Data on the server being monitored changed. Use the item to determine the details of the change. - - - There was a failure to create a notification subscription. Use the object's item to determine the cause of the failure. - - - Used when the type option sent by the server was not recognized by the client. - - + + + + + Describes the different notification types that can be received by an event handler through the parameter. + + + The enumeration is referenced by an instance of the class. This information is provided when a notification event is fired with the class. + + + + + Data on the server being monitored changed. Use the item to determine the details of the change. + + + + + There was a failure to create a notification subscription. Use the object's item to determine the cause of the failure. + + + + + Used when the type option sent by the server was not recognized by the client. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml index 78ae193eba..c439910d87 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml @@ -1,653 +1,1012 @@ - - - - - Represents a parameter to a and optionally its mapping to columns. This class cannot be inherited. For more information on parameters, see [Configuring parameters](/sql/connect/ado-net/configure-parameters). - - [!NOTE] -> Nameless, also called ordinal, parameters are not supported by the .NET Framework Data Provider for SQL Server. - - For more information, along with additional sample code demonstrating how to use parameters, see [Commands and Parameters](/sql/connect/ado-net/commands-parameters). - - - -## Examples - The following example creates multiple instances of through the collection within the . These parameters are used to select data from the data source and put the data in the . This example assumes that a and a have already been created by using the appropriate schema, commands, and connection. For more information and additional examples on using parameters, see [Retrieving and Modifying Data in ADO.NET](/sql/connect/ado-net/retrieving-modifying-data) and [Configuring parameters](/sql/connect/ado-net/configure-parameters). - - [!code-csharp[SqlParameterCollection_Add6](~/../sqlclient/doc/samples/SqlParameterCollection_Add6.cs#1)] - - ]]> - - - - - - Initializes a new instance of the class. - - - Initializes a new instance of the class. - - and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter.cs#1)] - - ]]> - - - - The name of the parameter to map. - One of the values. - Initializes a new instance of the class that uses the parameter name and the data type. - - are inferred from the value of the `dbType` parameter. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter2 Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter2.cs#1)] - - ]]> - - The value supplied in the parameter is an invalid back-end data type. - - - The name of the parameter to map. - An that is the value of the . - Initializes a new instance of the class that uses the parameter name and a value of the new . - - in the `value` parameter, the is inferred from the Microsoft .NET Framework type of the . - - Use caution when you use this overload of the constructor to specify integer parameter values. Because this overload takes a `value` of type , you must convert the integral value to an type when the value is zero, as the following C# example demonstrates. - -```csharp -Parameter = new SqlParameter("@pname", (object)0); -``` - -If you do not perform this conversion, the compiler assumes that you are trying to call the constructor overload. - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter6 Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter6.cs#1)] - - ]]> - - - - The name of the parameter to map. - One of the values. - The length of the parameter. - Initializes a new instance of the class that uses the parameter name, the , and the size. - - and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter4 Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter4.cs#1)] - - ]]> - - The value supplied in the parameter is an invalid back-end data type. - - - The name of the parameter to map. - One of the values. - The length of the parameter. - The name of the source column () if this is used in a call to >. - Initializes a new instance of the class that uses the parameter name, the , the size, and the source column name. - - and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter5 Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter5.cs#1)] - - ]]> - - The value supplied in the parameter is an invalid back-end data type. - - - The name of the parameter to map. - One of the values. - The length of the parameter. - One of the values. - - if the value of the field can be null; otherwise, . - The total number of digits to the left and right of the decimal point to which is resolved. - The total number of decimal places to which is resolved. - The name of the source column () if this is used in a call to . - One of the values. - An that is the value of the . - Initializes a new instance of the class that uses the parameter name, the type of the parameter, the size of the parameter, a , the precision of the parameter, the scale of the parameter, the source column, a to use, and the value of the parameter. - - are inferred from the value of the `dbType` parameter if they are not explicitly set in the `size` and `precision` parameters. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_SqlParameter1 Example#1](~/../sqlclient/doc/samples/SqlParameter_SqlParameter1.cs#1)] - - ]]> - - The value supplied in the parameter is an invalid back-end data type. - - - The name of the parameter to map. - One of the values. - The length of the parameter. - One of the values. - The total number of digits to the left and right of the decimal point to which is resolved. - The total number of decimal places to which is resolved. - The name of the source column () if this is used in a call to >. - One of the values. - - if the source column is nullable; if it is not. - An that is the value of the . - The name of the database where the schema collection for this XML instance is located. - The owning relational schema where the schema collection for this XML instance is located. - The name of the schema collection for this parameter. - Initializes a new instance of the class that uses the parameter name, the type of the parameter, the length of the parameter the direction, the precision, the scale, the name of the source column, one of the values, a Boolean for source column mapping, the value of the , the name of the database where the schema collection for this XML instance is located, the owning relational schema where the schema collection for this XML instance is located, and the name of the schema collection for this parameter. - - and are inferred from the value of the `dbType` parameter if they are not explicitly set in the `size` and `precision` parameters. - - ]]> - - - - Gets or sets the object that defines how string comparisons should be performed for this parameter. - A object that defines string comparison for this parameter. - To be added. - - - Gets or sets the of the parameter. - One of the values. The default is . - - and are linked. Therefore, setting the changes the to a supporting . - - For a list of the supported data types, see the appropriate member. For more information, see [DataAdapter Parameters](/sql/connect/ado-net/dataadapter-parameters). - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_IsNullable Example#1](~/../sqlclient/doc/samples/SqlParameter_IsNullable.cs#1)] - - ]]> - - - - Gets or sets a value that indicates whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. - One of the values. The default is . - - is output, and execution of the associated does not return a value, the contains a null value. - - `Output`, `InputOut`, and `ReturnValue` parameters returned by calling cannot be accessed until you close the . - - - -## Examples - The following example creates a and sets some of its properties. - - [Commands and Parameters](/sql/connect/ado-net/commands-parameters) - - [DataAdapter Parameters](/sql/connect/ado-net/dataadapter-parameters) - - [SQL Server and ADO.NET](/sql/connect/ado-net/sql/) - - ]]> - - The property was not set to one of the valid values. - - - Enforces encryption of a parameter when using Always Encrypted. If SQL Server informs the driver that the parameter does not need to be encrypted, the query using the parameter will fail. This property provides additional protection against security attacks that involve a compromised SQL Server providing incorrect encryption metadata to the client, which may lead to data disclosure. - - if the parameter has a force column encryption; otherwise, . - To be added. - - - Gets or sets a value that indicates whether the parameter accepts null values. is not used to validate the parameter's value and will not prevent sending or receiving a null value when executing a command. - - if null values are accepted; otherwise, . The default is . - - class. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#2](~/../sqlclient/doc/samples/SqlParameter.cs#2)] - - ]]> - - - - Gets or sets the locale identifier that determines conventions and language for a particular region. - The locale identifier associated with the parameter. - - property. - -```csharp -static void CreateSqlParameterLocaleId(){ - SqlParameter parameter = new SqlParameter("pName", SqlDbType.VarChar); - parameter.LocaleId = 1033; // English - United States -} -``` - - ]]> - - - - Gets or sets the offset to the property. - The offset to the . The default is 0. - - and sets some of its properties. - - [!code-csharp[SqlParameter#3](~/../sqlclient/doc/samples/SqlParameter.cs#3)] - - ]]> - - - - Gets or sets the name of the . - The name of the . The default is an empty string. - - is specified in the form @paramname. You must set before executing a that relies on parameters. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_ParameterName Example#1](~/../sqlclient/doc/samples/SqlParameter_ParameterName.cs#1)] - - ]]> - - - - Gets or sets the maximum number of digits used to represent the property. - The maximum number of digits used to represent the property. The default value is 0. This indicates that the data provider sets the precision for . - - property is used by parameters that have a of `Decimal`. - - You do not need to specify values for the and properties for input parameters, as they can be inferred from the parameter value. `Precision` and `Scale` are required for output parameters and for scenarios where you need to specify complete metadata for a parameter without indicating a value, such as specifying a null value with a specific precision and scale. - -> [!NOTE] -> Use of this property to coerce data passed to the database is not supported. To round, truncate, or otherwise coerce data before passing it to the database, use the class that is part of the `System` namespace prior to assigning a value to the parameter's `Value` property. - -> [!NOTE] -> Microsoft .NET Framework data providers that are included with the .NET Framework version 1.0 do not verify the or of parameter values. This can cause truncated data being inserted at the data source. If you are using .NET Framework version 1.0, validate the and of values before setting the parameter value. When you use .NET Framework version 1.1 or a later version, an exception is thrown if a parameter value is set with an invalid . values that exceed the parameter scale are still truncated. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter_Precision Example#1](~/../sqlclient/doc/samples/SqlParameter_Precision.cs#1)] - - ]]> - - - - Resets the type associated with this . - - and properties of the . - - ]]> - - - - Resets the type associated with this . - - and properties of the . - - ]]> - - - - Gets or sets the number of decimal places to which is resolved. - The number of decimal places to which is resolved. The default is 0. - - property is used by parameters that have a of `Decimal`. - -> [!WARNING] -> Data may be truncated if the property is not explicitly specified and the data on the server does not fit in scale 0 (the default). - - You do not need to specify values for the and properties for input parameters, as they can be inferred from the parameter value. `Precision` and `Scale` are required for output parameters and for scenarios where you need to specify complete metadata for a parameter without indicating a value, such as specifying a null value with a specific precision and scale. - -> [!NOTE] -> Use of this property to coerce data passed to the database is not supported. To round, truncate, or otherwise coerce data before passing it to the database, use the class that is part of the `System` namespace prior to assigning a value to the parameter's `Value` property. - -> [!NOTE] -> .NET Framework data providers that are included with the .NET Framework version 1.0 do not verify the or of parameter values. This can cause truncated data to be inserted at the data source. If you are using .NET Framework version 1.0, validate the and of values before setting the parameter value. values that exceed the parameter scale are still truncated. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#4](~/../sqlclient/doc/samples/SqlParameter.cs#4)] - - ]]> - - - - Gets or sets the maximum size, in bytes, of the data within the column. - The maximum size, in bytes, of the data within the column. The default value is inferred from the parameter value. - - . For character types, the size specified with is in characters. - - The property is used for binary and string types. For parameters of type `SqlType.String`, `Size` means length in Unicode characters. For parameters of type `SqlType.Xml`, `Size` is ignored. - - For nonstring data types and ANSI string data, the property refers to the number of bytes. For Unicode string data, refers to the number of characters. The count for strings does not include the terminating character. - - For variable-length data types, describes the maximum amount of data to transmit to the server. For example, for a Unicode string value, could be used to limit the amount of data sent to the server to the first one hundred characters. - - If not explicitly set, the size is inferred from the actual size of the specified parameter value. - - If the fractional part of the parameter value is greater than the size, then the value will be truncated to match the size. - - For fixed length data types, the value of is ignored. It can be retrieved for informational purposes, and returns the maximum amount of bytes the provider uses when transmitting the value of the parameter to the server. - - For information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#5](~/../sqlclient/doc/samples/SqlParameter.cs#5)] - - ]]> - - - - Gets or sets the name of the source column mapped to the and used for loading or returning the - The name of the source column mapped to the . The default is an empty string. - - is set to anything other than an empty string, the value of the parameter is retrieved from the column with the name. If is set to `Input`, the value is taken from the . If is set to `Output`, the value is taken from the data source. A of `InputOutput` is a combination of both. - - For more information about how to use the property, see [DataAdapter Parameters](/sql/connect/ado-net/dataadapter-parameters) and [Updating Data Sources with DataAdapters](/sql/connect/ado-net/update-data-sources-with-dataadapters). - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#6](~/../sqlclient/doc/samples/SqlParameter.cs#6)] - - ]]> - - - - Sets or gets a value which indicates whether the source column is nullable. This allows to correctly generate Update statements for nullable columns. - - if the source column is nullable; if it is not. - - is used by the to correctly generate update commands when dealing with nullable columns. Generally, use of is limited to developers inheriting from . - - uses this property to determine whether the source column is nullable, and sets this property to `true` if it is nullable, and `false` if it is not. When is generating its Update statement, it examines the for each parameter. If the property is `true`, generates a WHERE clauses like the following (in this query expression, "FieldName" represents the name of the field): - -``` -((@IsNull_FieldName = 1 AND FieldName IS NULL) OR - (FieldName = @Original_FieldName)) -``` - - If for the field is false, generates the following WHERE clause: - -``` -FieldName = @OriginalFieldName -``` - - In addition, @IsNull_FieldName contains 1 if the source field contains null, and 0 if it does not. This mechanism allows for a performance optimization in SQL Server, and provides for common code that works across multiple providers. - - ]]> - - - - Gets or sets the to use when you load - One of the values. The default is . - - used by the `DataRow.Item` property, or one of the `DataRow.GetChildRows` methods of the object. - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#7](~/../sqlclient/doc/samples/SqlParameter.cs#7)] - - ]]> - - - - Gets or sets the of the parameter. - One of the values. The default is . - - and are linked. Therefore, setting the changes the to a supporting . - - For a list of the supported data types, see the appropriate member. For more information, see [DataAdapter Parameters](/sql/connect/ado-net/dataadapter-parameters). - - For information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - - - Gets or sets the value of the parameter as an SQL type. - An that is the value of the parameter, using SQL types. The default value is null. - - that is sent to the server. For output and return value parameters, the value is set on completion of the and after the is closed. - - This property can be set to null or . Use to send a NULL value as the value of the parameter. Use null or do not set to use the default value for the parameter. - - If the application specifies the database type, the bound value is converted to that type when the provider sends the data to the server. The provider tries to convert any type of value if it supports the interface. Conversion errors may result if the specified type is not compatible with the value. - - Both the and properties can be inferred by setting the . - - The property is overwritten by `SqlDataAdapter.UpdateCommand`. - - Use the property to return parameter values as common language runtime (CLR) types. - - For information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - ]]> - - - - For a description of this member, see . - A new that is a copy of this instance. - - instance is cast to an interface. - - ]]> - - - - Gets a string that contains the . - A string that contains the . - To be added. - - - Gets or sets the type name for a table-valued parameter. - The type name of the specified table-valued parameter. - To be added. - - - Gets or sets a that represents a user-defined type as a parameter. - A that represents the fully qualified name of a user-defined type in the database. - - , see [Retrieving UDT Data](https://msdn.microsoft.com/library/ms131080.aspx). - - ]]> - - - - Gets or sets the value of the parameter. - An that is the value of the parameter. The default value is null. - - that is sent to the server. For output and return value parameters, the value is set on completion of the and after the is closed. - - This property can be set to `null` or . Use to send a NULL value as the value of the parameter. Use `null` or do not set to use the default value for the parameter. - - An exception is thrown if non-Unicode XML data is passed as a string. - - If the application specifies the database type, the bound value is converted to that type when the provider sends the data to the server. The provider tries to convert any type of value if it supports the interface. Conversion errors may result if the specified type is not compatible with the value. - - Both the and properties can be inferred by setting the Value. - - The property is overwritten by `SqlDataAdapter.UpdateCommand`. - - For information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - - - -## Examples - The following example creates a and sets some of its properties. - - [!code-csharp[SqlParameter#8](~/../sqlclient/doc/samples/SqlParameter.cs#8)] - - ]]> - - - - Gets the name of the database where the schema collection for this XML instance is located. - The name of the database where the schema collection for this XML instance is located. - - and are also null. - - ]]> - - - - Gets the name of the schema collection for this XML instance. - The name of the schema collection for this XML instance. - - and are also null. - - ]]> - - - - The owning relational schema where the schema collection for this XML instance is located. - The owning relational schema for this XML instance. - - and are also null. - - ]]> - - - + + + + + Represents a parameter to a and optionally its mapping to columns. This class cannot be inherited. For more information on parameters, see Configuring parameters + + + + Parameter names are not case-sensitive. + + + Nameless, also called ordinal, parameters are not supported by the .NET Framework Data Provider for SQL Server. + + + For more information, along with additional sample code demonstrating how to use parameters, see Commands and Parameters. + + + + + The following example creates multiple instances of through the collection within the . These parameters are used to select data from the data source and put the data in the . + + + This example assumes that a and a have already been created by using the appropriate schema, commands, and connection. For more information and additional examples on using parameters, see Retrieving and Modifying Data in ADO.NET and Configuring parameters. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet categoriesDataSet; + protected DataGrid dataGrid1; + protected SqlDataAdapter categoriesAdapter; + + public void AddSqlParameters() + { + // ... + // create categoriesDataSet and categoriesAdapter + // ... + + categoriesAdapter.SelectCommand.Parameters.Add( + "@CategoryName", + SqlDbType.VarChar, + 80 + ).Value = "toasters"; + categoriesAdapter.SelectCommand.Parameters.Add( + "@SerialNum", + SqlDbType.Int + ).Value = 239; + categoriesAdapter.Fill(categoriesDataSet); + } + } + + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter(); + parameter.ParameterName = "@Description"; + parameter.IsNullable = true; + parameter.SqlDbType = SqlDbType.VarChar; + parameter.Direction = ParameterDirection.Output; + parameter.Size = 88; + + command.Parameters.Add(parameter); + } + } + + + + + + The name of the parameter to map. + + + One of the values. + + + Initializes a new instance of the class that uses the parameter name and the data type. + + + The data type and, if appropriate, and are inferred from the value of the parameter. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command, string paramValue) + { + SqlParameter parameter = new SqlParameter("@Description", SqlDbType.VarChar); + parameter.IsNullable = true; + parameter.Direction = ParameterDirection.Output; + parameter.Size = 88; + parameter.Value = paramValue; + + command.Parameters.Add(parameter); + } + } + + + + The value supplied in the parameter is an invalid back-end data type. + + + + + The name of the parameter to map. + + + An that is the value of the . + + + Initializes a new instance of the class that uses the parameter name and a value of the new . + + + + When you specify an in the parameter, the is inferred from the Microsoft .NET Framework type of the . + + + Use caution when you use this overload of the constructor to specify integer parameter values. Because this overload takes a of type , you must convert the integral value to an type when the value is zero, as the following C# example demonstrates. + + + Parameter = new SqlParameter("@pname", (object)0); + + + If you do not perform this conversion, the compiler assumes that you are trying to call the constructor overload. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter( + "@Description", + SqlDbType.VarChar, + 88, + "Description"); + parameter.IsNullable = true; + parameter.Direction = ParameterDirection.Output; + + command.Parameters.Add(parameter); + } + } + + + + + + The name of the parameter to map. + + + One of the values. + + + The length of the parameter. + + + Initializes a new instance of the class that uses the parameter name, the , and the size. + + + The is inferred from the value of the parameter if it is not explicitly set in the parameter. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command, string paramValue) + { + SqlParameter parameter = new SqlParameter( + "@Description", + SqlDbType.VarChar, + 88); + parameter.IsNullable = true; + parameter.Direction = ParameterDirection.Output; + parameter.Value = paramValue; + + command.Parameters.Add(parameter); + } + } + + + + The value supplied in the parameter is an invalid back-end data type. + + + + + The name of the parameter to map. + + + One of the values. + + + The length of the parameter. + + + The name of the source column () if this is used in a call to >. + + + Initializes a new instance of the class that uses the parameter name, the , the size, and the source column name. + + + The is inferred from the value of the parameter if it is not explicitly set in the parameter. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter( + "@Description", + SqlDbType.VarChar, + 88, + "Description"); + parameter.IsNullable = true; + parameter.Direction = ParameterDirection.Output; + + command.Parameters.Add(parameter); + } + } + + + + The value supplied in the parameter is an invalid back-end data type. + + + + + The name of the parameter to map. + + + One of the values. + + + The length of the parameter. + + + One of the values. + + + if the value of the field can be null; otherwise, . + + + The total number of digits to the left and right of the decimal point to which is resolved. + + + The total number of decimal places to which is resolved. + + + The name of the source column () if this is used in a call to . + + + One of the values. + + + An that is the value of the . + + + Initializes a new instance of the class that uses the parameter name, the type of the parameter, the size of the parameter, a , the precision of the parameter, the scale of the parameter, the source column, a to use, and the value of the parameter. + + + The and are inferred from the value of the parameter if they are not explicitly set in the and parameters. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter( + "@Description", + SqlDbType.VarChar, + 11, + ParameterDirection.Input, + true, + 0, + 0, + "Description", + DataRowVersion.Current, + "garden hose"); + parameter.IsNullable = true; + + command.Parameters.Add(parameter); + } + } + + + + The value supplied in the parameter is an invalid back-end data type. + + + + + The name of the parameter to map. + + + One of the values. + + + The length of the parameter. + + + One of the values. + + + The total number of digits to the left and right of the decimal point to which is resolved. + + + The total number of decimal places to which is resolved. + + + The name of the source column ( ) if this is used in a call to >. + + + One of the values. + + + if the source column is nullable; if it is not. + + + An that is the value of the . + + + The name of the database where the schema collection for this XML instance is located. + + + The owning relational schema where the schema collection for this XML instance is located. + + + The name of the schema collection for this parameter. + + + Initializes a new instance of the class that uses the parameter name, the type of the parameter, the length of the parameter the direction, the precision, the scale, the name of the source column, one of the values, a Boolean for source column mapping, the value of the , the name of the database where the schema collection for this XML instance is located, the owning relational schema where the schema collection for this XML instance is located, and the name of the schema collection for this parameter. + + + The and are inferred from the value of the parameter if they are not explicitly set in the and parameters. + + + + + Gets or sets the object that defines how string comparisons should be performed for this parameter. + + + A object that defines string comparison for this parameter. + + + + + Gets or sets the of the parameter. + + + One of the values. The default is NVARCHAR. + + + + The and are linked. Therefore, setting the changes the to a supporting . + + + For a list of the supported data types, see the appropriate member. For more information, see DataAdapter Parameters. + + + + + The following example creates a and sets some of its properties. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command, string paramValue) + { + SqlParameter parameter = new SqlParameter( + "@Description", + SqlDbType.VarChar); + parameter.Value = paramValue; + parameter.IsNullable = true; + command.Parameters.Add(parameter); + } + + private static void SetParameterToNull(IDataParameter parameter) + { + if (parameter.IsNullable) + { + parameter.Value = DBNull.Value; + } + else + { + throw new ArgumentException("Parameter provided is not nullable", "parameter"); + } + } + } + + + + + + Gets or sets a value that indicates whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. + + + One of the values. The default is . + + + If the is output, and execution of the associated does not return a value, the contains a null value. , , and parameters returned by calling cannot be accessed until you close the . + + + + The following example creates a and sets some of its properties. + + + Commands and Parameters + DataAdapter Parameters + SQL Server and ADO.NET + + + + The property was not set to one of the valid values. + + + + + Enforces encryption of a parameter when using Always Encrypted. If SQL Server informs the driver that the parameter does not need to be encrypted, the query using the parameter will fail. This property provides additional protection against security attacks that involve a compromised SQL Server providing incorrect encryption metadata to the client, which may lead to data disclosure. + + + if the parameter has a force column encryption; otherwise, . + + + + + Gets or sets a value that indicates whether the parameter accepts null values. is not used to validate the parameter's value and will not prevent sending or receiving a null value when executing a command. + + + if null values are accepted; otherwise, . The default is . + + + Null values are handled using the class. + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterNullable() + { + SqlParameter parameter = new SqlParameter("Description", SqlDbType.VarChar, 88); + parameter.IsNullable = true; + parameter.Direction = ParameterDirection.Output; + } + + + + + + Gets or sets the locale identifier that determines conventions and language for a particular region. + + + The locale identifier associated with the parameter. + + + + The locale identifies conventions and language for a particular geographical region. The codepage used to encode a specific string (the character set) is based on the locale used by that string or the environment that produced it. This property sets (for input parameters) or gets (for output parameters) the locale to be attached to a string when exchanging data with the server. This property is typically used together with the property. + + + static void CreateSqlParameterLocaleId() + { + SqlParameter parameter = new SqlParameter("pName", SqlDbType.VarChar); + parameter.LocaleId = 1033; + // English - United States + } + + + + + + Gets or sets the offset to the property. + + + The offset to the . The default is 0. + + + The Offset property is used for client-side chunking of binary and string data. For example, in order to insert 10MB of text into a column on a server, a user might execute 10 parameterized inserts of 1MB chunks, shifting the value of Offset on each iteration by 1MB. Offset specifies the number of bytes for binary types, and the number of characters for strings. The count for strings does not include the terminating character. + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterOffset() + { + SqlParameter parameter = new SqlParameter("pDName", SqlDbType.VarChar); + parameter.IsNullable = true; + parameter.Offset = 3; + } + + + + + + Gets or sets the name of the . + + + The name of the . The default is an empty string. + + + The is specified in the form @paramname. You must set before executing a that relies on parameters. + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter(); + parameter.ParameterName = "@Description"; + parameter.IsNullable = true; + parameter.DbType = DbType.String; + parameter.Direction = ParameterDirection.Output; + + command.Parameters.Add(parameter); + } + } + + + + + + Gets or sets the maximum number of digits used to represent the property. + + + The maximum number of digits used to represent the property. The default value is 0. This indicates that the data provider sets the precision for . + + + + The Precision property is used by parameters that have a of Decimal. + + + You do not need to specify values for the Precision and properties for input parameters, as they can be inferred from the parameter value. Precision and are required for output parameters and for scenarios where you need to specify complete metadata for a parameter without indicating a value, such as specifying a null value with a specific precision and scale. + + + Use of this property to coerce data passed to the database is not supported. To round, truncate, or otherwise coerce data before passing it to the database, use the class that is part of the System namespace prior to assigning a value to the parameter's property. + + + Microsoft .NET Framework data providers that are included with the .NET Framework version 1.0 do not verify the Precision or of parameter values. This can cause truncated data being inserted at the data source. If you are using .NET Framework version 1.0, validate the Precision and of values before setting the parameter value. When you use .NET Framework version 1.1 or a later version, an exception is thrown if a parameter value is set with an invalid Precision. values that exceed the parameter scale are still truncated. + + + + + The following example creates a and sets some of its properties. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + private static void AddSqlParameter(SqlCommand command) + { + SqlParameter parameter = new SqlParameter("@Price", SqlDbType.Decimal); + parameter.Value = 3.1416; + parameter.Precision = 8; + parameter.Scale = 4; + + command.Parameters.Add(parameter); + } + } + + + + + + Resets the type associated with this . + + + When executing a command that includes parameter values, code can either set the type of parameter explicitly, or the parameter can infer its type from its value. Calling this method resets the parameter so that it can again infer its type from the value passed in the parameter. Calling this method affects both the and properties of the . + + + + + Resets the type associated with this . + + + When executing a command that includes parameter values, code can either set the type of parameter explicitly, or the parameter can infer its type from its value. Calling this method resets the parameter so that it can again infer its type from the value passed in the parameter. Calling this method affects both the and properties of the . + + + + + Gets or sets the number of decimal places to which is resolved. + + + The number of decimal places to which is resolved. The default is 0. + + + + The Scale property is used by parameters that have a of Decimal. + + + Data may be truncated if the Scale property is not explicitly specified and the data on the server does not fit in scale 0 (the default). + + + You do not need to specify values for the and Scale properties for input parameters, as they can be inferred from the parameter value. and Scale are required for output parameters and for scenarios where you need to specify complete metadata for a parameter without indicating a value, such as specifying a null value with a specific precision and scale. + + + Use of this property to coerce data passed to the database is not supported. To round, truncate, or otherwise coerce data before passing it to the database, use the class that is part of the System namespace prior to assigning a value to the parameter's property. + + + .NET Framework data providers that are included with the .NET Framework version 1.0 do not verify the or Scale of parameter values. This can cause truncated data to be inserted at the data source. If you are using .NET Framework version 1.0, validate the and of values before setting the parameter value. Scale values that exceed the parameter scale are still truncated. + + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterPrecisionScale() + { + SqlParameter parameter = new SqlParameter("Price", SqlDbType.Decimal); + parameter.Value = 3.1416; + parameter.Precision = 8; + parameter.Scale = 4; + } + + + + + + Gets or sets the maximum size, in bytes, of the data within the column. + + + The maximum size, in bytes, of the data within the column. The default value is inferred from the parameter value. + + + + Return values are not affected by this property; return parameters from stored procedures are always fixed-size integers. + + + For output parameters with a variable length type (nvarchar, for example), the size of the parameter defines the size of the buffer holding the output parameter. The output parameter can be truncated to a size specified with Size. For character types, the size specified with Size is in characters. + + + The Size property is used for binary and string types. For string type parameters, Size means length in Unicode characters. For parameters of type , Size is ignored. + + + For non-string data types and ANSI string data, the Size property refers to the number of bytes. For Unicode string data, Size refers to the number of characters. The count for strings does not include the terminating character. + + + For variable-length data types, Size describes the maximum amount of data to transmit to the server. For example, for a Unicode string value, Size could be used to limit the amount of data sent to the server to the first one hundred characters. + + + If not explicitly set, the size is inferred from the actual size of the specified parameter value. + + + If the fractional part of the parameter value is greater than the size, then the value will be truncated to match the size. + + + For fixed length data types, the value of Size is ignored. It can be retrieved for informational purposes, and returns the maximum amount of bytes the provider uses when transmitting the value of the parameter to the server. + + + For information about streaming, see SqlClient Streaming Support. + + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterSize() + { + string description = "12 foot scarf - multiple colors, one previous owner"; + SqlParameter parameter = new SqlParameter("Description", SqlDbType.VarChar); + parameter.Direction = ParameterDirection.InputOutput; + parameter.Size = description.Length; + parameter.Value = description; + } + + + + + + Gets or sets the name of the source column mapped to the and used for loading or returning the + + + The name of the source column mapped to the . The default is an empty string. + + + + When SourceColumn is set to anything other than an empty string, the value of the parameter is retrieved from the column with the SourceColumn name. If is set to , the value is taken from the . If is set to , the value is taken from the data source. A of is a combination of both. + + + For more information about how to use the SourceColumn property, see DataAdapter Parameters and Updating Data Sources with DataAdapters. + + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterSourceColumn() + { + SqlParameter parameter = new SqlParameter("Description", SqlDbType.VarChar, 88); + parameter.SourceColumn = "Description"; + } + + + + + + Sets or gets a value which indicates whether the source column is nullable. This allows to correctly generate Update statements for nullable columns. + + + if the source column is nullable; if it is not. + + + + SourceColumnNullMapping is used by the to correctly generate update commands when dealing with nullable columns. Generally, use of SourceColumnNullMapping is limited to developers inheriting from . uses this property to determine whether the source column is nullable, and sets this property to if it is nullable, and if it is not. When is generating its UPDATE statement, it examines the SourceColumnNullMapping for each parameter. If the property is , generates a WHERE clauses like the following (in this query expression, FieldName represents the name of the field): + + + ((@IsNull_FieldName = 1 AND FieldName IS NULL) OR + (FieldName = @Original_FieldName)) + + + If SourceColumnNullMapping for the field is , generates the following WHERE clause: + + + FieldName = @OriginalFieldName + + + In addition, @IsNull_FieldName contains 1 if the source field contains null, and 0 if it does not. This mechanism allows for a performance optimization in SQL Server, and provides for common code that works across multiple providers. + + + + + + Gets or sets the to use when you load + + + One of the values. The default is . + + + This property is used by the during an update to determine whether the original or current value is used for a parameter value. This lets primary keys be updated. This property is set to the version of the used by the property, or one of the methods of the object. + + + + The following example creates a and sets some of its properties. + + + static void CreateSqlParameterSourceVersion() + { + SqlParameter parameter = new SqlParameter("Description", SqlDbType.VarChar, 88); + parameter.SourceColumn = "Description"; + parameter.SourceVersion = DataRowVersion.Current; + } + + + + + + Gets or sets the of the parameter. + + + One of the values. The default is . + + + + The SqlDbType and are linked. Therefore, setting the changes the SqlDbType to a supporting . + + + For a list of the supported data types, see the appropriate member. For more information, see DataAdapter Parameters. + + + For information about streaming, see SqlClient Streaming Support. + + + + + + Gets or sets the value of the parameter as an SQL type. + + + An that is the value of the parameter, using SQL types. The default value is . + + + + For input parameters, the value is bound to the that is sent to the server. For output and return value parameters, the value is set on completion of the and after the is closed. + + + This property can be set to null or . Use to send a NULL value as the value of the parameter. Use null or do not set SqlValue to use the default value for the parameter. + + + If the application specifies the database type, the bound value is converted to that type when the provider sends the data to the server. The provider tries to convert any type of value if it supports the interface. Conversion errors may result if the specified type is not compatible with the value. + + + Both the and properties can be inferred by setting the . + + + The property is overwritten by . + + + Use the property to return parameter values as common language runtime (CLR) types. + + + For information about streaming, see SqlClient Streaming Support. + + + + + + For a description of this member, see . + + + A new that is a copy of this instance. + + + This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + + + + + Gets a string that contains the . + + + A string that contains the . + + + + + Gets or sets the type name for a table-valued parameter. + + + The type name of the specified table-valued parameter. + + + + + Gets or sets a that represents a user-defined type as a parameter. + + + A that represents the fully qualified name of a user-defined type in the database. + + + For a sample demonstrating UdtTypeName, see Retrieving UDT Data. + + + + + Gets or sets the value of the parameter. + + + An that is the value of the parameter. The default value is null. + + + + For input parameters, the value is bound to the that is sent to the server. For output and return value parameters, the value is set on completion of the and after the is closed. + + + This property can be set to or . Use to send a NULL value as the value of the parameter. Use or do not set Value to use the default value for the parameter. + + + An exception is thrown if non-Unicode XML data is passed as a string. + + + If the application specifies the database type, the bound value is converted to that type when the provider sends the data to the server. The provider tries to convert any type of value if it supports the interface. Conversion errors may result if the specified type is not compatible with the value. + + + Both the and properties can be inferred by setting Value. + + + The Value property is overwritten by . + + + For information about streaming, see SqlClient Streaming Support. + + + + + The following example creates a and sets some of its properties. + + + + static void CreateSqlParameterVersion() + { + SqlParameter parameter = new SqlParameter("Description", SqlDbType.VarChar, 88); + parameter.Value = "garden hose"; + } + + + + + + Gets the name of the database where the schema collection for this XML instance is located. + + + The name of the database where the schema collection for this XML instance is located. + + + This value is null (Nothing in Microsoft Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case and are also null. + + + + + Gets the name of the schema collection for this XML instance. + + + The name of the schema collection for this XML instance. + + + + This value is null (Nothing in Microsoft Visual Basic) if there is no associated schema collection. If the value is null, then and are also null. + + + + + + The owning relational schema where the schema collection for this XML instance is located. + + + The owning relational schema for this XML instance. + + + This value is null (Nothing in Microsoft Visual Basic) if the collection is defined within the current database. It is also null if there is no schema collection, in which case and are also null. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlParameterCollection.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlParameterCollection.xml index c75791c6bc..59853057da 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlParameterCollection.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlParameterCollection.xml @@ -1,366 +1,774 @@ - - - - - Represents a collection of parameters associated with a and their respective mappings to columns in a . This class cannot be inherited. - - through the collection. The parameters are used to select data within the data source and populate the . This code assumes that a and a have already been created with the appropriate schema, commands, and connection. - -[!code-csharp[SqlParameterCollection_Add6 Example#1](~/../sqlclient/doc/samples/SqlParameterCollection_Add6.cs#1)] - -]]> - - - - Adds a to the . - - - The to add to the collection. - Adds the specified object to the . - A new object. - - - - The specified in the parameter is already added to this or another . - The parameter passed was not a . - The parameter is null. - - - An . - Adds the specified object to the . - The index of the new object. - To be added. - - - The name of the parameter. - One of the values. - Adds a to the given the parameter name and the data type. - A new object. - - - - - - The name of the to add to the collection. - A . - Adds the specified object to the . - A new object. - -Use caution when you are using this overload of the method to specify integer parameter values. Because this overload takes a of type , you must convert the integral value to an type when the value is zero, as the following C# example demonstrates. - -``` -parameters.Add("@pname", Convert.ToInt32(0)); -``` - -If you do not perform this conversion, the compiler assumes that you are trying to call the (, ) overload. - - - - The specified in the parameter is already added to this or another . - The parameter is null. - - - The name of the parameter. - The of the to add to the collection. - The size as an . - Adds a to the , given the specified parameter name, and size. - A new object. - - - - - - The name of the parameter. - One of the values. - The column length. - The name of the source column () if this is used in a call to . - Adds a to the with the parameter name, the data type, and the column length. - A new object. - - - - - - Adds elements to the end of the . - - - The values to add. - Adds an array of values to the end of the . - To be added. - - - The values to add. - Adds an array of values to the end of the . - To be added. - - - The name of the parameter. - The value to be added. Use instead of null, to indicate a null value. - Adds a value to the end of the . - A object. - - replaces the `SqlParameterCollection.Add` method that takes a and an . The overload of `Add` that takes a string and an object was deprecated because of possible ambiguity with the `SqlParameterCollection.Add` overload that takes a and a enumeration value where passing an integer with the string could be interpreted as being either the parameter value or the corresponding value. Use whenever you want to add a parameter by specifying its name and value. - -For `Xml` enumeration values, you can use a string, an XML value, an derived type instance, or a object. - - - -## Examples -The following example demonstrates how to use the `AddWithValue` method. - -[!code-csharp[SqlParameterCollection_AddWithValue#1](~/../sqlclient/doc/samples/SqlParameterCollection_AddWithValue.cs#1)] - -]]> - - - - Removes all the objects from the . - To be added. - - - Determines whether the specified object is in this . - - - The value. - Determines whether the specified is in this . - - if the contains the value; otherwise, . - To be added. - - - The value. - Determines whether the specified is in this . - - if the contains the value; otherwise, . - To be added. - - - The value. - Determines whether the specified parameter name is in this . - - if the contains the value; otherwise, . - To be added. - - - Copies all the elements of the current to the specified object. - - - The one-dimensional that is the destination of the elements copied from the current . - A 32-bit integer that represents the index in the at which copying starts. - Copies all the elements of the current to the specified one-dimensional starting at the specified destination index. - To be added. - - - The that is the destination of the elements copied from the current . - A 32-bit integer that represents the index in the at which copying starts. - Copies all the elements of the current to the specified starting at the specified destination index. - To be added. - - - Returns an Integer that contains the number of elements in the . Read-only. - The number of elements in the as an Integer. - To be added. - - - Returns an enumerator that iterates through the . - An for the . - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - Gets the location of the specified within the collection. - - - The to find. - Gets the location of the specified within the collection. - The zero-based location of the specified that is a within the collection. Returns -1 when the object does not exist in the . - To be added. - - - The to find. - Gets the location of the specified within the collection. - The zero-based location of the specified that is a within the collection. Returns -1 when the object does not exist in the . - To be added. - - - The case-sensitive name of the to find. - Gets the location of the specified with the specified name. - The zero-based location of the specified with the specified case-sensitive name. Returns -1 when the object does not exist in the . - To be added. - - - Inserts a object into the . - - - The zero-based index at which value should be inserted. - A object to be inserted in the . - Inserts a object into the at the specified index. - To be added. - - - The zero-based index at which value should be inserted. - An to be inserted in the . - Inserts an into the at the specified index. - To be added. - - - Gets a value that indicates whether the has a fixed size. - - if the has a fixed size; otherwise, . - To be added. - - - Gets a value that indicates whether the is read-only. - - if the is read-only; otherwise, . - To be added. - - - Gets a value that indicates whether the is synchronized. - - if the is synchronized; otherwise, . - To be added. - - - Gets the with a specified attribute. - - - The zero-based index of the parameter to retrieve. - Gets the at the specified index. - The at the specified index. - - objects to supply an input parameter to a stored procedure that returns results in an output parameter. The code iterates through the items in the and displays some parameter properties in the console window. This example assumes a valid connection string to the **AdventureWorks** sample database on an instance of SQL Server. - -[!code-csharp[SqlParameterCollection_Count Example#1](~/../sqlclient/doc/samples/SqlParameterCollection_Count.cs#1)] - -]]> - - The specified index does not exist. - - - The name of the parameter to retrieve. - Gets the with the specified name. - The with the specified name. - - . If the `parameterName` is not valid, an will be thrown. - -]]> - - The specified is not valid. - - - Removes the specified from the collection. - - - A object to remove from the collection. - Removes the specified from the collection. - - object in a collection. If the parameter exists, the example removes it. This example assumes that a collection has already been created by a . - -[!code-csharp[SqlParameterCollection_Remove Example#1](~/../sqlclient/doc/samples/SqlParameterCollection_Remove.cs#1)] - -]]> - - The parameter is not a . - The parameter does not exist in the collection. - - - The object to remove from the collection. - Removes the specified from the collection. - To be added. - - - Removes the object from the at the specified index. - - - The zero-based index of the object to remove. - Removes the from the at the specified index. - To be added. - - - The name of the to remove. - Removes the from the at the specified parameter name. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - To be added. - To be added. - To be added. - To be added. - - - Gets an object that can be used to synchronize access to the . - An object that can be used to synchronize access to the . - To be added. - - + + + + + Represents a collection of parameters associated with a and their respective mappings to columns in a . This class cannot be inherited. + + + + If the command contains an ad hoc SQL statement, as opposed to a stored-procedure name, the number of the parameters in the collection must be equal to the number of parameter placeholders within the command text, or SQL Server raises an error. With a stored procedure, all the parameters declared in the stored procedure without a default value must be provided. Parameters declared with a default value are optional. This lets you specify a value other than the default. + + + For more information with additional sample code demonstrating how to use parameters, see Commands and Parameters. + + + + + The following example creates multiple instances of through the collection. The parameters are used to select data within the data source and populate the . This code assumes that a and a have already been created with the appropriate schema, commands, and connection. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet categoriesDataSet; + protected DataGrid dataGrid1; + protected SqlDataAdapter categoriesAdapter; + + + public void AddSqlParameters() + { + // ... + // create categoriesDataSet and categoriesAdapter + // ... + + categoriesAdapter.SelectCommand.Parameters.Add( + "@CategoryName", + SqlDbType.VarChar, + 80 + ).Value = "toasters"; + categoriesAdapter.SelectCommand.Parameters.Add( + "@SerialNum", + SqlDbType.Int + ).Value = 239; + categoriesAdapter.Fill(categoriesDataSet); + + } + } + + + + + Constructs and initializes a new instance of . + + + + The to add to the collection. + + + Adds the specified object to the . + + + A new object. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void AddSqlParameter(SqlCommand command) + { + command.Parameters.Add(new SqlParameter("Description", "Beverages")); + } + } + + + + The specified in the parameter is already added to this or another . + + + The parameter passed was not a . + + + The parameter is null. + + + + + An . + + + Adds the specified object to the . + + + The index of the new object. + + + + + The name of the parameter. + + + One of the values. + + + Adds a to the given the parameter name and the data type. + + + A new object. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void AddSqlParameter(SqlCommand command) + { + SqlParameter param = command.Parameters.Add( + "@Description", + SqlDbType.NVarChar); + param.Size = 16; + param.Value = "Beverages"; + } + } + + + + + + The name of the to add to the collection. + + + A . + + + Adds the specified object to the . + + + A new object. + + + + Use caution when you are using this overload to specify integer parameter values. Because this overload takes a of type , you must convert the integral value to an type when the value is zero, as the following C# example demonstrates. + + + parameters.Add("@pname", Convert.ToInt32(0)); + + + If you do not perform this conversion, the compiler assumes that you are trying to call the overload. + + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void AddSqlParameter(SqlCommand command) + { + SqlParameter param = new SqlParameter( + "@Description", + SqlDbType.NVarChar, + 16); + param.Value = "Beverages"; + command.Parameters.Add(param); + } + } + + + + The specified in the parameter is already added to this or another . + + + The parameter is null. + + + + + The name of the parameter. + + + The of the to add to the collection. + + + The size as an . + + + Adds a to the , given the specified parameter name, and size. + + + A new object. + + + This overload is useful when you are adding a parameter of a variable-length data type such as varchar or binary. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void AddSqlParameter(SqlCommand command) + { + SqlParameter param = new SqlParameter( + "@Description", + SqlDbType.NVarChar, + 16); + param.Value = "Beverages"; + command.Parameters.Add(param); + } + } + + + + + + The name of the parameter. + + + One of the values. + + + The column length. + + + The name of the source column () if this is used in a call to . + + + Adds a to the with the parameter name, the data type, and the column length. + + + A new object. + + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + public class Sample + { + public void AddSqlParameter(SqlCommand cmd) + { + SqlParameter p1 = cmd.Parameters.Add("@Description", SqlDbType.NVarChar, 16, "Description"); + } + } + + + + + + The values to add. + + + Adds an array of values to the end of the . + + + + + The values to add. + + + Adds an array of values to the end of the . + + + + + The name of the parameter. + + + The value to be added. Use instead of null, to indicate a null value. + + + Adds a value to the end of the . + + + A object. + + + + AddWithValue replaces the SqlParameterCollection.Add method that takes a and an . The overload of Add that takes a string and an object was deprecated because of possible ambiguity with the SqlParameterCollection.Add overload that takes a and a enumeration value where passing an integer with the string could be interpreted as being either the parameter value or the corresponding value. Use AddWithValue whenever you want to add a parameter by specifying its name and value. + + + For enumeration values, you can use a string, an XML value, an derived type instance, or a object. + + + + + The following example demonstrates how to use the AddWithValue method. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + string connectionString = GetConnectionString(); + string demo = @"<StoreSurvey xmlns=""http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey""><AnnualSales>1500000</AnnualSales><AnnualRevenue>150000</AnnualRevenue><BankName>Primary International</BankName><BusinessType>OS</BusinessType><YearOpened>1974</YearOpened><Specialty>Road</Specialty><SquareFeet>38000</SquareFeet><Brands>3</Brands><Internet>DSL</Internet><NumberEmployees>40</NumberEmployees></StoreSurvey>"; + Int32 id = 3; + UpdateDemographics(id, demo, connectionString); + Console.ReadLine(); + } + + private static void UpdateDemographics( + Int32 customerID, + string demoXml, + string connectionString) + { + // Update the demographics for a store, which is stored + // in an xml column. + string commandText = "UPDATE Sales.Store SET Demographics = @demographics " + + "WHERE CustomerID = @ID;"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + SqlCommand command = new SqlCommand(commandText, connection); + command.Parameters.Add("@ID", SqlDbType.Int); + command.Parameters["@ID"].Value = customerID; + + // Use AddWithValue to assign Demographics. + // SQL Server will implicitly convert strings into XML. + command.Parameters.AddWithValue("@demographics", demoXml); + + try + { + connection.Open(); + Int32 rowsAffected = command.ExecuteNonQuery(); + Console.WriteLine("RowsAffected: {0}", rowsAffected); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file. + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + + + Removes all the objects from the . + + + + + The value. + + + Determines whether the specified is in this . + + + if the contains the value; otherwise, . + + + + + The value. + + + Determines whether the specified is in this . + + + if the contains the value; otherwise, . + + + + + The value. + + + Determines whether the specified parameter name is in this . + + + if the contains the value; otherwise, . + + + + + The one-dimensional that is the destination of the elements copied from the current . + + + A 32-bit integer that represents the index in the at which copying starts. + + + Copies all the elements of the current to the specified one-dimensional starting at the specified destination index. + + + + + The that is the destination of the elements copied from the current . + + + A 32-bit integer that represents the index in the at which copying starts. + + + Copies all the elements of the current to the specified starting at the specified destination index. + + + + + Returns an Integer that contains the number of elements in the . Read-only. + + + The number of elements in the as an Integer. + + + + + Returns an enumerator that iterates through the . + + + An for the . + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + The to find. + + + Gets the location of the specified within the collection. + + + The zero-based location of the specified that is a within the collection. Returns -1 when the object does not exist in the . + + + + + The to find. + + + Gets the location of the specified within the collection. + + + The zero-based location of the specified that is a within the collection. Returns -1 when the object does not exist in the . + + + + + The case-sensitive name of the to find. + + + Gets the location of the specified with the specified name. + + + The zero-based location of the specified with the specified case-sensitive name. Returns -1 when the object does not exist in the . + + + + + The zero-based index at which value should be inserted. + + + A object to be inserted in the . + + + Inserts a object into the at the specified index. + + + + + The zero-based index at which value should be inserted. + + + An to be inserted in the . + + + Inserts an into the at the specified index. + + + + + Gets a value that indicates whether the has a fixed size. + + + if the has a fixed size; otherwise, . + + + + + Gets a value that indicates whether the is read-only. + + + if the is read-only; otherwise, . + + + + + Gets a value that indicates whether the is synchronized. + + + if the is synchronized; otherwise, . + + + + + The zero-based index of the parameter to retrieve. + + + Gets the at the specified index. + + + The at the specified index. + + + + The following example demonstrates creating objects to supply an input parameter to a stored procedure that returns results in an output parameter. The code iterates through the items in the and displays some parameter properties in the console window. This example assumes a valid connection string to the AdventureWorks sample database on an instance of SQL Server. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + class Program + { + static void Main() + { + // Supply any valid Document ID value. + // The value 7 is supplied for demonstration purposes. + string summaryString = CreateSqlParameters(7); + Console.ReadLine(); + } + + static private string CreateSqlParameters(int documentID) + { + // Assumes GetConnectionString returns a valid connection string to the + // AdventureWorks sample database on an instance of SQL Server 2005. + using (SqlConnection connection = new SqlConnection(GetConnectionString())) + { + connection.Open(); + SqlCommand command = connection.CreateCommand(); + try + { + // Setup the command to execute the stored procedure. + command.CommandText = "GetDocumentSummary"; + command.CommandType = CommandType.StoredProcedure; + + // Create the input parameter for the DocumentID. + SqlParameter paramID = new SqlParameter("@DocumentID", SqlDbType.Int); + paramID.Value = documentID; + command.Parameters.Add(paramID); + + // Create the output parameter to retrieve the summary. + SqlParameter paramSummary = new SqlParameter("@DocumentSummary", SqlDbType.NVarChar, -1); + paramSummary.Direction = ParameterDirection.Output; + command.Parameters.Add(paramSummary); + + // List the parameters and some of properties. + SqlParameterCollection paramCollection = command.Parameters; + string parameterList = ""; + for (int i = 0; i < paramCollection.Count; i++) + { + parameterList += String.Format(" {0}, {1}, {2}\n", + paramCollection[i], paramCollection[i].DbType, + paramCollection[i].Direction); + } + Console.WriteLine("Parameter Collection:\n" + parameterList); + + // Execute the stored procedure; retrieve + // and display the output parameter value. + command.ExecuteNonQuery(); + Console.WriteLine((String)(paramSummary.Value)); + return (String)(paramSummary.Value); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + return null; + } + } + } + + static private string GetConnectionString() + { + // To avoid storing the connection string in your code, + // you can retrieve it from a configuration file, using the + // System.Configuration.ConfigurationSettings.AppSettings property + return "Data Source=(local);Initial Catalog=AdventureWorks;" + + "Integrated Security=SSPI"; + } + } + + + + The specified index does not exist. + + + + + The name of the parameter to retrieve. + + + Gets the with the specified name. + + + The with the specified name. + + + The is used to look up the index value in the underlying . If the is not valid, an will be thrown. + + + The specified is not valid. + + + + + A object to remove from the collection. + + + Removes the specified from the collection. + + + + The following example searches for a object in a collection. If the parameter exists, the example removes it. This example assumes that a collection has already been created by a . + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + protected DataSet DataSet1; + protected DataGrid dataGrid1; + protected SqlCommand command; + protected SqlParameter param; + + public void SearchSqlParams() + { + // ... + // create SqlCommand command and SqlParameter param + // ... + if (command.Parameters.Contains(param)) + { + command.Parameters.Remove(param); + } + } + } + + + + The parameter is not a . + + + The parameter does not exist in the collection. + + + + + The object to remove from the collection. + + + Removes the specified from the collection. + + + + + The zero-based index of the object to remove. + + + Removes the from the at the specified index. + + + + + The name of the to remove. + + + Removes the from the at the specified parameter name. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + To be added. + + + To be added. + + + To be added. + + + To be added. + + + + + Gets an object that can be used to synchronize access to the . + + + An object that can be used to synchronize access to the . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryIntervalBaseEnumerator.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryIntervalBaseEnumerator.xml index 8856f2fe22..3c09bec921 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryIntervalBaseEnumerator.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryIntervalBaseEnumerator.xml @@ -1,55 +1,102 @@ - - - - - Generates a sequence of time intervals. - - - Initializes a new instance of the class with a default value of zero for the gap time, minimum, and maximum interval time. - - - The gap time used to calculate the time delay before each attempt. - The maximum time allowed as a gap time. - The minimum time allowed as a gap time. - Initializes a new instance of the class. - The supplied arguments failed validation. - - - The default gap time of each interval. - - - The minimum allowed time interval value. - - - The maximum allowed time interval value. - - - Gets the element in the collection at the current position of the enumerator. - - - Sets the enumerator to its initial position, which is before the first element in the collection. - - - The gap time of each interval. Must be between 0 and 120 seconds. - Maximum time interval value. Must be between 0 and 120 seconds. - Minimum time interval value. Must be less than maximum time interval and between 0 and 120 seconds. - Validate the enumeration parameters. - The supplied arguments failed validation. - - - Calculates the next interval time. - Returns the next gap time interval. - - - Advances the enumerator to the next element of the collection. - Returns , if the enumerator was successfully advanced to the next element; if the enumerator has passed the end of the collection. - - - Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - - - Creates a new object that is a copy of the current instance. - A new object that is a copy of this instance. - - + + + + + Generates a sequence of time intervals. + + + + + Initializes a new instance of the class with a default value of zero for the gap time, minimum, and maximum interval time. + + + + + The gap time used to calculate the time delay before each attempt. + + + The maximum time allowed as a gap time. + + + The minimum time allowed as a gap time. + + + Initializes a new instance of the class. + + + The supplied arguments failed validation. + + + + + The default gap time of each interval. + + + + + The minimum allowed time interval value. + + + + + The maximum allowed time interval value. + + + + + Gets the element in the collection at the current position of the enumerator. + + + + + Sets the enumerator to its initial position, which is before the first element in the collection. + + + + + The gap time of each interval. Must be between 0 and 120 seconds. + + + Maximum time interval value. Must be between 0 and 120 seconds. + + + Minimum time interval value. Must be less than maximum time interval and between 0 and 120 seconds. + + + Validate the enumeration parameters. + + + The supplied arguments failed validation. + + + + + Calculates the next interval time. + + + Returns the next gap time interval. + + + + + Advances the enumerator to the next element of the collection. + + + Returns , if the enumerator was successfully advanced to the next element; if the enumerator has passed the end of the collection. + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Creates a new object that is a copy of the current instance. + + + A new object that is a copy of this instance. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBase.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBase.xml index 3766fa205e..3557cb287e 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBase.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBase.xml @@ -1,57 +1,87 @@ - - - - - Retrieves the next time interval with respect to the number of retries if a transient condition occurs. - - - Maximum number of retries. - - that returns the maximum number of retry execution attempts that will be attempted after the first failure. - - - Current retry number starting from zero. - - that returns the number of retry execution attempts after the first failure. - - - The timer interval enumerator. - - value that indicates an enumerator to generate a sequence of time intervals. - - - Delegate to a transient condition predicate. The function that this delegate points to must return a true value when an expected transient exception happens. - - value that delegates to a function that receives a input parameter. - - - The sender object. - Pre-retry validation for the sender state. - Returns if the sender is authorized to retry the operation. - - [IMPORTANT!] -> Operations that are part of a **Transaction** are not safe to retry without specific knowledge of business logic. Due to this complexity, retry logic should be managed at the application level. - -> [!NOTE] -> The `RetryCondition` is an extra condition that checks before executing the `TransientPredicate` and the default condition always returns **true**. - -]]> - - - - The interval time that is generated by the `RetryIntervalEnumerator`. - Try to get the next interval time by using the enumerator if the counter does not exceed the number of retries. - Returns if the number of retry attempts has not been exceeded; otherwise . - - - Set the counters and enumerator to default values for next use. - - - Creates a new object that is a copy of the current instance. - When implemented in a derived class, the method is expected to return a new object of the current instance. The default implementation throws NotImplementedException. - In all cases. - - + + + + + Retrieves the next time interval with respect to the number of retries if a transient condition occurs. + + + + + Maximum number of retries. + + + that returns the maximum number of retry execution attempts that will be attempted after the first failure. + + + + + Current retry number starting from zero. + + + that returns the number of retry execution attempts after the first failure. + + + + + The timer interval enumerator. + + + value that indicates an enumerator to generate a sequence of time intervals. + + + + + Delegate to a transient condition predicate. The function that this delegate points to must return a true value when an expected transient exception happens. + + + value that delegates to a function that receives a input parameter. + + + + + The sender object. + + + Pre-retry validation for the sender state. + + + Returns if the sender is authorized to retry the operation. + + + + Operations that are part of a Transaction are not safe to retry without specific knowledge of business logic. Due to this complexity, retry logic should be managed at the application level. + + + The RetryCondition is an extra condition that checks before executing the and the default condition always returns . + + + + + + The interval time that is generated by the . + + + Try to get the next interval time by using the enumerator if the counter does not exceed the number of retries. + + + Returns if the number of retry attempts has not been exceeded; otherwise . + + + + + Set the counters and enumerator to default values for next use. + + + + + Creates a new object that is a copy of the current instance. + + + When implemented in a derived class, the method is expected to return a new object of the current instance. The default implementation throws . + + + In all cases. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBaseProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBaseProvider.xml index 031c2b1ff7..72bd0d7ced 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBaseProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicBaseProvider.xml @@ -1,90 +1,136 @@ - - - - - Applies retry logic on an operation through the `Execute` or `ExecuteAsync` function. - - - Occurs before applying the calculated delay time and executing the function on a next attempt. - - with event argument of object can be subscribed. - - [IMPORTANT!] -> Don't block execution with a time consuming action when an event occurs. For instance, if you log data to a file, run it in a new thread to avoid blocking the main execution thread. - -]]> - - - - - Defines the retry logic used to decide when to retry based on the encountered exception. - - [!NOTE] -> The `RetryLogic` property is assigned at `SqlRetryLogicBaseProvider` creation and its value is used as a template internally. Don't use it to monitor the status of the retry logic during and after execution. Instead, use the event to collect data about retry executions. - -]]> - - - - - The object that the `function` returns when executed. - The source of the event. - The operation to re-execute if a transient condition occurs. - Executes a function and applies retry logic, if enabled. **Note:** Exceptions will be reported via an aggregate exception if the execution isn't successful via retry attempts. - - The return value of the `function` if it runs without exception. - - [!NOTE] -> The type of exception depends on the `function`'s internal implementation. But if the exception is due to all retry attempts failing, it will be an that consists of all exceptions that happened during the failed attempts. - -]]> - - - The `function` parameter can't be `null`. - The collection of exceptions after all retry attempts have failed. - - - The object that the `function` returns in a Task when executed. - The source of the event. - The operation to re-execute if a transient condition occurs. - The cancellation instruction. - Executes a function and applies retry logic, if enabled. The cancellation token can be used to request that the operation be abandoned before the execution attempts are exceeded. **Note:** Exceptions will be reported via the returned Task object, which will contain an aggregate exception if execution fails for all retry attempts. - A task representing the asynchronous operation. The results of the task will be the return value of the `function`, if it runs without exception. - - [!NOTE] -> If the exception comes from all retry attempts failing, it will be an that consists of all exceptions from the failed attempts. - -]]> - - - The `function` parameter can't be `null`. - The collection of exceptions after failed retry attempts. - - - The source of the event. - The operation to re-execute if a transient condition occurs. - The cancellation instruction. - Executes a function and applies retry logic, if enabled. The cancellation token can be used to request that the operation be abandoned before the execution attempts are exceeded. **Note:** Exceptions will be reported via the returned Task object, which will contain an aggregate exception if execution fails for all retry attempts. - A Task or an exception. - - [!NOTE] -> If the exception comes from all retry attempts failing, it will be an that consists of all exceptions from the failed attempts. - -]]> - - - The `function` parameter can't be `null`. - The collection of exceptions after failed retry attempts. - - + + + + + Applies retry logic on an operation through the or function. + + + + + Occurs before applying the calculated delay time and executing the function on a next attempt. + + + with event argument of object can be subscribed. + + + + Don't block execution with a time-consuming action when an event occurs. For instance, if you log data to a file, run it in a new thread to avoid blocking the main execution thread. + + + + + + Defines the retry logic used to decide when to retry based on the encountered exception. + + + + The RetryLogic property is assigned at construction of the creation and its value is used as a template internally. Don't use it to monitor the status of the retry logic during and after execution. Instead, use the event to collect data about retry executions. + + + + + + The object that the `function` returns when executed. + + + The source of the event. + + + The operation to re-execute if a transient condition occurs. + + + + Executes a function and applies retry logic, if enabled. + + + Exceptions will be reported via an aggregate exception if the execution isn't successful via retry attempts. + + + + The return value of the if it runs without exception. + + + + + The type of exception depends on the 's internal implementation. But if the exception is due to all retry attempts failing, it will be an that consists of all exceptions that happened during the failed attempts. + + + + + The parameter can't be . + + + The collection of exceptions after all retry attempts have failed. + + + + + The object that the returns in a Task when executed. + + + The source of the event. + + + The operation to re-execute if a transient condition occurs. + + + The cancellation instruction. + + + + Executes a function and applies retry logic, if enabled. The cancellation token can be used to request that the operation be abandoned before the execution attempts are exceeded. + + + Exceptions will be reported via the returned Task object, which will contain an aggregate exception if execution fails for all retry attempts. + + + + A task representing the asynchronous operation. The results of the task will be the return value of the , if it runs without exception. + + + + If the exception comes from all retry attempts failing, it will be an that consists of all exceptions from the failed attempts. + + + + The parameter can't be . + + + The collection of exceptions after failed retry attempts. + + + + + The source of the event. + + + The operation to re-execute if a transient condition occurs. + + + The cancellation instruction. + + + + Executes a function and applies retry logic, if enabled. The cancellation token can be used to request that the operation be abandoned before the execution attempts are exceeded. + + + Exceptions will be reported via the returned Task object, which will contain an aggregate exception if execution fails for all retry attempts. + + + + A Task or an exception. + + + + If the exception comes from all retry attempts failing, it will be an that consists of all exceptions from the failed attempts. + + + + The parameter can't be . + + + The collection of exceptions after failed retry attempts. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicOption.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicOption.xml index 8ba200753b..4c5f1d6de6 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicOption.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryLogicOption.xml @@ -1,47 +1,88 @@ - - - - - Provides the retry logic parameters to create an instance of the class by using methods. - - - object that is configured to apply retry logic for the error number **102** for a maximum of **5** times and **3** to **60** seconds gap time between each run. It will only work for the `Select` SQL statements assigned to the . - -[!code-csharp[SqlConfigurableRetryLogic_SqlRetryLogicOptions#1](~/../sqlclient/doc/samples/SqlConfigurableRetryLogic_SqlRetryLogicOptions.cs#1)] - -]]> - - - Sets the number of times to try and execute the function. - - between 1 and 60; 1 means to execute one time and if an error is encountered, don't retry. - - - Sets the gap time interval as a object. - - The upcoming gap time before the next execution attempt; must be between 0 and 120 seconds. - - - Sets the minimum allowed gap time interval as a object. - - The minimum upcoming gap time before the next execution attempt; the default value is **zero** and must be between 0 and 120 seconds. - - - Sets the allowed maximum gap time interval as a object. - - The maximum upcoming gap time interval before the next execution attempt; must be between 0 and 120 seconds. - - - Sets the list of transient error numbers on which to retry when they occur. - List of ; Set to to use the internal list of exceptions from the object. - - - Sets a pre-retry validation function on the to only include specific SQL statements. - - The pre-retry validation delegate function; if the `CommandText` is authorized to retry the operation. - - + + + + + Provides the retry logic parameters to create an instance of the class by using methods. + + + + The following sample declares a object that is configured to apply retry logic for the error number 102 for a maximum of 5 times and 3 to 60 seconds gap time between each run. It will only work for the SELECT SQL statements assigned to the . + + + + using System; + using System.Text.RegularExpressions; + using Microsoft.Data.SqlClient; + + class RetryLogicSample + { + static void Main(string[] args) + { + var RetryLogicOption = new SqlRetryLogicOption() + { + NumberOfTries = 5, + // Declare the error number 102 as a transient error to apply the retry logic when it occurs. + TransientErrors = new int[] { 102 }, + // When a SqlCommand executes out of a transaction, + // the retry logic will apply if it contains a 'select' keyword. + AuthorizedSqlCondition = x => string.IsNullOrEmpty(x) + || Regex.IsMatch(x, @"\b(SELECT)\b", RegexOptions.IgnoreCase), + DeltaTime = TimeSpan.FromSeconds(1), + MaxTimeInterval = TimeSpan.FromSeconds(60), + MinTimeInterval = TimeSpan.FromSeconds(3) + }; + } + } + + + + + + Sets the number of times to try and execute the function. + + + between 1 and 60; 1 means to execute one time and if an error is encountered, don't retry. + + + + + Sets the gap time interval as a object. + + + The upcoming gap time before the next execution attempt; must be between 0 and 120 seconds. + + + + + Sets the minimum allowed gap time interval as a object. + + + The minimum upcoming gap time before the next execution attempt; the default value is zero and must be between 0 and 120 seconds. + + + + + Sets the allowed maximum gap time interval as a object. + + + The maximum upcoming gap time interval before the next execution attempt; must be between 0 and 120 seconds. + + + + + Sets the list of transient error numbers on which to retry when they occur. + + + List of ; Set to to use the internal list of exceptions from the object. + + + + + Sets a pre-retry validation function on the to only include specific SQL statements. + + + The pre-retry validation delegate function; if the is authorized to retry the operation. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryingEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryingEventArgs.xml index f7911a4160..eddcf0a718 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRetryingEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRetryingEventArgs.xml @@ -1,32 +1,52 @@ - - - - - Represents the set of arguments passed to the event. - - - The current retry attempt count. - The delay that indicates how long the current thread will be suspended before the next iteration is invoked. - The list of exceptions since the first retry that caused the retry logic to re-execute the function. - Initializes a new instance of the class. - - - Retry-attempt-number, after the first exception occurrence. - - that returns the number of retry execution attempts; starting from 1. - - - Gets or sets a value that indicates whether the retry logic should be canceled. - If set to , the execution attempt will be interrupted immediately. - - - Gets the current waiting time as a object. - - The upcoming gap time before the next execution attempt. - - - Gets the list of exceptions since the first attempt failure. - List of occurred exceptions. - - + + + + + Represents the set of arguments passed to the event. + + + + + The current retry attempt count. + + + The delay that indicates how long the current thread will be suspended before the next iteration is invoked. + + + The list of exceptions since the first retry that caused the retry logic to re-execute the function. + + + Initializes a new instance of the class. + + + + + Retry-attempt-number, after the first exception occurrence. + + + that returns the number of retry execution attempts; starting from 1. + + + + Gets or sets a value that indicates whether the retry logic should be canceled. + + + If set to , the execution attempt will be interrupted immediately. + + + + + Gets the current waiting time as a object. + + The upcoming gap time before the next execution attempt. + + + + Gets the list of exceptions since the first attempt failure. + + + List of occurred exceptions. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventArgs.xml index c71d543248..f0d95737a1 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventArgs.xml @@ -1,60 +1,146 @@ - - - - - Provides data for the event. - - event is raised when an to a row is completed. - - When using , there are two events that occur for each data row updated. The order of execution is as follows: - -1. The values in the are moved to the parameter values. - -2. The event is raised. - -3. The command executes. - -4. If the command is set to `FirstReturnedRecord`, and the first returned result is placed in the . - -5. If there are output parameters, they are placed in the . - -6. The event is raised. - -7. is called. - - - -## Examples - The following example shows how to use both the and events. - - The event returns this output: - - Event Arguments: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) - - The event returns this output: - - Event Arguments: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) - - [!code-csharp[SqlDataAdapter_RowUpdated Example#1](~/../sqlclient/doc/samples/SqlDataAdapter_RowUpdated.cs#1)] - - ]]> - - - - The sent through an . - The executed when is called. - One of the values that specifies the type of query executed. - The sent through an . - Initializes a new instance of the class. - To be added. - - - Gets or sets the executed when is called. - The executed when is called. - To be added. - - + + + + + Provides data for the event. + + + + The event is raised when an to a row is completed. + + + When using , there are two events that occur for each data row updated. The order of execution is as follows: + + + The values in the are moved to the parameter values. + The event is raised. + The command executes. + If the command is set to FirstReturnedRecord, and the first returned result is placed in the . + If there are output parameters, they are placed in the . + The event is raised. + is called. + + + + + The following example shows how to use both the and events. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + private DataSet DataSet1; + private DataGrid dataGrid1; + + // handler for RowUpdating event + private static void OnRowUpdating(object sender, SqlRowUpdatingEventArgs e) + { + PrintEventArgs(e); + } + + // handler for RowUpdated event + private static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) + { + PrintEventArgs(e); + } + + public static int Main() + { + const string connectionString = + "Integrated Security=SSPI;database=Northwind;server=MSSQL1"; + const string queryString = "SELECT * FROMProducts"; + + // create DataAdapter + SqlDataAdapter adapter = new SqlDataAdapter(queryString, connectionString); + SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + + // Create and fill DataSet (select only first 5 rows) + DataSet dataSet = new DataSet(); + adapter.Fill(dataSet, 0, 5, "Table"); + + // Modify DataSet + DataTable table = dataSet.Tables["Table"]; + table.Rows[0][1] = "new product"; + + // add handlers + adapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); + + // update, this operation fires two events + // (RowUpdating/RowUpdated) per changed row + adapter.Update(dataSet, "Table"); + + // remove handlers + adapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating); + adapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated); + return 0; + } + + private static void PrintEventArgs(SqlRowUpdatingEventArgs args) + { + Console.WriteLine("OnRowUpdating"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " status=" + args.Status + ")"); + } + + private static void PrintEventArgs(SqlRowUpdatedEventArgs args) + { + Console.WriteLine("OnRowUpdated"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " recordsAffected=" + args.RecordsAffected + + " status=" + args.Status + ")"); + } + } + + + The event returns this output: + + + Event Arguments: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 status=0) + + + The event returns this output: + + + Event Arguments: (command=Microsoft.Data.SqlClient.SqlCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) + + + + + + The sent through an . + + + The executed when is called. + + + One of the values that specifies the type of query executed. + + + The sent through an . + + + Initializes a new instance of the class. + + + + + Gets or sets the executed when is called. + + + The executed when is called. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventHandler.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventHandler.xml index 1dab5604a5..ac66308043 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventHandler.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatedEventHandler.xml @@ -1,20 +1,23 @@ - - - - - The source of the event. - The that contains the event data. - Represents the method that will handle the event of a . - - delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see [Handling and Raising Events](/dotnet/standard/events/). - - ]]> - - - + + + + + The source of the event. + + + The that contains the event data. + + + Represents the method that will handle the event of a . + + + + The handler is not required to perform any action, and your code should avoid generating exceptions or allowing exceptions to propagate to the calling method. Any exceptions that do reach the caller are ignored. + + + When you create a delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see Handling and Raising Events. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventArgs.xml index a8d644fa08..e1a9ffe8e5 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventArgs.xml @@ -1,65 +1,155 @@ - - - - - Provides data for the event. - - event is raised before an to a row. - - When you are using , there are two events that occur for each data row updated. The order of execution is as follows: - -1. The values in the are moved to the parameter values. - -2. The event is raised. - -3. The command executes. - -4. If the command is set to `FirstReturnedRecord`, and the first returned result is placed in the . - -5. If there are output parameters, they are placed in the . - -6. The event is raised. - -7. is called. - - - -## Examples - The following example shows how to use both the and events. - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SQLCommand commandType=2 status=0) - - The event returns this output: - - event args: (command=Microsoft.Data.SqlClient.SQLCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) - - [!code-csharp[SqlRowUpdatingEventArgs Example#1](~/../sqlclient/doc/samples/SqlRowUpdatingEventArgs.cs#1)] - - ]]> - - - - The to . - The to execute during . - One of the values that specifies the type of query executed. - The sent through an . - Initializes a new instance of the class. - To be added. - - - To be added. - To be added. - To be added. - - - Gets or sets the to execute when performing the . - The to execute when performing the . - To be added. - - + + + + + Provides data for the event. + + + + The event is raised before an to a row. + + + When you are using , there are two events that occur for each data row updated. The order of execution is as follows: + + + The values in the are moved to the parameter values. + The event is raised. + The command executes. + If the command is set to FirstReturnedRecord, and the first returned result is placed in the . + If there are output parameters, they are placed in the . + The event is raised. + is called. + + + + + The following example shows how to use both the and events. + + + + using System; + using System.Data; + using System.Data.Common; + using System.Windows.Forms; + using System.Xml; + using Microsoft.Data.SqlClient; + + public class Form1 : Form + { + private DataSet DataSet1; + private DataGrid dataGrid1; + + + // handler for RowUpdating event + private static void OnRowUpdating(object sender, SqlRowUpdatingEventArgs e) + { + PrintEventArgs(e); + } + + //Handler for RowUpdated event. + private static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) + { + PrintEventArgs(e); + } + + public static int Main() + { + const string CONNECTION_STRING = "Persist Security Info=False;Integrated Security=SSPI;database=northwind;server=mySQLServer"; + const string SELECT_ALL = "select * from Products"; + + //Create DataAdapter. + SqlDataAdapter rAdapter = new SqlDataAdapter(SELECT_ALL, CONNECTION_STRING); + + //Create and fill DataSet (Select only first 5 rows.). + DataSet rDataSet = new DataSet(); + rAdapter.Fill(rDataSet, 0, 5, "Table"); + + //Modify DataSet. + DataTable rTable = rDataSet.Tables["Table"]; + rTable.Rows[0][1] = "new product"; + + //Add handlers. + rAdapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating); + rAdapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); + + //Update--this operation fires two events (RowUpdating and RowUpdated) for each changed row. + rAdapter.Update(rDataSet, "Table"); + + //Remove handlers. + rAdapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating); + rAdapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated); + return 0; + } + + private static void PrintEventArgs(SqlRowUpdatingEventArgs args) + { + Console.WriteLine("OnRowUpdating"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " status=" + args.Status + ")"); + } + + private static void PrintEventArgs(SqlRowUpdatedEventArgs args) + { + Console.WriteLine("OnRowUpdated"); + Console.WriteLine(" event args: (" + + " command=" + args.Command + + " commandType=" + args.StatementType + + " recordsAffected=" + args.RecordsAffected + + " status=" + args.Status + ")"); + } + } + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SQLCommand commandType=2 status=0) + + + The event returns this output: + + + event args: (command=Microsoft.Data.SqlClient.SQLCommand commandType=2 recordsAffected=1 row=System.Data.DataRow[37] status=0) + + + + + + The to . + + + The to execute during . + + + One of the values that specifies the type of query executed. + + + The sent through an . + + + Initializes a new instance of the class. + + + + + To be added. + + + To be added. + + + To be added. + + + + + Gets or sets the to execute when performing the . + + + The to execute when performing the . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventHandler.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventHandler.xml index 9abc365553..e861f4c855 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventHandler.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowUpdatingEventHandler.xml @@ -1,22 +1,26 @@ - - - - - The source of the event. - The that contains the event data. - Represents the method that will handle the event of a . - - to influence the processing of the updates. For example, the handler may opt to skip the update of the current row or skip the update of all remaining rows. Note that the rows are updated in the order that they were received from the data source. - - When you create a delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see [Handling and Raising Events](/dotnet/standard/events/). - - ]]> - - - + + + + + The source of the event. + + + The that contains the event data. + + + Represents the method that will handle the event of a . + + + + The handler is not required to perform any action, and your code should avoid generating exceptions or allowing exceptions to propagate to the calling method. Any exceptions that do reach the caller are ignored. + + + The handler may use the to influence the processing of the updates. For example, the handler may opt to skip the update of the current row or skip the update of all remaining rows. Note that the rows are updated in the order that they were received from the data source. + + + When you create a delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. For more information about event handler delegates, see Handling and Raising Events. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventArgs.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventArgs.xml index d655582980..07cd09770c 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventArgs.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventArgs.xml @@ -1,51 +1,48 @@ - - - - - Represents the set of arguments passed to the . - To be added. - - - An that indicates the number of rows copied during the current bulk copy operation. - Creates a new instance of the object. - - - - - - Gets or sets a value that indicates whether the bulk copy operation should be aborted. - - if the bulk copy operation should be aborted; otherwise . - - property to cancel a bulk copy operation. Set to `true` to abort the bulk copy operation. - - If you call the **Close** method from , an exception is generated, and the object state does not change. - - If an application specifically creates a object in the constructor, the transaction is not rolled back. The application is responsible for determining whether it is required to rollback the operation, and if so, it must call the method. If the application does not create a transaction, the internal transaction corresponding to the current batch is automatically rolled back. However, changes related to previous batches within the bulk copy operation are retained, because the transactions for them already have been committed. - - ]]> - - - - Gets a value that returns the number of rows copied during the current bulk copy operation. - - that returns the number of rows copied. - - property is reset on each call to any of the `SqlBulkCopy.WriteToServer` methods. - - ]]> - - - + + + + + Represents the set of arguments passed to the . + + + + + An that indicates the number of rows copied during the current bulk copy operation. + + + Creates a new instance of the object. + + + The value in the parameter is reset on each call to any one of the methods. + + + + + Gets or sets a value that indicates whether the bulk copy operation should be aborted. + + if the bulk copy operation should be aborted; otherwise . + + + Use the Abort property to cancel a bulk copy operation. Set Abort to to abort the bulk copy operation. + + + If you call the method from , an exception is generated, and the object state does not change. + + + If an application specifically creates a object in the constructor, the transaction is not rolled back. The application is responsible for determining whether it is required to roll back the operation, and if so, it must call the method. If the application does not create a transaction, the internal transaction corresponding to the current batch is automatically rolled back. However, changes related to previous batches within the bulk copy operation are retained, because the transactions for them already have been committed. + + + + + + Gets a value that returns the number of rows copied during the current bulk copy operation. + + + that returns the number of rows copied. + + + The value in the property is reset on each call to any of the methods. + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventHandler.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventHandler.xml index 325fcf10f1..3ed80e6cc3 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventHandler.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlRowsCopiedEventHandler.xml @@ -1,11 +1,15 @@ - - - - - The source of the event. - A object that contains the event data. - Represents the method that handles the event of a . - To be added. - - + + + + + The source of the event. + + + A object that contains the event data. + + + Represents the method that handles the event of a . + + + diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlTransaction.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlTransaction.xml index 56908b095e..2a7aae8798 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlTransaction.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlTransaction.xml @@ -1,193 +1,499 @@ - - - - - Represents a Transact-SQL transaction to be made in a SQL Server database. This class cannot be inherited. - - object by calling on the object. All subsequent operations associated with the transaction (for example, committing or aborting the transaction), are performed on the object. - -> [!NOTE] -> `Try`/`Catch` exception handling should always be used when committing or rolling back a . Both and generate an if the connection is terminated or if the transaction has already been rolled back on the server. - - For more information on SQL Server transactions, see [Explicit Transactions](https://msdn.microsoft.com/library/ms175127\(SQL.105\).aspx) and [Coding Efficient Transactions](https://msdn.microsoft.com/library/ms187484\(SQL.105\).aspx). - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error, or if it is disposed without first being committed. `Try`/`Catch` error handling is used to handle any errors when attempting to commit or roll back the transaction. - - [!code-csharp[SqlConnection_BeginTransaction Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction.cs#1)] - - ]]> - - - - Commits the database transaction. - - method is equivalent to the Transact-SQL COMMIT TRANSACTION statement. You cannot roll back a transaction once it has been committed, because all modifications have become a permanent part of the database. For more information, see [COMMIT TRANSACTION (Transact-SQL)](/sql/t-sql/language-elements/commit-transaction-transact-sql). - -> [!NOTE] -> `Try`/`Catch` exception handling should always be used when committing or rolling back a . Both `Commit` and generates an if the connection is terminated or if the transaction has already been rolled back on the server. - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. `Try`/`Catch` error handling is used to handle any errors when attempting to commit or roll back the transaction. - - [!code-csharp[SqlConnection_BeginTransaction Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction.cs#1)] - - ]]> - - An error occurred while trying to commit the transaction. - The transaction has already been committed or rolled back. - - -or- - - The connection is broken. - - - Gets the object associated with the transaction, or if the transaction is no longer valid. - The object associated with the transaction. - - . - - ]]> - - - - To be added. - To be added. - To be added. - - - Releases the resources that are held by the object. - To be added. - - - to release managed and unmanaged resources; to release only unmanaged resources. - Releases the unmanaged resources used and optionally releases the managed resources. - - . + + + + + Represents a Transact-SQL transaction to be made in a SQL Server database. This class cannot be inherited. + + + + The application creates a object by calling on the object. All subsequent operations associated with the transaction (for example, committing or aborting the transaction), are performed on the object. + + + Try / Catch exception handling should always be used when committing or rolling back a . Both and generate an if the connection is terminated or if the transaction has already been rolled back on the server. + + + For more information on SQL Server transactions, see Explicit Transactions and Coding Efficient Transactions + + + + + The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error, or if it is disposed without first being committed. Try / Catch error handling is used to handle any errors when attempting to commit or roll back the transaction. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction(); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback(); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + + + Commits the database transaction. + + + + The method is equivalent to the Transact-SQL COMMIT TRANSACTION statement. You cannot roll back a transaction once it has been committed, because all modifications have become a permanent part of the database. For more information, see COMMIT TRANSACTION (Transact-SQL). + + + Try / Catch exception handling should always be used when committing or rolling back a . Both Commit and generates an if the connection is terminated or if the transaction has already been rolled back on the server. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + + + The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. Try / Catch error handling is used to handle any errors when attempting to commit or roll back the transaction. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction(); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback(); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + An error occurred while trying to commit the transaction. + + + + The transaction has already been committed or rolled back. + The connection is broken. + + + + + + Gets the object associated with the transaction, or if the transaction is no longer valid. + + + The object associated with the transaction. + + + A single application may have multiple database connections, each with zero or more transactions. This property lets you determine the connection object associated with a particular transaction created by . + + + + + To be added. + + + To be added. + + + To be added. + + + + + Releases the resources that are held by the object. + + + + + to release managed and unmanaged resources; to release only unmanaged resources. + + + Releases the unmanaged resources used and optionally releases the managed resources. + + + This method calls . + + + + + Specifies the for this transaction. + + + The for this transaction. The default is . + + + + Parallel transactions are not supported. Therefore, the applies to the whole transaction. + + + For more information on SQL Server isolation levels, see Transaction Isolation Levels. + + + + + + Rolls back a transaction from a pending state. + + + + + Rolls back a transaction from a pending state. + + + + The Rollback method is equivalent to the Transact-SQL ROLLBACK TRANSACTION statement. For more information, see ROLLBACK TRANSACTION (Transact-SQL). + + + The transaction can only be rolled back from a pending state (after has been called, but before is called). The transaction is rolled back in the event it is disposed before or Rollback is called. + + + Try / Catch exception handling should always be used when rolling back a transaction. A Rollback generates an if the connection is terminated or if the transaction has already been rolled back on the server. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + + + The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. Try / Catch error handling is used to handle any errors when attempting to commit or roll back the transaction. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } + + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction(); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback(); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + An error occurred while trying to commit the transaction. + + + + The transaction has already been committed or rolled back. + The connection is broken. + + + + + + The name of the transaction to roll back, or the savepoint to which to roll back. + + + Rolls back a transaction from a pending state, and specifies the transaction or savepoint name. + + + + The method is equivalent to the Transact-SQL ROLLBACK TRANSACTION statement. For more information, see Transactions (Transact-SQL). + + + The transaction can only be rolled back from a pending state (after has been called, but before is called). The transaction is rolled back if it is disposed before or Rollback is called. + + + Try / Catch exception handling should always be used when rolling back a transaction. A Rollback generates an if the connection is terminated or if the transaction has already been rolled back on the server. + + + For more information on SQL Server transactions, see Transactions (Transact-SQL). + + + + + The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. Try / Catch error handling is used to handle any errors when attempting to commit or roll back the transaction. + + + + using System; + using System.Data; + using Microsoft.Data.SqlClient; + + namespace Transaction1CS + { + class Program + { + static void Main() + { + string connectionString = + "Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)"; + ExecuteSqlTransaction(connectionString); + Console.ReadLine(); + } -]]> - - - - Specifies the for this transaction. - The for this transaction. The default is . - - applies to the whole transaction. - - For more information on SQL Server isolation levels, see [Transaction Isolation Levels](/sql/t-sql/language-elements/transaction-isolation-levels). - - ]]> - - - - Rolls back a transaction from a pending state. - - - Rolls back a transaction from a pending state. - - method is equivalent to the Transact-SQL ROLLBACK TRANSACTION statement. For more information, see [ROLLBACK TRANSACTION (Transact-SQL) -](/sql/t-sql/language-elements/rollback-transaction-transact-sql). - - The transaction can only be rolled back from a pending state (after has been called, but before is called). The transaction is rolled back in the event it is disposed before `Commit` or `Rollback` is called. - -> [!NOTE] -> `Try`/`Catch` exception handling should always be used when rolling back a transaction. A `Rollback` generates an if the connection is terminated or if the transaction has already been rolled back on the server. - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. `Try`/`Catch` error handling is used to handle any errors when attempting to commit or roll back the transaction. - - [!code-csharp[SqlConnection_BeginTransaction Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction.cs#1)] - - ]]> - - An error occurred while trying to commit the transaction. - The transaction has already been committed or rolled back. - - -or- - - The connection is broken. - - - The name of the transaction to roll back, or the savepoint to which to roll back. - Rolls back a transaction from a pending state, and specifies the transaction or savepoint name. - - method is equivalent to the Transact-SQL ROLLBACK TRANSACTION statement. For more information, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - - The transaction can only be rolled back from a pending state (after has been called, but before is called). The transaction is rolled back if it is disposed before `Commit` or `Rollback` is called. - -> [!NOTE] -> `Try`/`Catch` exception handling should always be used when rolling back a transaction. A `Rollback` generates an if the connection is terminated or if the transaction has already been rolled back on the server. - - For more information on SQL Server transactions, see [Transactions (Transact-SQL)](/sql/t-sql/language-elements/transactions-transact-sql). - - - -## Examples - The following example creates a and a . It also demonstrates how to use the , , and methods. The transaction is rolled back on any error. `Try`/`Catch` error handling is used to handle any errors when attempting to commit or roll back the transaction. - - [!code-csharp[SqlConnection_BeginTransaction2 Example#1](~/../sqlclient/doc/samples/SqlConnection_BeginTransaction2.cs#1)] - - ]]> - - No transaction name was specified. - The transaction has already been committed or rolled back. - - -or- - - The connection is broken. - - - The name of the savepoint. - Creates a savepoint in the transaction that can be used to roll back a part of the transaction, and specifies the savepoint name. - - method is equivalent to the Transact-SQL SAVE TRANSACTION statement. - - The value used in the `savePoint` parameter can be the same value used in the `transactionName` parameter of some implementations of the method. - - Savepoints offer a mechanism to roll back parts of transactions. You create a savepoint using the method, and then later call the method to roll back to the savepoint instead of rolling back to the start of the transaction. - - ]]> - - An error occurred while trying to commit the transaction. - The transaction has already been committed or rolled back. - - -or- - - The connection is broken. - - + private static void ExecuteSqlTransaction(string connectionString) + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + SqlTransaction transaction; + + // Start a local transaction. + transaction = connection.BeginTransaction("SampleTransaction"); + + // Must assign both transaction object and connection + // to Command object for a pending local transaction + command.Connection = connection; + command.Transaction = transaction; + + try + { + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + command.ExecuteNonQuery(); + command.CommandText = + "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + command.ExecuteNonQuery(); + + // Attempt to commit the transaction. + transaction.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch (Exception ex) + { + Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); + Console.WriteLine(" Message: {0}", ex.Message); + + // Attempt to roll back the transaction. + try + { + transaction.Rollback("SampleTransaction"); + } + catch (Exception ex2) + { + // This catch block will handle any errors that may have occurred + // on the server that would cause the rollback to fail, such as + // a closed connection. + Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); + Console.WriteLine(" Message: {0}", ex2.Message); + } + } + } + } + } + } + + + + No transaction name was specified. + + + + The transaction has already been committed or rolled back. + The connection is broken. + + + + + + The name of the savepoint. + + + Creates a savepoint in the transaction that can be used to roll back a part of the transaction, and specifies the savepoint name. + + + + The Save method is equivalent to the Transact-SQL SAVE TRANSACTION statement. + + + The value used in the parameter can be the same value used in the transactionName parameter of some implementations of the method. + + + Savepoints offer a mechanism to roll back parts of transactions. You create a savepoint using the Save method, and then later call the method to roll back to the savepoint instead of rolling back to the start of the transaction. + + + + An error occurred while trying to commit the transaction. + + + + The transaction has already been committed or rolled back. + The connection is broken. + + + + diff --git a/doc/snippets/Microsoft.Data.SqlTypes/SqlFileStream.xml b/doc/snippets/Microsoft.Data.SqlTypes/SqlFileStream.xml index 2397ba11a3..1abd1847df 100644 --- a/doc/snippets/Microsoft.Data.SqlTypes/SqlFileStream.xml +++ b/doc/snippets/Microsoft.Data.SqlTypes/SqlFileStream.xml @@ -1,346 +1,561 @@ - - - - Exposes SQL Server data that is stored with the FILESTREAM column attribute as a sequence of bytes. - - class is used to work with `varbinary(max)` data stored with the FILESTREAM attribute in a SQL Server 2008 database. You must install the .NET Framework 3.5 SP1 (or later) to use to work with FILESTREAM data. - -Specifying the FILESTREAM attribute on a `varbinary(max)` column causes SQL Server to store the data in the local NTFS file system instead of in the database file. Transact-SQL statements provide data manipulation capabilities within the server, and Win32 file system interfaces provide streaming access to the data. - -> [!NOTE] -> Individual files stored in a FILESTREAM column cannot be opened directly from the NTFS file system. Streaming FILESTREAM data works only in the context of a SQL Server transaction. - -The class is derived from the class, which represents an abstraction of a sequence of bytes from some arbitrary data source such as a file or a block of memory. You can read from a FILESTREAM by transferring data from a stream into a data structure such as an array of bytes. You can write to a FILESTREAM by transferring the data from a data structure into a stream. You can also seek within the stream, which allows you to query and modify data at the current position within the stream. - -For conceptual documentation and code examples, see [FILESTREAM Data](/sql/connect/ado-net/sql/filestream-data). - -For documentation about setting up and configuring FILESTREAM data on SQL Server, see [Designing and Implementing FILESTREAM Storage](https://go.microsoft.com/fwlink/?LinkId=121499) in SQL Server 2008 Books Online. - -]]> - - FILESTREAM Data in SQL Server 2008 (ADO.NET) - SQL Server Data Type Mappings (ADO.NET) - SQL Server Binary and Large-Value Data (ADO.NET) - - - The logical path to the file. The path can be retrieved by using the Transact-SQL Pathname function on the underlying FILESTREAM column in the table. - The transaction context for the object. Applications should return the byte array returned by calling the GET_FILESTREAM_TRANSACTION_CONTEXT method. - The access mode to use when opening the file. Supported enumeration values are , , and . - -When using , the object can be used to read all of the existing data. - -When using , points to a zero byte file. Existing data will be overwritten when the object is closed and the transaction is committed. - -When using , the points to a file which has all the existing data in it. The handle is positioned at the beginning of the file. You can use one of the methods to move the handle position within the file to write or append new data. - Initializes a new instance of the class. - - | -|Write|| -|ReadWrite| and | - -For more information about CAS, see [Code Access Security and ADO.NET](/dotnet/framework/data/adonet/code-access-security). - -If an exception is thrown, any open transactions should be rolled back. Otherwise, data loss can occur. - -]]> - - - is a null reference, or is null. - - is an empty string (""), contains only white space, or contains one or more invalid characters. - begins with "\\\\.\\", for example "\\\\.\PHYSICALDRIVE0 ". - The handle returned by the call to NTCreateFile is not of type FILE_TYPE_DISK. - contains an unsupported value. - The file cannot be found. - An I/O error occurred. - The caller does not have the required permission. - The specified is invalid, such as being on an unmapped drive. - The access requested is not permitted by the operating system for the specified path. This occurs when Write or ReadWrite access is specified, and the file or directory is set for read-only access. - NtCreateFile fails with error code set to ERROR_SHARING_VIOLATION. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - The logical path to the file. The path can be retrieved by using the Transact-SQL Pathname function on the underlying FILESTREAM column in the table. - The transaction context for the object. When set to null, an implicit transaction will be used for the object. Applications should return the byte array returned by calling the GET_FILESTREAM_TRANSACTION_CONTEXT method. - The access mode to use when opening the file. Supported enumeration values are , , and . - -When using , the object can be used to read all of the existing data. - -When using , points to a zero byte file. Existing data will be overwritten when the object is closed and the transaction is committed. - -When using , the points to a file which has all the existing data in it. The handle is positioned at the beginning of the file. You can use one of the methods to move the handle position within the file to write or append new data. - Specifies the option to use while opening the file. Supported values are , , , and . - The allocation size to use while creating a file. If set to 0, the default value is used. - Initializes a new instance of the class. - - | -|Write|| -|ReadWrite| and | - -For more information about CAS, see [Code Access Security and ADO.NET](/dotnet/framework/data/adonet/code-access-security). - -If an exception is thrown, any open transactions should be rolled back. Otherwise, data loss can occur. - -]]> - - - is a null reference, or is null. - - is an empty string (""), contains only white space, or contains one or more invalid characters. - - begins with "\\\\.\\", for example "\\\\.\PHYSICALDRIVE0 " - -The handle returned by call to NTCreateFile is not of type FILE_TYPE_DISK. - - contains an unsupported value. - The file cannot be found. - An I/O error occurred. - The caller does not have the required permission. - The specified is invalid, such as being on an unmapped drive. - The access requested is not permitted by the operating system for the specified path. This occurs when Write or ReadWrite access is specified, and the file or directory is set for read-only access. - NtCreateFile fails with error code set to ERROR_SHARING_VIOLATION. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - The buffer to read the data into. - The byte offset in at which to begin writing data read from the stream. - The maximum number of bytes to read. - An optional asynchronous callback, to be called when the read is complete. - A user-provided object that distinguishes this particular asynchronous read request from other requests - Begins an asynchronous read operation. - An that represents the asynchronous read, which could still be pending. - - property to determine whether the current instance supports reading. - -]]> - - Reading data is not supported on the stream. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - The buffer to write data from. - The byte offset in from which to begin writing. - The maximum number of bytes to write. - An optional asynchronous callback, to be called when the write is complete. - A user-provided object that distinguishes this particular asynchronous write request from other requests. - Begins an asynchronous write operation. - An that represents the asynchronous write, which could still be pending. - - property to determine whether the current instance supports writing. - -]]> - - Writing data is not supported on the stream. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets a value indicating whether the current stream supports reading. - - if the current stream supports reading; otherwise, . - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets a value indicating whether the current stream supports seeking. - - if the current stream supports seeking; otherwise, . - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets a value indicating whether the current stream can time out. - - if the current stream can time out; otherwise, . - To be added. - - - Gets a value indicating whether the current stream supports writing. - - if the current stream supports writing; otherwise, . - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Destructor of the SqlFileStream class object. - To be added. - - - to release managed and unmanaged resources; to release only unmanaged resources. - Releases the unmanaged resources used and optionally releases the managed resources. - - . - -]]> - - - - The reference to the pending asynchronous request to finish. - Waits for the pending asynchronous read to complete. - The number of bytes read from the stream, between zero (0) and the number of bytes you requested. Streams return zero (0) only at the end of the stream, otherwise, they should block until at least one byte is available. - To be added. - The object did not come from the corresponding method. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - A reference to the outstanding asynchronous I/O request. - Ends an asynchronous write operation. - To be added. - The object did not come from the corresponding method. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Ensures that resources are freed and other cleanup operations are performed when the garbage collector reclaims the . - To be added. - - - Clears all buffers for this stream and causes any buffered data to be written to the underlying device. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets a value indicating the length of the current stream in bytes. - An indicating the length of the current stream in bytes. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets the logical path of the passed to the constructor. - A string value indicating the name of the . - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets or sets the position within the current stream. - The current position within the . - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. - The zero-based byte offset in buffer at which to begin storing the data read from the current stream. - The maximum number of bytes to be read from the current stream. - Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. - The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. - - property to determine whether the current instance supports writing. - -]]> - - The object does not support reading of data. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. - The unsigned byte cast to an , or -1 if at the end of the stream. - - property to determine whether the current instance supports reading. - -]]> - - The object does not support reading of data. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. - A value, in milliseconds, that determines how long the stream will attempt to read before timing out. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - A byte offset relative to the parameter - A value of type indicating the reference point used to obtain the new position - Sets the position within the current stream. - The new position within the current stream. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - The desired length of the current stream in bytes. - Sets the length of the current stream. - - property to determine whether the current instance supports reading. - -]]> - - The object does not support reading of data. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets or sets the transaction context for this object. - The array that was passed to the constructor for this object. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - An array of bytes. This method copies bytes from to the current stream. - The zero-based byte offset in at which to begin copying bytes to the current stream. - The number of bytes to be written to the current stream. - Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. - - property to determine whether the current instance supports writing. - -]]> - - The object does not support writing of data. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - The byte to write to the stream. - Writes a byte to the current position in the stream and advances the position within the stream by one byte. - - property to determine whether the current instance supports writing. - -]]> - - The object does not support writing of data. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - - Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. - A value, in milliseconds, that determines how long the stream will attempt to write before timing out. - To be added. - FILESTREAM Data in SQL Server 2008 (ADO.NET) - - + + + + + Exposes SQL Server data that is stored with the FILESTREAM column attribute as a sequence of bytes. + + + + The class is used to work with VARBINARY(MAX) data stored with the FILESTREAM attribute in a SQL Server 2008 database. You must install the .NET Framework 3.5 SP1 (or later) to use to work with FILESTREAM data. + + + Specifying the FILESTREAM attribute on a VARBINARY(MAX) column causes SQL Server to store the data in the local NTFS file system instead of in the database file. Transact-SQL statements provide data manipulation capabilities within the server, and Win32 file system interfaces provide streaming access to the data. + + + Individual files stored in a FILESTREAM column cannot be opened directly from the NTFS file system. Streaming FILESTREAM data works only in the context of a SQL Server transaction. + + + The class is derived from the class, which represents an abstraction of a sequence of bytes from some arbitrary data source such as a file or a block of memory. You can read from a FILESTREAM by transferring data from a stream into a data structure such as an array of bytes. You can write to a FILESTREAM by transferring the data from a data structure into a stream. You can also seek within the stream, which allows you to query and modify data at the current position within the stream. + + + For conceptual documentation and code examples, see FILESTREAM Data. + + + For documentation about setting up and configuring FILESTREAM data on SQL Server, see Designing and Implementing FILESTREAM Storage in SQL Server 2008 Books Online. + + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + SQL Server Data Type Mappings (ADO.NET) + + + SQL Server Binary and Large-Value Data (ADO.NET) + + + + + The logical path to the file. The path can be retrieved by using the Transact-SQL Pathname function on the underlying FILESTREAM column in the table. + + + The transaction context for the object. Applications should return the byte array returned by calling the GET_FILESTREAM_TRANSACTION_CONTEXT method. + + + + The access mode to use when opening the file. Supported enumeration values are , , and . + + + When using , the object can be used to read all the existing data. + + + When using , points to a zero byte file. Existing data will be overwritten when the object is closed and the transaction is committed. + + + When using , the points to a file which has all the existing data in it. The handle is positioned at the beginning of the file. You can use one of the methods to move the handle position within the file to write or append new data. + + + + Initializes a new instance of the class. + + + + The following table lists the code access security (CAS) permissions that all callers in the stack must have to use the constructors. + + + + + File access + Permission + + + Read + + + + Write + + + + ReadWrite + + and + + + + + + For more information about CAS, see Code Access Security and ADO.NET. + + + If an exception is thrown, any open transactions should be rolled back. Otherwise, data loss can occur. + + + + is a null reference, or is null. + + + + is an empty string (""), contains only white space, or contains one or more invalid characters. begins with "\\\\.\\", for example "\\\\.\PHYSICALDRIVE0 ". + + + The handle returned by the call to NTCreateFile is not of type FILE_TYPE_DISK. contains an unsupported value. + + + + The file cannot be found. + + + An I/O error occurred. + + + The caller does not have the required permission. + + + The specified is invalid, such as being on an unmapped drive. + + + The access requested is not permitted by the operating system for the specified path. This occurs when Write or ReadWrite access is specified, and the file or directory is set for read-only access. + + + NtCreateFile fails with error code set to ERROR_SHARING_VIOLATION. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + The logical path to the file. The path can be retrieved by using the Transact-SQL Pathname function on the underlying FILESTREAM column in the table. + + + The transaction context for the object. When set to null, an implicit transaction will be used for the object. Applications should return the byte array returned by calling the GET_FILESTREAM_TRANSACTION_CONTEXT method. + + + The access mode to use when opening the file. Supported enumeration values are , , and . When using , the object can be used to read all the existing data. When using , points to a zero byte file. Existing data will be overwritten when the object is closed and the transaction is committed. When using , the points to a file which has all the existing data in it. The handle is positioned at the beginning of the file. You can use one of the methods to move the handle position within the file to write or append new data. + + + Specifies the option to use while opening the file. Supported values are , , , and . + + + The allocation size to use while creating a file. If set to 0, the default value is used. + + + Initializes a new instance of the class. + + + + The following table lists the code access security (CAS) permissions that all callers in the stack must have to use the SqlFileStream constructors. + + + + + File access + Permission + + + Read + + + + Write + + + + ReadWrite + + and + + + + + + For more information about CAS, see Code Access Security and ADO.NET. + + + If an exception is thrown, any open transactions should be rolled back. Otherwise, data loss can occur. + + + + is a null reference, or is null. + + + + is an empty string (""), contains only white space, or contains one or more invalid characters. begins with "\\\\.\\", for example "\\\\.\PHYSICALDRIVE0 " + + + The handle returned by call to NTCreateFile is not of type FILE_TYPE_DISK. contains an unsupported value. + + + + The file cannot be found. + + + An I/O error occurred. + + + The caller does not have the required permission. + + + The specified is invalid, such as being on an unmapped drive. + + + The access requested is not permitted by the operating system for the specified path. This occurs when Write or ReadWrite access is specified, and the file or directory is set for read-only access. + + + NtCreateFile fails with error code set to ERROR_SHARING_VIOLATION. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + The buffer to read the data into. + + + The byte offset in at which to begin writing data read from the stream. + + + The maximum number of bytes to read. + + + An optional asynchronous callback, to be called when the read is complete. + + + A user-provided object that distinguishes this particular asynchronous read request from other requests + + + Begins an asynchronous read operation. + + + An that represents the asynchronous read, which could still be pending. + + + Use the property to determine whether the current instance supports reading. + + + Reading data is not supported on the stream. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + The buffer to write data from. + + + The byte offset in from which to begin writing. + + + The maximum number of bytes to write. + + + An optional asynchronous callback, to be called when the write is complete. + + + A user-provided object that distinguishes this particular asynchronous write request from other requests. + + + Begins an asynchronous write operation. + + + An that represents the asynchronous write, which could still be pending. + + + Use the property to determine whether the current instance supports writing. + + + Writing data is not supported on the stream. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets a value indicating whether the current stream supports reading. + + + if the current stream supports reading; otherwise, . + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets a value indicating whether the current stream supports seeking. + + + if the current stream supports seeking; otherwise, . + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets a value indicating whether the current stream can time out. + + + if the current stream can time out; otherwise, . + + + + + Gets a value indicating whether the current stream supports writing. + + + if the current stream supports writing; otherwise, . + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Destructor of the SqlFileStream class object. + + + + + to release managed and unmanaged resources; to release only unmanaged resources. + + + Releases the unmanaged resources used and optionally releases the managed resources. + + + This method calls . + + + + + The reference to the pending asynchronous request to finish. + + + Waits for the pending asynchronous read to complete. + + + The number of bytes read from the stream, between zero (0) and the number of bytes you requested. Streams return zero (0) only at the end of the stream, otherwise, they should block until at least one byte is available. + + + The object did not come from the corresponding method. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + A reference to the outstanding asynchronous I/O request. + + + Ends an asynchronous write operation. + + + The object did not come from the corresponding method. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Ensures that resources are freed and other cleanup operations are performed when the garbage collector reclaims the . + + + + + Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets a value indicating the length of the current stream in bytes. + + + An indicating the length of the current stream in bytes. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets the logical path of the passed to the constructor. + + + A string value indicating the name of the . + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets or sets the position within the current stream. + + + The current position within the . + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + + + The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + + + The maximum number of bytes to be read from the current stream. + + + Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + + + The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + + + Use the property to determine whether the current instance supports writing. + + + The object does not support reading of data. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. + + + The unsigned byte cast to an , or -1 if at the end of the stream. + + + Use the property to determine whether the current instance supports reading. + + + The object does not support reading of data. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. + + + A value, in milliseconds, that determines how long the stream will attempt to read before timing out. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + A byte offset relative to the parameter + + + A value of type indicating the reference point used to obtain the new position + + + Sets the position within the current stream. + + + The new position within the current stream. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + The desired length of the current stream in bytes. + + + Sets the length of the current stream. + + + Use the property to determine whether the current instance supports reading. + + + The object does not support reading of data. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets or sets the transaction context for this object. + + + The TransactionContext array that was passed to the constructor for this object. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + An array of bytes. This method copies bytes from to the current stream. + + + The zero-based byte offset in at which to begin copying bytes to the current stream. + + + The number of bytes to be written to the current stream. + + + Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + + + Use the property to determine whether the current instance supports writing. + + + The object does not support writing of data. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + The byte to write to the stream. + + + Writes a byte to the current position in the stream and advances the position within the stream by one byte. + + + Use the property to determine whether the current instance supports writing. + + + The object does not support writing of data. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + + + Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. + + + A value, in milliseconds, that determines how long the stream will attempt to write before timing out. + + + FILESTREAM Data in SQL Server 2008 (ADO.NET) + + + diff --git a/doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml b/doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml new file mode 100644 index 0000000000..6d55346417 --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml @@ -0,0 +1,33 @@ + + + + + Represents the JSON datatype in SQL Server. + + + Parameterless constructor. Initializes a new instance of the SqlJson class which represents a null JSON value. + + + + Takes a as input and initializes a new instance of the SqlJson class. + + + + Takes a as input and initializes a new instance of the SqlJson class. + + + + + + Represents a null instance of the type. + + + Gets the string representation of the Json content of this instance. + + + + Retrieves the column at ordinal as a . + A object representing the column at the given ordinal. + + + diff --git a/doc/snippets/Microsoft.Data/OperationAbortedException.xml b/doc/snippets/Microsoft.Data/OperationAbortedException.xml index b008f22b67..5ac373d13f 100644 --- a/doc/snippets/Microsoft.Data/OperationAbortedException.xml +++ b/doc/snippets/Microsoft.Data/OperationAbortedException.xml @@ -1,17 +1,12 @@ - - - - - This exception is thrown when an ongoing operation is aborted by the user. - - event sets the **Abort** property to `true` in the object passed to the handler, the method stops sending rows to the server and throws an . - -]]> - - - + + + + + This exception is thrown when an ongoing operation is aborted by the user. + + + This exception indicates that an operation has been aborted by the consumer of an API. For example, if the event handler of the event sets the property to in the object passed to the handler, the method stops sending rows to the server and throws an . + + + diff --git a/doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml b/doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml new file mode 100644 index 0000000000..a3d03229f5 --- /dev/null +++ b/doc/snippets/Microsoft.Data/SqlDbTypeExtensions.xml @@ -0,0 +1,24 @@ + + + + + Extensions for SqlDbType. + + + class provides enums which will be added. These are meant to be used by applications which cannot leverage the enums in available in newer .NET runtime versions. + +]]> + + + + + Gets the enum value for the JSON datatype. + + enum value for JSON datatype. + + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/DataAccessKind.xml b/doc/snippets/Microsoft.SqlServer.Server/DataAccessKind.xml index 1590300ea4..d5b2f18c7c 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/DataAccessKind.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/DataAccessKind.xml @@ -1,26 +1,30 @@ - - - - - Describes the type of access to user data for a user-defined method or function. - - and to indicate whether the method or function uses ADO.NET to connect back to the database using the "context connection." - -Note that methods and functions are not allowed to make changes to the database, so the options for this enumeration are `None` (meaning no data-access performed by the method or function) and `Read` (meaning that the method or function perform read-only data-access operations, such as executing SELECT statements). - - ]]> - - - - The method or function does not access user data. - - - The method or function reads user data. - - + + + + + Describes the type of access to user data for a user-defined method or function. + + + + Describes the type of access to user data for a user-defined method or function. + + + This enumeration is used in and to indicate whether the method or function uses ADO.NET to connect back to the database using the "context connection." + + + Note that methods and functions are not allowed to make changes to the database, so the options for this enumeration are (meaning no data-access performed by the method or function) and (meaning that the method or function perform read-only data-access operations, such as executing SELECT statements). + + + + + + The method or function does not access user data. + + + + + The method or function reads user data. + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/Format.xml b/doc/snippets/Microsoft.SqlServer.Server/Format.xml index 31b5776207..cf461f1129 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/Format.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/Format.xml @@ -1,56 +1,313 @@ - - - - - Used by and to indicate the serialization format of a user-defined type (UDT) or aggregate. - - and to indicate the serialization format of a user-defined type (UDT) or aggregate. Use of the `Native` and `UserDefined` enumeration members has special requirements. - -- `Format.Native` - The requirements for the `Format.Native` format are: - - - The with a property value of must be applied to the aggregate or UDT if it is defined in a class and not a structure. This controls the physical layout of the data fields and is used to force the members to be laid out sequentially in the order they appear. SQL Server uses this attribute to determine the field order for UDTs with multiple fields. - - - The type must contain at least one member (serialized values cannot be zero bytes in size). - - - All the fields of the aggregate must be *blittable*; that is, they must have a common representation in both managed and unmanaged memory and not require special handling by the interop marshaler. - - - All the fields of the UDT should be of one of the following types that can be serialized: `bool`, `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `float`, `double`, , , , , , , , , or other value types defined by the user that contain fields of one of these types. - - The aggregate must not specify a value for `MaxByteSize`. - - - The aggregate must not have any [NonSerialized] fields. - - - Fields must not be marked as an explicit layout (with a of ). -- `Format.UserDefined` - The requirements for the `Format.UserDefined` format are: - - The aggregate must specify a value for `MaxByteSize`. - - - Specify the attribute property. The default value is `false`. - - - If you omit any field in the or methods, the state of that field is not serialized. - -## Examples - -The following example shows the `UserDefinedType` attribute of the Point UDT. The UDT is byte-ordered, is named "Point", has a validation method named "ValidatePoint", and uses the native serialization format. - -[!code-csharp[SqlUserDefinedTypeAttribute Example#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/DataWorks_SqlUserDefinedTypeAttribute_Sample.cs#1)] -[!code-vb[SqlUserDefinedTypeAttribute Example#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/visualbasic/DataWorks_SqlUserDefinedTypeAttribute_Sample.vb#1)] - - ]]> - - - - This serialization format uses a very simple algorithm that enables SQL Server to store an efficient representation of the UDT on disk. Types marked for serialization can only have value types (structs in Microsoft Visual C# and structures in Microsoft Visual Basic .NET) as members. Members of reference types (such as classes in Visual C# and Visual Basic), either user-defined or those existing in .NET class libraries (such as ), are not supported. - - - The serialization format is unknown. - - - This serialization format gives the developer full control over the binary format through the and methods. - - + + + + + Used by and to indicate the serialization format of a user-defined type (UDT) or aggregate. + + + + This enumeration is used by and to indicate the serialization format of a user-defined type (UDT) or aggregate. Use of the and enumeration members has special requirements. + + + The requirements for the format are: + + + + The with a property value of must be applied to the aggregate or UDT if it is defined in a class and not a structure. This controls the physical layout of the data fields and is used to force the members to be laid out sequentially in the order they appear. SQL Server uses this attribute to determine the field order for UDTs with multiple fields. + + + The type must contain at least one member (serialized values cannot be zero bytes in size). + + + All the fields of the aggregate must be blittable; that is, they must have a common representation in both managed and unmanaged memory and not require special handling by the interop marshaller. + + + All the fields of the UDT should be of one of the following types that can be serialized: bool, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, , , , , , , , , or other value types defined by the user that contain fields of one of these types. + + + The aggregate must not specify a value for MaxByteSize + + + The aggregate must not have any [NonSerialized] fields. + + + Fields must not be marked as an explicit layout (with a of ). + + + + The requirements for the format are: + + + + The aggregate must specify a value for MaxByteSize + + + Specify the attribute property. The default value is . + + + If you omit any field in the or methods, the state of that field is not serialized. + + + + + + The following example shows the attribute of the Point UDT. The UDT is byte-ordered, is named "Point", has a validation method named "ValidatePoint", and uses the native serialization format. + + + + using System; + using System.Data.SqlTypes; + using Microsoft.SqlServer.Server; + using System.Text; + + [Serializable] + [Microsoft.SqlServer.Server.SqlUserDefinedType( + Format.Native, + IsByteOrdered=true, + Name="Point",ValidationMethodName = "ValidatePoint")] + public struct Point : INullable + { + private bool is_Null; + private int _x; + private int _y; + + public bool IsNull + { + get + { + return (is_Null); + } + } + + public static Point Null + { + get + { + Point pt = new Point(); + pt.is_Null = true; + return pt; + } + } + + // Use StringBuilder to provide string representation of UDT. + public override string ToString() + { + // Since InvokeIfReceiverIsNull defaults to 'true' + // this test is unnecessary if Point is only being called + // from SQL. + if (this.IsNull) + { + return "NULL"; + } + else + { + StringBuilder builder = new StringBuilder(); + builder.Append(_x); + builder.Append(","); + builder.Append(_y); + return builder.ToString(); + } + } + + [SqlMethod(OnNullCall = false)] + public static Point Parse(SqlString s) + { + // With OnNullCall=false, this check is unnecessary if + // Point only called from SQL. + if (s.IsNull) + return Null; + + // Parse input string to separate out points. + Point pt = new Point(); + string[] xy = s.Value.Split(",".ToCharArray()); + pt.X = int.Parse(xy[0]); + pt.Y = int.Parse(xy[1]); + + // Call ValidatePoint to enforce validation + // for string conversions. + if (!pt.ValidatePoint()) + throw new ArgumentException("Invalid XY coordinate values."); + return pt; + } + + // X and Y coordinates exposed as properties. + public int X + { + get + { + return this._x; + } + // Call ValidatePoint to ensure valid range of Point values. + set + { + int temp = _x; + _x = value; + if (!ValidatePoint()) + { + _x = temp; + throw new ArgumentException("Invalid X coordinate value."); + } + } + } + + public int Y + { + get + { + return this._y; + } + set + { + int temp = _y; + _y = value; + if (!ValidatePoint()) + { + _y = temp; + throw new ArgumentException("Invalid Y coordinate value."); + } + } + } + + // Validation method to enforce valid X and Y values. + private bool ValidatePoint() + { + return true; + } + } + + + + Option Explicit On + Option Strict On + + Imports System.Data.SqlTypes + Imports Microsoft.SqlServer.Server + Imports System.Text + + <Serializable(), SqlUserDefinedTypeAttribute(_ + Format.Native, _ + IsByteOrdered:=True, _ + Name:="Point", _ + ValidationMethodName:="ValidatePoint")> _ + Public Structure Point + Implements INullable + Private is_Null As Boolean + Private _x As Integer + Private _y As Integer + + Public ReadOnly Property IsNull() As Boolean _ + Implements INullable.IsNull + Get + Return (is_Null) + End Get + End Property + + Public Shared ReadOnly Property Null() As Point + Get + Dim pt As New Point + pt.is_Null = True + Return (pt) + End Get + End Property + + ' Use StringBuilder to provide string representation of UDT. + Public Overrides Function ToString() As String + ' Since InvokeIfReceiverIsNull defaults to 'true' + ' this test is unnecessary if Point is only being called + ' from SQL. + If Me.IsNull Then + Return "NULL" + Else + Dim builder As StringBuilder = New StringBuilder + builder.Append(_x) + builder.Append(",") + builder.Append(_y) + Return builder.ToString + End If + End Function + + <SqlMethod(OnNullCall:=False)> _ + Public Shared Function Parse(ByVal s As SqlString) As Point + ' With OnNullCall=False, this check is unnecessary if + ' Point only being called from SQL. + If s.IsNull Then + Return Null + End If + + ' Parse input string here to separate out points. + Dim pt As New Point() + Dim xy() As String = s.Value.Split(",".ToCharArray()) + pt.X = Integer.Parse(xy(0)) + pt.Y = Integer.Parse(xy(1)) + + ' Call ValidatePoint to enforce validation + ' for string conversions. + If Not pt.ValidatePoint() Then + Throw New ArgumentException("Invalid XY coordinate values.") + End If + Return pt + End Function + + ' X and Y coordinates are exposed as properties. + Public Property X() As Integer + Get + Return (Me._x) + End Get + + Set(ByVal Value As Integer) + Dim temp As Integer = _x + _x = Value + If Not ValidatePoint() Then + _x = temp + Throw New ArgumentException("Invalid X coordinate value.") + End If + End Set + End Property + + Public Property Y() As Integer + Get + Return (Me._y) + End Get + + Set(ByVal Value As Integer) + Dim temp As Integer = _y + _y = Value + If Not ValidatePoint() Then + _y = temp + Throw New ArgumentException("Invalid Y coordinate value.") + End If + End Set + End Property + + ' Validation method to enforce valid X and Y values. + Private Function ValidatePoint() As Boolean + ' Allow only zero or positive integers for X and Y coordinates. + If (_x >= 0) And (_y >= 0) Then + Return True + Else + Return False + End If + End Function + + End Structure + + + + + + This serialization format uses a very simple algorithm that enables SQL Server to store an efficient representation of the UDT on disk. Types marked for + Native serialization can only have value types (structs in Microsoft Visual C# and structures in Microsoft Visual Basic .NET) as members. Members of reference types (such as classes in Visual C# and Visual Basic), either user-defined or those existing in .NET class libraries (such as ), are not supported. + + + + + The serialization format is unknown. + + + + + This serialization format gives the developer full control over the binary format through the and methods. + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/IBinarySerialize.xml b/doc/snippets/Microsoft.SqlServer.Server/IBinarySerialize.xml index 79128e5655..a94c8921be 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/IBinarySerialize.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/IBinarySerialize.xml @@ -1,56 +1,184 @@ - - - - - Provides custom implementation for user-defined type (UDT) and user-defined aggregate serialization and deserialization. - - .`Native` or .`UserDefined`. - -.`Native` allows SQL Server to handle serialization and deserialization automatically, but the format has restrictions on the kind of types it can handle. .`UserDefined` allows user-defined types and aggregates to handle their own serialization. User-defined types and aggregates must be marked with .`UserDefined` in the `SqlUserDefinedType` or `SqlUserDefinedAggregate` attribute, and must implement the interface. - -Note that even with custom serialization, the total size of each instance must be under the maximum allowed limit, currently 8000 bytes. - - ]]> - - - - The stream from which the object is deserialized. - Generates a user-defined type (UDT) or user-defined aggregate from its binary form. - - method must reconstitute your object using the information written by the method. - -## Examples -The following example shows the implementation of the method of a UDT, which uses a to de-serialize a previously persisted UDT. This example assumes that the UDT has two data properties: `StringValue` and `DoubleValue`. - -[!code-csharp[IBinarySerialize Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/DataWorks_IBinarySerialize_Sample.cs#1)] -[!code-vb[IBinarySerialize Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/visualbasic/DataWorks_IBinarySerialize_Sample.vb#1)] - - ]]> - - - - The stream to which the UDT or user-defined aggregate is serialized. - Converts a user-defined type (UDT) or user-defined aggregate into its binary format so that it may be persisted. - - method to reconstitute your UDT or user-defined aggregate. - -## Examples -The following example shows the implementation of the method of a UDT, which uses a to serialize the UDT in the user-defined binary format. The purpose of the null character padding is to ensure that the string value is completely separated from the double value, so that one UDT is compared to another in Transact-SQL code, string bytes are compared to string bytes and double bytes are compared to double bytes. - -[!code-csharp[IBinarySerialize Samples#2](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/DataWorks_IBinarySerialize_Sample.cs#2)] -[!code-vb[IBinarySerialize Samples#2](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/visualbasic/DataWorks_IBinarySerialize_Sample.vb#2)] - - ]]> - - - + + + + + Provides custom implementation for user-defined type (UDT) and user-defined aggregate serialization and deserialization. + + + + User-defined types (UDTs) and user-defined aggregates are required to define a storage format, which can be either or . + + + allows SQL Server to handle serialization and deserialization automatically, but the format has restrictions on the kind of types it can handle. allows user-defined types and aggregates to handle their own serialization. User-defined types and aggregates must be marked with in the or attribute, and must implement the IBinarySerialize interface. + + + Note that even with custom serialization, the total size of each instance must be under the maximum allowed limit, currently 8000 bytes. + + + + + + The stream from which the object is deserialized. + + + Generates a user-defined type (UDT) or user-defined aggregate from its binary form. + + + The method must reconstitute your object using the information written by the method. + + + + The following example shows the implementation of the method of a UDT, which uses a to de-serialize a previously persisted UDT. This example assumes that the UDT has two data properties: StringValue and DoubleValue. + + + + // The binary layout is as follows: + // Bytes 0 - 19: string text, padded to the right with null characters + // Bytes 20+: Double value + + // using Microsoft.SqlServer.Server; + public void Read(System.IO.BinaryReader r) + { + + int maxStringSize = 20; + char[] chars; + int stringEnd; + string stringValue; + double doubleValue; + + // Read the characters from the binary stream. + chars = r.ReadChars(maxStringSize); + + // Find the start of the null character padding. + stringEnd = Array.IndexOf(chars, '\0'); + + if (stringEnd == 0) + { + stringValue = null; + return; + } + + // Build the string from the array of characters. + stringValue = new String(chars, 0, stringEnd); + + // Read the double value from the binary stream. + doubleValue = r.ReadDouble(); + + // Set the object's properties equal to the values. + this.StringValue = stringValue; + this.DoubleValue = doubleValue; + } + + + + ' The binary layout is as follows: + ' Bytes 0 - 19: string text, padded to the right with null + ' characters + ' Bytes 20+: double value + Public Sub Read(ByVal r As System.IO.BinaryReader) _ + Implements Microsoft.SqlServer.Server.IBinarySerialize.Read + + Dim maxStringSize As Integer = 20 + Dim chars As Char() + Dim stringEnd As Integer + Dim stringValue As String + Dim value As double + + ' Read the characters from the binary stream. + chars = r.ReadChars(maxStringSize) + + ' Find the start of the null character padding. + stringEnd = Array.IndexOf(chars, ControlChars.NullChar) + + If StringEnd = 0 Then + stringValue = Nothing + Exit Sub + End If + + ' Build the string from the array of characters. + stringValue = new String(chars, 0, stringEnd) + + ' Read the double value from the binary stream. + value = r.ReadDouble() + + ' Set the object's properties equal to the values. + Me.StringValue = stringValue + Me.DoubleValue = value + + End Sub + + + + + + The stream to which the UDT or user-defined aggregate is serialized. + + + Converts a user-defined type (UDT) or user-defined aggregate into its binary format so that it may be persisted. + + + Write sufficient information to the binary stream to allow the method to reconstitute your UDT or user-defined aggregate. + + + + The following example shows the implementation of the method of a UDT, which uses a to serialize the UDT in the user-defined binary format. The purpose of the null character padding is to ensure that the string value is completely separated from the double value, so that one UDT is compared to another in Transact-SQL code, string bytes are compared to string bytes and double bytes are compared to double bytes. + + + + // The binary layout is as follows: + // Bytes 0 - 19: string text, padded to the right with null characters + // Bytes 20+: Double value + + // using Microsoft.SqlServer.Server; + public void Write(System.IO.BinaryWriter w) + { + int maxStringSize = 20; + string stringValue = "The value of PI: "; + string paddedString; + double value = 3.14159; + + // Pad the string from the right with null characters. + paddedString = stringValue.PadRight(maxStringSize, '\0'); + + // Write the string value one byte at a time. + for (int i = 0; i < paddedString.Length; i++) + { + w.Write(paddedString[i]); + } + + // Write the double value. + w.Write(value); + } + + + + ' The binary layout is as follows: + ' Bytes 0 - 19: string text, padded to the right with null characters + ' Bytes 20+: Double value + Public Sub Write(ByVal w As System.IO.BinaryWriter) _ + Implements Microsoft.SqlServer.Server.IBinarySerialize.Write + + Dim maxStringSize As Integer = 20 + Dim stringValue As String = "The value of PI: " + Dim paddedString As String + Dim value As Double = 3.14159 + + ' Pad the string from the right with null characters. + paddedString = stringValue.PadRight(maxStringSize, ControlChars.NullChar) + + + ' Write the string value one byte at a time. + Dim i As Integer + For i = 0 To paddedString.Length - 1 + w.Write(paddedString(i)) + Next + + ' Write the double value. + w.Write(value) + + End Sub + + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/InvalidUdtException.xml b/doc/snippets/Microsoft.SqlServer.Server/InvalidUdtException.xml index 9ec4002c76..42d9b9885a 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/InvalidUdtException.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/InvalidUdtException.xml @@ -1,39 +1,45 @@ - - - - - Thrown when SQL Server or the ADO.NET provider detects an invalid user-defined type (UDT). - To be added. - - - The object. - The object. - Streams all the properties into the class for the given . - - class to make the class serializable. - - ]]> - - - - The object. - The object that represents a string in string resources. The default value is `SqlUdtReason_NoUdtAttribute` which looks up a localized string similar to "no UDT attribute". - Creates a new object. - A new object. - - [!IMPORTANT] -> This function is exposed for backward compatibility and should be used with the default value for the `resourceReason` parameter. - - ]]> - - - + + + + + Thrown when SQL Server or the ADO.NET provider detects an invalid user-defined type (UDT). + + + + + The object. + + + The object. + + + Streams all the properties into the class for the given . + + + This method is present in the class to make the class serializable. + + + + + The object. + + + The object that represents a string in string resources. The default value is `SqlUdtReason_NoUdtAttribute` which looks up a localized string similar to "no UDT attribute". + + + Creates a new object. + + + A new object. + + + + This method Looks up a localized string similar to '{0}' is an invalid user defined type, reason: {1}., and fills it in order with the corresponding and values. + + + This function is exposed for backward compatibility and should be used with the default value for the parameter. + + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SqlFacetAttribute.xml b/doc/snippets/Microsoft.SqlServer.Server/SqlFacetAttribute.xml index cae95f8032..cc47a27ca7 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SqlFacetAttribute.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SqlFacetAttribute.xml @@ -1,124 +1,297 @@ - - - - - Annotates the returned result of a user-defined type (UDT) with additional information that can be used in Transact-SQL. - - may only be specified on non-void return values. - - is used only to derive information about the return type, and is not intended to be a constraint specification on what can be stored in the type. Thus, if a field has a indicating its size to be 2 characters, then the SQL Server type of the field access expression is of size 2, but assignments into the field are not restricted by this facet. - -The table below captures the matrix of valid values for the various properties for specific field types. In this table, "Y" indicates that the property is valid, and "N" indicates that the property is not valid. - -The specified must be compatible with the field type. If the property is not valid, type registration will report an error if the user specifies a non-default value for the property. The maximum values for and properties are 38. For the property, the value should be in the range of 1-8000 for binary and non-Unicode data, 1-4000 for Unicode data, or -1. All other values are not valid. - -|Type|IsFixedLength|MaxSize|Precision|Scale|IsNullable| -|----------|-------------------|-------------|---------------|-----------|----------------| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|N|N|Y| -||N|N|Y|Y|Y| -||Y|Y|N|N|Y| -||Y|Y|N|N|Y| -||N|N|N|N|Y| -||Y|Y|N|N|Y| -||Y|Y|N|N|Y| -|Embedded UDTs|N|N|N|N|Y| -||Y|Y|N|N|Y| -|Byte[]|Y|Y|N|N|Y| -|Char[]|Y|Y|N|N|Y| -||N|N|N|Y1|N| -||N|N|Y|Y|Y| - -(1) Specifying the scale on a DateTime type will cause the value to be returned to Transact-SQL as a DateTime2 type with the specified scale. - - ]]> - - - - An optional attribute on a user-defined type (UDT) return type, used to annotate the returned result with additional information that can be used in Transact-SQL. - To be added. - - - Indicates whether the return type of the user-defined type is of a fixed length. - - if the return type is of a fixed length; otherwise . - - property is set to 1. - -The default value is `false`. - -]]> - - - - Indicates whether the return type of the user-defined type can be . - - if the return type of the user-defined type can be ; otherwise . - - - - - - The maximum size, in logical units, of the underlying field type of the user-defined type. - An representing the maximum size, in logical units, of the underlying field type. - - - - - - The precision of the return type of the user-defined type. - An representing the precision of the return type. - - property is valid only for numeric types. The property must also be specified when setting the property. - -The maximum value of the property is 38; the default value is 38. - - ]]> - - - - The scale of the return type of the user-defined type. - An representing the scale of the return type. - - property is valid only for decimal types. The property must also be specified when setting the property. - -The maximum value of the property is 38; the default value is 0. - - ]]> - - - + + + + + Annotates the returned result of a user-defined type (UDT) with additional information that can be used in Transact-SQL. + + + + may only be specified on non-void return values. + + + is used only to derive information about the return type, and is not intended to be a constraint specification on what can be stored in the type. Thus, if a field has a indicating its size to be 2 characters, then the SQL Server type of the field access expression is of size 2, but assignments into the field are not restricted by this facet. + + + The table below captures the matrix of valid values for the various properties for specific field types. In this table, "Y" indicates that the property is valid, and "N" indicates that the property is not valid. + + + The specified must be compatible with the field type. If the property is not valid, type registration will report an error if the user specifies a non-default value for the property. The maximum values for and properties are 38. For the property, the value should be in the range of 1-8000 for binary and non-Unicode data, 1-4000 for Unicode data, or -1. All other values are not valid. + + + + + Type + IsFixedLength + MaxSize + Precision + Scale + IsNullable + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + N + N + Y + + + + N + N + Y + Y + Y + + + + Y + Y + N + N + Y + + + + Y + Y + N + N + Y + + + + N + N + N + N + Y + + + + Y + Y + N + N + Y + + + + Y + Y + N + N + Y + + + Embedded UDTs + N + N + N + N + Y + + + + Y + Y + N + N + Y + + + Byte[] + Y + Y + N + N + Y + + + Char[] + Y + Y + N + N + Y + + + + N + N + N + Y1 + N + + + + N + N + Y + Y + Y + + + + + (1) Specifying the scale on a DATETIME type will cause the value to be returned to Transact-SQL as a DATETIME2 type with the specified scale. + + + + + + An optional attribute on a user-defined type (UDT) return type, used to annotate the returned result with additional information that can be used in Transact-SQL. + + + + + Indicates whether the return type of the user-defined type is of a fixed length. + + + if the return type is of a fixed length; otherwise . + + + + This property must be set to if the property is set to 1. + + + The default value is . + + + + + + Indicates whether the return type of the user-defined type can be . + + + if the return type of the user-defined type can be ; otherwise . + + + The default value is . + + + + + The maximum size, in logical units, of the underlying field type of the user-defined type. + + + An representing the maximum size, in logical units, of the underlying field type. + + + + Logical unit is bytes (with a maximum size of 8000) for the binary and non-Unicode data types, and the number of Unicode characters (with a maximum size of 4000) for the character field types. + + + The value -1 is reserved for large character and binary types. + + + The default value is 4000 for Unicode character types and 8000 for binary and non-Unicode types. + + + + + + The precision of the return type of the user-defined type. + + + An representing the precision of the return type. + + + + The property is valid only for numeric types. The property must also be specified when setting the property. + + + The maximum value of the property is 38; the default value is 38. + + + + + + The scale of the return type of the user-defined type. + + + An representing the scale of the return type. + + + + The property is valid only for decimal types. The property must also be specified when setting the property. + + + The maximum value of the property is 38; the default value is 0. + + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SqlFunctionAttribute.xml b/doc/snippets/Microsoft.SqlServer.Server/SqlFunctionAttribute.xml index ddf4c76e4b..00900d7b9d 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SqlFunctionAttribute.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SqlFunctionAttribute.xml @@ -1,130 +1,226 @@ - - - - - Used to mark a method definition of a user-defined aggregate as a function in SQL Server. The properties on the attribute reflect the physical characteristics used when the type is registered with SQL Server. - - - - - - An optional attribute on a user-defined aggregate, used to indicate that the method should be registered in SQL Server as a function. Also used to set the , , , , , , and properties of the function attribute. - To be added. - - - Indicates whether the function involves access to user data stored in the local instance of SQL Server. - - .: Does not access data. .: Only reads user data. - - . is also required when connecting to remote servers if transactions integration is required (the default). - -If a Transact-SQL query is executed from inside a table-valued function (TVF), the property should be set. - -]]> - - - - The name of a method in the same class which is used to fill a row of data in the table returned by the table-valued function. - A value representing the name of a method in the same class which is used to fill a row of data in the table returned by the table-valued function. - - - Indicates whether the user-defined function is deterministic. - - if the function is deterministic; otherwise . - - property is also useful for indexing the result of the function in the form of indexed computed columns and indexed views. If this property is not specified, the function is assumed to be non-deterministic. - -Functions that access local data can be deterministic. The data access characteristic is captured separately by the and properties. - -Note that data access to remote servers (for example, using a to connect to another SQL Server instance) is available in user-defined functions. However, you must still honor the declaration. If the common language runtime (CLR) function is marked as deterministic, it should not cause side-effects in the remote server. While side-effects against the context connection are restricted, SQL Server will not enforce the restriction for side-effects over remote connections. - -The default value of this attribute is `false`. - -Do not mark a function as deterministic if the function does not always produce the same output values, given the same input values and the same database state. Marking a function as deterministic when the function is not truly deterministic can result in corrupted indexed views and computed columns. - -]]> - - - - Indicates whether the function involves imprecise computations, such as floating point operations. - - if the function involves precise computations; otherwise . - - - - - - The name under which the function should be registered in SQL Server. - A value representing the name under which the function should be registered. - - - - - - Indicates whether the function requires access to data stored in the system catalogs or virtual system tables of SQL Server. - - .: Does not access system data. .: Only reads system data. - - . - -]]> - - - - A string that represents the table definition of the results, if the method is used as a table-valued function (TVF). - A value representing the table definition of the results. - - - - - + + + + + Used to mark a method definition of a user-defined aggregate as a function in SQL Server. The properties on the attribute reflect the physical characteristics used when the type is registered with SQL Server. + + + + The following example shows an aggregate function that returns a list of files in the specified directory path. + + + + using System.IO; + using System.Collections; + using Microsoft.SqlServer.Server; + + public class Class1 + { + [SqlFunctionAttribute(FillRowMethodName = "FillFileRow")] + public static IEnumerable GetFileDetails(string directoryPath) + { + try + { + DirectoryInfo di = new DirectoryInfo(directoryPath); + return di.GetFiles(); + } + catch (DirectoryNotFoundException dnf) + { + return new string[1] { dnf.ToString() }; + } + } + } + + + + Option Explicit On + Option Strict On + + Imports System.IO + Imports System.Collections + Imports Microsoft.SqlServer.Server + + Public Class Class1 + + <SqlFunction(FillRowMethodName:="FillFileRow")> _ + Public Shared Function GetFileDetails(ByVal directoryPath As String) As IEnumerable + Try + Dim di As DirectoryInfo = new DirectoryInfo(directoryPath) + return di.GetFiles() + Catch dnf As DirectoryNotFoundException + Dim message As String() = {dnf.ToString() } + return message + End Try + End Function + + End Class + + + + + + An optional attribute on a user-defined aggregate, used to indicate that the method should be registered in SQL Server as a function. Also used to set the , , , , , , and properties of the function attribute. + + + + + Indicates whether the function involves access to user data stored in the local instance of SQL Server. + + . : Does not access data. . : Only reads user data. + + + The default is . is also required when connecting to remote servers if transactions integration is required (the default). + + + If a Transact-SQL query is executed from inside a table-valued function (TVF), the property should be set. + + + + + + The name of a method in the same class which is used to fill a row with data in the table returned by the table-valued function. + + + A value representing the name of a method in the same class which is used to fill a row with data in the table returned by the table-valued function. + + + + + Indicates whether the user-defined function is deterministic. + + + if the function is deterministic; otherwise . + + + + A user-defined function is said to be deterministic if it always produces the same output values given the same input values and the same database state. + + + The property is also useful for indexing the result of the function in the form of indexed computed columns and indexed views. If this property is not specified, the function is assumed to be non-deterministic. + + + Functions that access local data can be deterministic. The data access characteristic is captured separately by the and properties. + + + Note that data access to remote servers (for example, using a to connect to another SQL Server instance) is available in user-defined functions. However, you must still honor the declaration. If the common language runtime (CLR) function is marked as deterministic, it should not cause side effects in the remote server. While side effects against the context connection are restricted, SQL Server will not enforce the restriction for side effects over remote connections. + + + The default value of this attribute is . + + + Do not mark a function as deterministic if the function does not always produce the same output values, given the same input values and the same database state. Marking a function as deterministic when the function is not truly deterministic can result in corrupted indexed views and computed columns. + + + + + + Indicates whether the function involves imprecise computations, such as floating point operations. + + + if the function involves precise computations; otherwise . + + + + Precision of a function is one of the properties used to determine if computed columns that use this function can be indexed. + + + The default value of this attribute is . + + + + + + The name under which the function should be registered in SQL Server. + + + A value representing the name under which the function should be registered. + + + + This attribute is used only by Microsoft Visual Studio to automatically register the specified method as a user-defined function. It is not used by SQL Server. + + + The following example specifies that the user-defined function is referenced using the name sp_scalarFunc. + + + + + + public partial class UserDefinedFunctions + { + [SqlFunction(Name="sp_scalarFunc")] + public static SqlString SampleScalarFunction(SqlString s) + { + //... + return ""; + } + } + + + + Partial Public Class UserDefinedFunctions + + <SqlFunction(Name:="sp_scalarFunc")> + Public Shared Function SampleScalarFunction(ByVal s As SqlString) As SqlString + + '... + Return "" + End Function + + End Class + + + + + + Indicates whether the function requires access to data stored in the system catalogs or virtual system tables of SQL Server. + + + : Does not access system data. : Only reads system data. + + The default is . + + + + + A string that represents the table definition of the results, if the method is used as a table-valued function (TVF). + + + A value representing the table definition of the results. + + + This attribute is used only by Microsoft Visual Studio to automatically register the specified method as a TVF. It is not used by SQL Server. + + + + The following example specifies that the user-defined function is referenced using the name sp_tableFunc. The TableDefinition property has the value letter nchar(1). + + + + public partial class UserDefinedFunctions + { + [SqlFunction(Name="sp_tableFunc", TableDefinition="letter nchar(1)")] + public static IEnumerable SampleTableFunction(SqlString s) + { + //... + return new ArrayList(new char[3] {'a', 'b', 'c'}); + } + } + + + + Partial Public Class UserDefinedFunctions + + <SqlFunction(Name:="sp_tableFunc", TableDefinition:="letter nchar(1)")> + Public Shared Function SampleTableFunction(ByVal s As SqlString) As IEnumerable + + '... + Return New Char(2) {"a"c, "b"c, "c"c} + End Function + + End Class + + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SqlMethodAttribute.xml b/doc/snippets/Microsoft.SqlServer.Server/SqlMethodAttribute.xml index 55a9858ded..1c55b2d3f6 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SqlMethodAttribute.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SqlMethodAttribute.xml @@ -1,68 +1,95 @@ - - - - - Indicates the determinism and data access properties of a method or property on a user-defined type (UDT). The properties on the attribute reflect the physical characteristics that are used when the type is registered with SQL Server. - - should be used on the setter or the getter directly. - - inherits from a , so inherits the `FillRowMethodName` and `TableDefinition` fields from . Note that it is not possible to write a table-valued method, although the names of these fields might suggest that it is possible. - -## Examples -The following example shows a UDT method that is attributed to indicate that the method will not be invoked on null instances of the type, that the method will not change the state of the type, and that the method will not be called when `null` parameters are supplied to the method invocation. - -[!code-csharp[SqlMethodAttribute Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/SqlMethod.cs#1)] - -]]> - - - - An attribute on a user-defined type (UDT), used to indicate the determinism and data access properties of a method or a property on a UDT. - To be added. - - - Indicates whether SQL Server should invoke the method on null instances. - if SQL Server should invoke the method on null instances; otherwise, . If the method cannot be invoked (because of an attribute on the method), the SQL Server is returned. - - - - - - Indicates whether a method on a user-defined type (UDT) is a mutator. - if the method is a mutator; otherwise . - - property is set to `true` and the return type of the method is `void`, SQL Server marks the method as a mutator. A mutator method is one that causes a state change in the UDT instance. Mutator methods can be called in assignment statements or data modification statements, but cannot be used in queries. If a method is marked as a mutator but does not return void, then CREATE TYPE does not fail with an error. Even though a returned value other than `void` does not raise an error, the returned value is not accessible and cannot be used. - -The default value of the property is `false`. - -A property can be a mutator if is used on the setter and is set to `true`. However, a property setter is implicitly treated as a mutator, so it is not necessary to set the property of the to `true`. - -]]> - - - - Indicates whether the method on a user-defined type (UDT) is called when input arguments are specified in the method invocation. - if the method is called when input arguments are specified in the method invocation; if the method returns a value when any of its input parameters are . If the method cannot be invoked (because of an attribute on the method), the SQL Server is returned. - - property is `true`. - -]]> - - - + + + + + Indicates the determinism and data access properties of a method or property on a user-defined type (UDT). The properties on the attribute reflect the physical characteristics that are used when the type is registered with SQL Server. + + + + For a property, the should be used on the setter or the getter directly. + + + inherits from a , so inherits the and fields from . Note that it is not possible to write a table-valued method, although the names of these fields might suggest that it is possible. + + + + + The following example shows a UDT method that is attributed to indicate that the method will not be invoked on null instances of the type, that the method will not change the state of the type, and that the method will not be called when parameters are supplied to the method invocation. + + + + using System; + using System.Data.SqlTypes; + using System.Text; + using Microsoft.SqlServer.Server; + + [Serializable] + [SqlUserDefinedType( + Format.Native, + IsByteOrdered = true, + Name = "Point", + ValidationMethodName = "ValidatePoint")] + public struct Point : INullable + { + private bool is_Null; + private int _x; + private int _y; + + // Distance from Point to the specified x and y values method. + [SqlMethod(OnNullCall = false, IsMutator = false, InvokeIfReceiverIsNull = false)] + public Double DistanceFromXY(int iX, int iY) + { + return Math.Sqrt(Math.Pow(iX - _x, 2.0) + Math.Pow(iY - _y, 2.0)); + } + } + + + + + + An attribute on a user-defined type (UDT), used to indicate the determinism and data access properties of a method or a property on a UDT. + + + + + Indicates whether SQL Server should invoke the method on null instances. + + + if SQL Server should invoke the method on null instances; otherwise, . If the method cannot be invoked (because of an attribute on the method), the SQL Server is returned. + + + The default value of the InvokeIfReceiverIsNull property is . That is, the method is not invoked on a null instance. If InvokeIfReceiverIsNull is , the return value of the method depends upon its type. If the return type of the method is nullable, the distinguished null value for the type is returned. If the return type is non-nullable, the default CLR value for the type is returned. The default value for reference types is . The default value for a value type is the value that is returned when you call the parameterless constructor for the type. + + + + + Indicates whether a method on a user-defined type (UDT) is a mutator. + + + if the method is a mutator; otherwise . + + + + If the property is set to and the return type of the method is , SQL Server marks the method as a mutator. A mutator method is one that causes a state change in the UDT instance. Mutator methods can be called in assignment statements or data modification statements, but cannot be used in queries. If a method is marked as a mutator but does not return void, then CREATE TYPE does not fail with an error. Even though a returned value other than does not raise an error, the returned value is not accessible and cannot be used. + + + The default value of the property is . + + + A property can be a mutator if is used on the setter and is set to . However, a property setter is implicitly treated as a mutator, so it is not necessary to set the property of the to . + + + + + + Indicates whether the method on a user-defined type (UDT) is called when input arguments are specified in the method invocation. + + + if the method is called when input arguments are specified in the method invocation; if the method returns a value when any of its input parameters are . If the method cannot be invoked (because of an attribute on the method), the SQL Server is returned. + + + The default value of the property is . + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.xml b/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.xml index a0a5eafe1b..432a475fd9 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.xml @@ -1,134 +1,209 @@ - - - - - Indicates that the type should be registered as a user-defined aggregate. The properties on the attribute reflect the physical attributes used when the type is registered with SQL Server. This class cannot be inherited. - - custom attribute. Every user-defined aggregate must be annotated with this attribute. - -See "CLR User-Defined Aggregates" in SQL Server 2005 Books Online for more information on user-defined aggregates and examples. - -## Examples -The following example shows the attribute for a user-defined aggregate. The aggregate uses custom serialization, has a maximum size of 8000 bytes when serialized, and is invariant to nulls, duplicates, and order. - -[!code-csharp[SqlUserDefinedAggregateAttribute Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/DataWorks_SqlUserDefinedAggregateAttribute_Sample.cs#1)] -[!code-vb[SqlUserDefinedAggregateAttribute Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/visualbasic/DataWorks_SqlUserDefinedAggregateAttribute_Sample.vb#1)] - -]]> - - - - One of the values representing the serialization format of the aggregate. - A required attribute on a user-defined aggregate, used to indicate that the given type is a user-defined aggregate and the storage format of the user-defined aggregate. - - - The serialization format as a . - A representing the serialization format. - - - - - - Indicates whether the aggregate is invariant to duplicates. - if the aggregate is invariant to duplicates; otherwise . - - - - - - Indicates whether the aggregate is invariant to nulls. - if the aggregate is invariant to nulls; otherwise . - - - - - - Indicates whether the aggregate is invariant to order. - if the aggregate is invariant to order; otherwise . - - - - - - Indicates whether the aggregate returns if no values have been accumulated. - if the aggregate returns if no values have been accumulated; otherwise . - - - - - - The maximum size, in bytes, of the aggregate instance. - An value representing the maximum size of the aggregate instance. - - property with the UserDefined serialization . - -The maximum allowed value for this property is specified by the field. - -The maximum size allowed is 2 gigabytes (GB). You can specify a number from 1 to 8000 bytes, or -1 to represent a value larger than 8000 bytes, up to 2 gigabytes. - -For an aggregate with user-defined serialization specified, refers to the total size of the serialized data. Consider an aggregate serializing a string of 10 characters (). When the string is serialized using a , the total size of the serialized string is 22 bytes: 2 bytes per Unicode UTF-16 character, multiplied by the maximum number of characters, plus 2 control bytes of overhead incurred from serializing a binary stream. So, when determining the value of , the total size of the serialized data must be considered: the size of the data serialized in binary form plus the overhead incurred by serialization. - -]]> - - - - The maximum size, in bytes, required to store the state of this aggregate instance during computation. - - value representing the maximum size of the aggregate instance. - -]]> - - - - The name of the aggregate. - A value representing the name of the aggregate. - - + + + + + Indicates that the type should be registered as a user-defined aggregate. The properties on the attribute reflect the physical attributes used when the type is registered with SQL Server. This class cannot be inherited. + + + + SQL Server creates a user-defined aggregate that is bound to the class definition that has the custom attribute. Every user-defined aggregate must be annotated with this attribute. + + + See "CLR User-Defined Aggregates" in SQL Server 2005 Books Online for more information on user-defined aggregates and examples. + + + + + The following example shows the attribute for a user-defined aggregate. The aggregate uses custom serialization, has a maximum size of 8000 bytes when serialized, and is invariant to nulls, duplicates, and order. + + + + using System; + using System.IO; + using Microsoft.SqlServer.Server; + + [Serializable] + [SqlUserDefinedAggregate( + Microsoft.SqlServer.Server.Format.UserDefined, + IsInvariantToNulls = true, + IsInvariantToDuplicates = false, + IsInvariantToOrder = false, + MaxByteSize = 8000)] + public class Concatenate : Microsoft.SqlServer.Server.IBinarySerialize + { + public void Read(BinaryReader r) + { + } + + public void Write(BinaryWriter w) + { + } + } + + + + Imports System.IO + Imports Microsoft.SqlServer.Server + + <Serializable(), SqlUserDefinedAggregate( _ + Microsoft.SqlServer.Server.Format.UserDefined, _ + IsInvariantToNulls:=True, _ + IsInvariantToDuplicates:=False, _ + IsInvariantToOrder:=False, _ + MaxByteSize:=8000)> _ + Public Class Concatenate + Implements Microsoft.SqlServer.Server.IBinarySerialize + + Public Sub Read(ByVal r As BinaryReader) Implements Microsoft.SqlServer.Server.IBinarySerialize.Read + + End Sub + + Public Sub Write(ByVal w As BinaryWriter) Implements Microsoft.SqlServer.Server.IBinarySerialize.Write + + End Sub + + + + + + One of the values representing the serialization format of the aggregate. + + + A required attribute on a user-defined aggregate, used to indicate that the given type is a user-defined aggregate and the storage format of the user-defined aggregate. + + + + + The serialization format as a . + + + A representing the serialization format. + + + + + [SqlUserDefinedAggregate(Format.Native)] + public class SampleAggregate + { + //... + } + + + + <SqlUserDefinedAggregate(Format.Native)> + Public Class SampleAggregate + '... + End Class + + + + + + Indicates whether the aggregate is invariant to duplicates. + + + if the aggregate is invariant to duplicates; otherwise . + + + + Used by the query processor, this property is if the aggregate is invariant to duplicates. That is, the aggregate of S, {X} is the same as aggregate of S when X is already in S. For example, aggregate functions such as MIN and MAX satisfy this property, while SUM does not. + + + Incorrectly setting this property can result in incorrect query results. This property is not an optimizer hint; it affects both the plan selected and the results returned by the query. + + + + + + Indicates whether the aggregate is invariant to nulls. + + + if the aggregate is invariant to nulls; otherwise . + + + + Used by the query processor, this property is if the aggregate is invariant to nulls. That is, the aggregate of S, {NULL} is the same as aggregate of S. For example, aggregate functions such as MIN and MAX satisfy this property, while COUNT(*) does not. + + + Incorrectly setting this property can result in incorrect query results. This property is not an optimizer hint; it affects the plan selected and the results returned by the query. + + + + + + Indicates whether the aggregate is invariant to order. + + + if the aggregate is invariant to order; otherwise . + + + + Reserved for future use. This property is not currently used by the query processor: order is currently not guaranteed. + + + Incorrectly setting this property can result in incorrect query results. This property is not an optimizer hint; it affects the plan selected and the results returned by the query. + + + The default value for this property is . + + + + + + Indicates whether the aggregate returns if no values have been accumulated. + + + if the aggregate returns if no values have been accumulated; otherwise . + + + + Used by the query processor, this property is if the aggregate returns if no values have been accumulated. + + + Incorrectly setting this property can result in incorrect query results. This property is not an optimizer hint; it affects the plan selected and the results returned by the query. + + + + + + The maximum size, in bytes, of the aggregate instance. + + + An value representing the maximum size of the aggregate instance. + + + + This property does not have to be specified for Native format serialization. + + + You must specify the property with the UserDefined serialization . + + + The maximum allowed value for this property is specified by the field. + + + The maximum size allowed is 2 gigabytes (GB). You can specify a number from 1 to 8000 bytes, or -1 to represent a value larger than 8000 bytes, up to 2 gigabytes. + + + For an aggregate with user-defined serialization specified, refers to the total size of the serialized data. Consider an aggregate serializing a string of 10 characters ( ). When the string is serialized using a , the total size of the serialized string is 22 bytes: 2 bytes per Unicode UTF-16 character, multiplied by the maximum number of characters, plus 2 control bytes of overhead incurred from serializing a binary stream. So, when determining the value of , the total size of the serialized data must be considered: the size of the data serialized in binary form plus the overhead incurred by serialization. + + + + + + The maximum size, in bytes, required to store the state of this aggregate instance during computation. + + + An value representing the maximum size of the aggregate instance. + + + + + The name of the aggregate. + + + A value representing the name of the aggregate. + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.xml b/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.xml index ffd70496cc..d383c39842 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.xml @@ -1,139 +1,170 @@ - - - - - Used to mark a type definition in an assembly as a user-defined type (UDT) in SQL Server. The properties on the attribute reflect the physical characteristics used when the type is registered with SQL Server. This class cannot be inherited. - - custom attribute. Every UDT must be annotated with this attribute. See [CLR User-Defined Types](https://go.microsoft.com/fwlink/?LinkId=128028) for more information about UDTs, including an example of a UDT. - -## Examples -The following example shows the `UserDefinedType` attribute of the Point UDT. The UDT is byte-ordered, is named "Point", has a validation method named "ValidatePoint", and uses the native serialization format. - -[!code-csharp[SqlUserDefinedTypeAttribute Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/csharp/DataWorks_SqlUserDefinedTypeAttribute_Sample.cs#1)] -[!code-vb[SqlUserDefinedTypeAttribute Samples#1](~/../sqlclient/doc/samples/Microsoft.SqlServer.Server/visualbasic/DataWorks_SqlUserDefinedTypeAttribute_Sample.vb#1)] - -]]> - - - - One of the values representing the serialization format of the type. - A required attribute on a user-defined type (UDT), used to confirm that the given type is a UDT and to indicate the storage format of the UDT. - - - - - - The serialization format as a . - A value representing the serialization format. - - - Indicates whether the user-defined type is byte ordered. - - if the user-defined type is byte ordered; otherwise . - - property in effect guarantees that the serialized binary data can be used for semantic ordering of the information. Thus, each instance of a byte-ordered UDT object can only have one serialized representation. When a comparison operation is performed in SQL Server on the serialized bytes, its results should be the same as if the same comparison operation had taken place in managed code. - -The following features are supported when is set to `true`: - -- The ability to create indexes on columns of this type. - -- The ability to create primary and foreign keys as well as CHECK and UNIQUE constraints on columns of this type. - -- The ability to use Transact-SQL ORDER BY, GROUP BY, and PARTITION BY clauses. In these cases, the binary representation of the type is used to determine the order. - -- The ability to use comparison operators in Transact-SQL statements. - -- The ability to persist computed columns of this type. - -Note that both the `Native` and `UserDefined` serialization formats support the following comparison operators when is set to `true`: - -- Equal to (=) - -- Not equal to (!=) - -- Greater than (>) - -- Less than (\<) - -- Greater than or equal to (>=) - -- Less than or equal to (<=) - -]]> - - - - Indicates whether all instances of this user-defined type are the same length. - - if all instances of this type are the same length; otherwise . - - - . This attribute is only relevant for UDTs with `UserDefined` serialization . - -]]> - - - - The maximum size of the instance, in bytes. - An value representing the maximum size of the instance. - - property with the `UserDefined` serialization . - -When connecting to SQL Server 2005 or earlier, must be between 1 and 8000. - -When connecting to SQL Server 2008 or later, set between 1 and 8000, for a type whose instances are always 8,000 bytes or less. For types that can have instances larger than 8000, specify -1. - -For a UDT with user-defined serialization specified, refers to the total size of the UDT in its serialized form as defined by the user. Consider a UDT with a property of a string of 10 characters (). When the UDT is serialized using a , the total size of the serialized string is 22 bytes: 2 bytes per Unicode UTF-16 character, multiplied by the maximum number of characters, plus 2 control bytes of overhead incurred from serializing a binary stream. So, when determining the value of , the total size of the serialized UDT must be considered: the size of the data serialized in binary form plus the overhead incurred by serialization. - -This property should not be used with `Native` serialization . - -]]> - - - - The SQL Server name of the user-defined type. - A value representing the SQL Server name of the user-defined type. - - property is not used within SQL Server, but is used by the Microsoft Visual Studio .NET Integrated Development Environment (IDE). - -]]> - - - - The name of the method used to validate instances of the user-defined type. - A representing the name of the method used to validate instances of the user-defined type. - - - - - + + + + + Used to mark a type definition in an assembly as a user-defined type (UDT) in SQL Server. The properties on the attribute reflect the physical characteristics used when the type is registered with SQL Server. This class cannot be inherited. + + + SQL Server creates a user-defined type that is bound to the type definition that has the custom attribute. Every UDT must be annotated with this attribute. See CLR User-Defined Typesfor more information about UDTs, including an example of a UDT. + + + + The following example shows the UserDefinedType attribute of the Point UDT. The UDT is byte-ordered, is named "Point", has a validation method named "ValidatePoint", and uses the native serialization format. + + + + [Serializable] + [Microsoft.SqlServer.Server.SqlUserDefinedType( + Format.Native, + IsByteOrdered=true, + Name="Point", + ValidationMethodName = "ValidatePoint")] + public struct Point : INullable + { + } + + + + <Serializable(), SqlUserDefinedTypeAttribute( _ + Format.Native, _ + IsByteOrdered:=True, _ + Name:="Point", _ + ValidationMethodName:="ValidatePoint")> _ + Public Structure Point + Implements INullable + End Structure + + + + + + One of the values representing the serialization format of the type. + + + A required attribute on a user-defined type (UDT), used to confirm that the given type is a UDT and to indicate the storage format of the UDT. + + + The following example specifies that the of the user-defined type is and the is 8000 bytes. + + + + + [SqlUserDefinedType(Format.Native, MaxByteSize=8000)] + public class SampleType + { + //... + } + + + + <SqlUserDefinedType(Format.Native, MaxByteSize:=8000)> + Public Class SampleType + '... + End Class + + + + + + The serialization format as a . + + + A value representing the serialization format. + + + + + Indicates whether the user-defined type is byte ordered. + + + if the user-defined type is byte ordered; otherwise . + + + + When set to , the property in effect guarantees that the serialized binary data can be used for semantic ordering of the information. Thus, each instance of a byte-ordered UDT object can only have one serialized representation. When a comparison operation is performed in SQL Server on the serialized bytes, its results should be the same as if the same comparison operation had taken place in managed code. + + + The following features are supported when is set to : + + + The ability to create indexes on columns of this type. + The ability to create primary and foreign keys as well as CHECK and UNIQUE constraints on columns of this type. + The ability to use Transact-SQL ORDER BY, GROUP BY, and PARTITION BY clauses. In these cases, the binary representation of the type is used to determine the order. + The ability to use comparison operators in Transact-SQL statements. + The ability to persist computed columns of this type. + + + Note that both the Native and UserDefined serialization formats support the following comparison operators when is set to : + + + Equal to (=) + Not equal to (!=) + Greater than (>) + Less than (<) + Greater than or equal to (>=) + Less than or equal to (<=) + + + + + + Indicates whether all instances of this user-defined type are the same length. + + + if all instances of this type are the same length; otherwise . + + + + If set to , all instances of UDTs corresponding to this common language runtime (CLR) type must have a length in bytes exactly equal to . This attribute is only relevant for UDTs with UserDefined serialization . + + + + + + The maximum size of the instance, in bytes. + + + An value representing the maximum size of the instance. + + + + You must specify the property with the UserDefined serialization . + + + When connecting to SQL Server 2005 or earlier, must be between 1 and 8000. + + + When connecting to SQL Server 2008 or later, set between 1 and 8000, for a type whose instances are always 8,000 bytes or fewer. For types that can have instances larger than 8000, specify -1. + + + For a UDT with user-defined serialization specified, refers to the total size of the UDT in its serialized form as defined by the user. Consider a UDT with a property of a string of 10 characters (). When the UDT is serialized using a , the total size of the serialized string is 22 bytes: 2 bytes per Unicode UTF-16 character, multiplied by the maximum number of characters, plus 2 control bytes of overhead incurred from serializing a binary stream. So, when determining the value of , the total size of the serialized UDT must be considered: the size of the data serialized in binary form plus the overhead incurred by serialization. + + + This property should not be used with Native serialization . + + + + + + The SQL Server name of the user-defined type. + + + A value representing the SQL Server name of the user-defined type. + + + The property is not used within SQL Server, but is used by the Microsoft Visual Studio .NET Integrated Development Environment (IDE). + + + + + The name of the method used to validate instances of the user-defined type. + + + A representing the name of the method used to validate instances of the user-defined type. + + + The method specified by this attribute validates instances of the UDT when the UDT has been deserialized from a binary value that is not trusted. + + + diff --git a/doc/snippets/Microsoft.SqlServer.Server/SystemDataAccessKind.xml b/doc/snippets/Microsoft.SqlServer.Server/SystemDataAccessKind.xml index 93f80783d0..f4feb5849d 100644 --- a/doc/snippets/Microsoft.SqlServer.Server/SystemDataAccessKind.xml +++ b/doc/snippets/Microsoft.SqlServer.Server/SystemDataAccessKind.xml @@ -1,26 +1,30 @@ - - - - - Describes the type of access to system data for a user-defined method or function. - - and to indicate what type of access to system data the method or function has. - -Note that methods and functions are not allowed to make changes to the database, so the options for this enumeration are `None` (meaning no data-access performed by the method or function) and `Read` (meaning that the method or function performs read-only data-access operations, such as executing SELECT statements). - - ]]> - - - - The method or function does not access system data. - - - The method or function reads system data. - - + + + + + Describes the type of access to system data for a user-defined method or function. + + + + Describes the type of access to system data for a user-defined method or function. + + + This enumeration is used in and to indicate what type of access to system data the method or function has. + + + Note that methods and functions are not allowed to make changes to the database, so the options for this enumeration are (meaning no data-access performed by the method or function) and (meaning that the method or function performs read-only data-access operations, such as executing SELECT statements). + + + + + + The method or function does not access system data. + + + + + The method or function reads system data. + + + diff --git a/eng/pipelines/common/templates/jobs/build-signed-akv-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-akv-package-job.yml new file mode 100644 index 0000000000..d0ad120b10 --- /dev/null +++ b/eng/pipelines/common/templates/jobs/build-signed-akv-package-job.yml @@ -0,0 +1,70 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: symbolsFolder + type: string + default: symbols + + - name: softwareFolder + type: string + default: software + + - name: publishSymbols + type: boolean + +jobs: +- job: build_signed_akv_package + displayName: 'Build Signed AKV Provider Package' + pool: + type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs + + variables: + - template: ../../../libraries/variables.yml@self + + steps: + - script: SET + displayName: 'Print Environment Variables' + + - template: ../steps/build-all-configurations-signed-dlls-step.yml@self + parameters: + product: AKV + packageRefMdsVersion: $(MDS_PackageRef_Version) + AssemblyFileVersion: $(AKVAssemblyFileVersion) + + - template: ../steps/code-analyze-step.yml@self + parameters: + analyzeType: all + product: AKV + packageRefMdsVersion: $(MDS_PackageRef_Version) + + - template: ../steps/esrp-code-signing-step.yml@self + parameters: + artifactType: dll + + - template: ../steps/generate-nuget-package-step.yml@self + parameters: + OutputDirectory: $(artifactDirectory) + nuspecPath: ${{variables.akvNuspecPath }} + NugetPackageVersion: ${{variables.AKVNuGetPackageVersion }} + referenceType: package + + - template: ../steps/esrp-code-signing-step.yml@self + parameters: + artifactType: pkg + + - template: ../steps/copy-dlls-for-test-step.yml@self + parameters: + product: AKV + referenceType: package + + # Publish symbols to servers + - template: ../steps/publish-symbols-step.yml@self + parameters: + referenceType: package + symbolsVersion: ${{variables.AKVNuGetPackageVersion }} + product: AKV + publishSymbols: ${{ parameters['PublishSymbols'] }} + symbolsArtifactName: akv_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_$(NuGetPackageVersion)_$(System.TimelineId) diff --git a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml new file mode 100644 index 0000000000..adb092342a --- /dev/null +++ b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml @@ -0,0 +1,63 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: symbolsFolder + type: string + default: symbols + + - name: softwareFolder + type: string + default: software + + - name: publishSymbols + type: boolean + + - name: isPreview + type: boolean + +jobs: +- job: build_signed_package + displayName: 'Build Signed MDS Package' + pool: + type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs + + variables: + - template: ../../../libraries/variables.yml@self + - ${{ if parameters.isPreview }}: + - name: NugetPackageVersion + value: $(PreviewNugetPackageVersion) + + steps: + - script: SET + displayName: 'Print Environment Variables' + + - template: ../steps/build-all-configurations-signed-dlls-step.yml@self + + - template: ../steps/code-analyze-step.yml@self + parameters: + analyzeType: all + + - template: ../steps/esrp-code-signing-step.yml@self + parameters: + artifactType: dll + + - template: ../steps/generate-nuget-package-step.yml@self + parameters: + OutputDirectory: $(artifactDirectory) + + - template: ../steps/esrp-code-signing-step.yml@self + parameters: + artifactType: pkg + + - template: ../steps/copy-dlls-for-test-step.yml@self + parameters: + product: MDS + + # Publish symbols to servers + - template: ../steps/publish-symbols-step.yml@self + parameters: + publishSymbols: ${{ parameters['PublishSymbols'] }} + symbolsArtifactName: mds_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_$(NuGetPackageVersion)_$(System.TimelineId) diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml new file mode 100644 index 0000000000..cb3790262c --- /dev/null +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -0,0 +1,77 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: poolName + type: string + default: $(ci_var_defaultPoolName) + + - name: imageOverride + type: string + default: ADO-MMS22-SQL19 + + - name: artifactName + type: string + default: Artifacts + + - name: platform + type: string + default: $(Platform) + + - name: configuration + type: string + default: $(Configuration) + + - name: prebuildSteps + type: stepList + default: [] + +jobs: +- job: build_nugets + + pool: + name: ${{parameters.poolName }} + demands: + - imageOverride -equals ${{ parameters.imageOverride }} + - msbuild + + variables: + - template: ../../../libraries/ci-build-variables.yml@self + + steps: + - ${{ if ne(parameters.prebuildSteps, '') }}: + - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration + + - template: ../steps/ci-project-build-step.yml@self + parameters: + platform: ${{ parameters.platform }} + configuration: ${{ parameters.configuration }} + operatingSystem: Windows + build: all + + - template: ../steps/generate-nuget-package-step.yml@self + parameters: + NugetPackageVersion: $(NugetPackageVersion) + configuration: $(Configuration) + nuspecPath: 'tools/specs/Microsoft.Data.SqlClient.nuspec' + OutputDirectory: $(packagePath) + generateSymbolsPackage: false + displayName: 'Generate NuGet package M.D.SqlClient' + + - template: ../steps/generate-nuget-package-step.yml@self + parameters: + NugetPackageVersion: $(NugetPackageVersion) + configuration: $(Configuration) + nuspecPath: 'tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec' + OutputDirectory: $(packagePath) + generateSymbolsPackage: false + installNuget: false + displayName: 'Generate NuGet package AKV Provider' + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: Artifacts' + inputs: + PathtoPublish: $(packagePath) + ArtifactName: ${{ parameters.artifactName }} diff --git a/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml new file mode 100644 index 0000000000..abf67e315a --- /dev/null +++ b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml @@ -0,0 +1,122 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: upload + type: string + default: $(ci_var_uploadTestResult) + + - name: poolName + type: string + default: $(defaultHostedPoolName) + + - name: image + type: string + default: 'windows-2022' + + - name: downloadArtifactsSteps + type: stepList + default: [] + +jobs: +- job: CodeCoverage + displayName: 'Merge Code Coverage' + + variables: + uploadTestResult: ${{ parameters.upload }} + + pool: + name: '${{ parameters.poolName }}' + vmImage: ${{ parameters.image }} + + steps: + - ${{if eq(parameters.debug, true)}}: + - powershell: | + Get-ChildItem env: | Sort-Object Name + displayName: 'List Environment Variables [debug]' + + - task: NuGetAuthenticate@1 + displayName: 'NuGet Authenticate' + + - task: UseDotNet@2 + displayName: 'Use .NET SDK 7.0.x' + inputs: + version: 7.0.x + + - ${{ parameters.downloadArtifactsSteps }} + + - ${{ if eq(parameters.debug, true)}}: + - powershell: | + Get-ChildItem $(Build.SourcesDirectory)\coverageNetFx\ -Recurse -File -Filter *.coverage + displayName: 'List coverageNetFx files [debug]' + + - powershell: | + Get-ChildItem $(Build.SourcesDirectory)\coverageNetCore\ -Recurse -File -Filter *.coverage + displayName: 'List coverageNetCore files [debug]' + + - powershell: | + dotnet tool install --global dotnet-coverage + + $files = Get-ChildItem $(Build.SourcesDirectory)\coverageNetFx\ -Recurse -File -Filter *.coverage + # echo $files + mkdir coverageNetFxXml + $counter=0 + foreach ($file in $files) { + & dotnet-coverage merge $file.FullName --output coverageNetFxXml\$((++$counter)).coveragexml --output-format xml + } + + $files = Get-ChildItem $(Build.SourcesDirectory)\coverageNetCore\ -Recurse -File -Filter *.coverage + # echo $files + mkdir coverageNetCoreXml + $counter=0 + foreach ($file in $files) { + & dotnet-coverage merge $file.FullName --output coverageNetCoreXml\$((++$counter)).coveragexml --output-format xml + } + + # dir coverageNetFxXml\ + # dir coverageNetCoreXml\ + + Write-Host "Clean up disk ... [removing coverageNetFx & coverageNetCore]" + + Remove-Item $(Build.SourcesDirectory)\coverageNetFx -Recurse -Force + Remove-Item $(Build.SourcesDirectory)\coverageNetCore -Recurse -Force + + displayName: 'Convert coverage files to xml' + + - ${{ if eq(parameters.debug, true)}}: + - powershell: | + dir coverageNetFxXml\ + dir coverageNetCoreXml\ + displayName: 'List converted files [debug]' + + - script: | + dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools + + tools\reportgenerator "-reports:coverageNetFxXml\*.coveragexml" "-targetdir:coveragereportNetFx" "-reporttypes:Cobertura;" "-assemblyfilters:+microsoft.data.sqlclient.dll" "-sourcedirs:$(Build.SourcesDirectory)\src\Microsoft.Data.SqlClient\netfx\src;$(Build.SourcesDirectory)\src\Microsoft.Data.SqlClient\src" "-classfilters:+Microsoft.Data.*" + + tools\reportgenerator "-reports:coverageNetCoreXml\*.coveragexml" "-targetdir:coveragereportAddOns" "-reporttypes:Cobertura;" "-assemblyfilters:+microsoft.data.sqlclient.alwaysencrypted.azurekeyvaultprovider.dll" "-sourcedirs:$(Build.SourcesDirectory)\src\Microsoft.Data.SqlClient\add-ons\AzureKeyVaultProvider" "-classfilters:+Microsoft.Data.*" + + tools\reportgenerator "-reports:coverageNetCoreXml\*.coveragexml" "-targetdir:coveragereportNetCore" "-reporttypes:Cobertura;" "-assemblyfilters:+microsoft.data.sqlclient.dll" "-sourcedirs:$(Build.SourcesDirectory)\src\Microsoft.Data.SqlClient\netcore\src;$(Build.SourcesDirectory)\src\Microsoft.Data.SqlClient\src" "-classfilters:+Microsoft.Data.*" + displayName: 'Run ReportGenerator' + + - task: PublishCodeCoverageResults@2 + displayName: 'Publish code coverage from netcore' + inputs: + summaryFileLocation: '*\Cobertura.xml' + + - powershell: | + #download Codecov CLI + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -Uri https://cli.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe + + ./codecov --verbose upload-process --fail-on-error -t $(CODECOV_TOKEN) -f "coveragereportNetFx\Cobertura.xml" -F netfx + ./codecov --verbose upload-process --fail-on-error -t $(CODECOV_TOKEN) -f "coveragereportNetCore\Cobertura.xml" -F netcore + ./codecov --verbose upload-process --fail-on-error -t $(CODECOV_TOKEN) -f "coveragereportAddOns\Cobertura.xml" -F addons + displayName: 'Upload to CodeCov' + condition: and(succeeded(), eq(variables['uploadTestResult'], 'true')) diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml new file mode 100644 index 0000000000..4aaba4c71e --- /dev/null +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -0,0 +1,248 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: poolName + type: string + + - name: hostedPool + type: boolean + default: false + + - name: image + type: string + + - name: jobDisplayName + type: string + + - name: usemanagedSNI + type: boolean + default: false + + - name: configProperties + type: object + default: {} # - key: 'value' + + - name: prebuildSteps + type: stepList + default: [] + + - name: artifactName + type: string + default: Artifacts + + - name: targetFramework + type: string + + - name: enableX86Test + type: boolean + default: false + + - name: testSet + type: string + + - name: publishTestResults + type: boolean + default: false + + - name: configSqlFor + type: string # local, azure, or enclave + default: local + + - name: operatingSystem + type: string + default: '' + + - name: buildType + displayName: 'Build Type' + default: Project + values: + - Project + - Package + +jobs: +- job: ${{ format('{0}', coalesce(parameters.jobDisplayName, parameters.image, 'unknown_image')) }} + + pool: + name: '${{ parameters.poolName }}' + ${{ if eq(parameters.hostedPool, true) }}: + vmImage: ${{ parameters.image }} + ${{ else }}: + demands: + - imageOverride -equals ${{ parameters.image }} + + variables: + - name: dotnetx86RootPath + value: '$(dotnetx86Path)' + + steps: + - ${{ if ne(parameters.prebuildSteps, '') }}: + - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration + + - ${{ if ne(parameters.configProperties, '{}') }}: + - template: ../steps/update-config-file-step.yml@self # update config.json file + parameters: + debug: ${{ parameters.debug }} + UseManagedSNIOnWindows: ${{ parameters.usemanagedSNI }} + ${{ if parameters.configProperties.TCPConnectionString }}: + TCPConnectionString: ${{ parameters.configProperties.TCPConnectionString }} + ${{ if parameters.configProperties.NPConnectionString }}: + NPConnectionString: ${{ parameters.configProperties.NPConnectionString }} + ${{ if parameters.configProperties.AADAuthorityURL }}: + AADAuthorityURL: ${{ parameters.configProperties.AADAuthorityURL }} + ${{ if parameters.configProperties.TCPConnectionStringHGSVBS }}: + TCPConnectionStringHGSVBS: ${{ parameters.configProperties.TCPConnectionStringHGSVBS }} + ${{ if parameters.configProperties.TCPConnectionStringNoneVBS }}: + TCPConnectionStringNoneVBS: ${{ parameters.configProperties.TCPConnectionStringNoneVBS }} + ${{ if parameters.configProperties.TCPConnectionStringAASSGX }}: + TCPConnectionStringAASSGX: ${{ parameters.configProperties.TCPConnectionStringAASSGX }} + ${{ if parameters.configProperties.EnclaveEnabled }}: + EnclaveEnabled: ${{ eq(parameters.configProperties.EnclaveEnabled, 'true') }} + ${{ if parameters.configProperties.TracingEnabled }}: + TracingEnabled: ${{ eq(parameters.configProperties.TracingEnabled, 'true') }} + ${{ if parameters.configProperties.AADPasswordConnectionString }}: + AADPasswordConnectionString: ${{ parameters.configProperties.AADPasswordConnectionString }} + ${{ if parameters.configProperties.AADServicePrincipalId }}: + AADServicePrincipalId: ${{ parameters.configProperties.AADServicePrincipalId }} + ${{ if parameters.configProperties.AADServicePrincipalSecret }}: + AADServicePrincipalSecret: ${{ parameters.configProperties.AADServicePrincipalSecret }} + ${{ if parameters.configProperties.AzureKeyVaultUrl }}: + AzureKeyVaultUrl: ${{ parameters.configProperties.AzureKeyVaultUrl }} + ${{ if parameters.configProperties.AzureKeyVaultTenantId }}: + AzureKeyVaultTenantId: ${{ parameters.configProperties.AzureKeyVaultTenantId }} + ${{ if parameters.configProperties.UserManagedIdentityClientId }}: + UserManagedIdentityClientId: ${{ parameters.configProperties.UserManagedIdentityClientId }} + ${{ if parameters.configProperties.FileStreamDirectory }}: + FileStreamDirectory: ${{ parameters.configProperties.FileStreamDirectory }} + ${{ if parameters.configProperties.LocalDbAppName }}: + LocalDbAppName: ${{ parameters.configProperties.LocalDbAppName }} + ${{ if parameters.configProperties.LocalDbSharedInstanceName }}: + LocalDbSharedInstanceName: ${{ parameters.configProperties.LocalDbSharedInstanceName }} + ${{ if parameters.configProperties.AliasName }}: + AliasName: ${{ parameters.configProperties.AliasName }} + ${{ if parameters.configProperties.SupportsIntegratedSecurity }}: + SupportsIntegratedSecurity: ${{ eq(parameters.configProperties.SupportsIntegratedSecurity, 'true') }} + ${{ if parameters.configProperties.SupportsFileStream }}: + SupportsFileStream: ${{ eq(parameters.configProperties.SupportsFileStream, 'true') }} + ${{ if parameters.configProperties.DNSCachingConnString }}: + DNSCachingConnString: ${{ parameters.configProperties.DNSCachingConnString }} + ${{ if parameters.configProperties.DNSCachingServerCR }}: + DNSCachingServerCR: ${{ parameters.configProperties.DNSCachingServerCR }} + ${{ if parameters.configProperties.DNSCachingServerTR }}: + DNSCachingServerTR: ${{ parameters.configProperties.DNSCachingServerTR }} + ${{ if parameters.configProperties.EnclaveAzureDatabaseConnString }}: + EnclaveAzureDatabaseConnString: ${{ parameters.configProperties.EnclaveAzureDatabaseConnString }} + ${{ if parameters.configProperties.IsDNSCachingSupportedCR }}: + IsDNSCachingSupportedCR: ${{ eq(parameters.configProperties.IsDNSCachingSupportedCR, 'true') }} + ${{ if parameters.configProperties.IsDNSCachingSupportedTR }}: + IsDNSCachingSupportedTR: ${{ eq(parameters.configProperties.IsDNSCachingSupportedTR, 'true') }} + ${{ if parameters.configProperties.IsAzureSynapse }}: + IsAzureSynapse: ${{ eq(parameters.configProperties.IsAzureSynapse, 'true') }} + ${{ if parameters.configProperties.ManagedIdentitySupported }}: + ManagedIdentitySupported: ${{ eq(parameters.configProperties.ManagedIdentitySupported, 'true') }} + + - ${{ if and(eq(parameters.configSqlFor, 'azure'), eq(parameters.operatingSystem, 'Windows')) }}: + - powershell: | + # Try to start the SQL Browser service, if it exists + $svc_name = "SQLBrowser" + if ((Get-Service -Name "$svc_name" -ErrorAction SilentlyContinue) -ne $null) { + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + Set-Service -StartupType Automatic $svc_name + net start $svc_name + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + } + + displayName: 'Start Sql Browser' + condition: eq(variables['Agent.OS'], 'Windows_NT') + - ${{ elseif eq(parameters.configSqlFor, 'local') }}: + - template: ../steps/configure-sql-server-step.yml@self # configure SQL Server + parameters: + operatingSystem: ${{ parameters.operatingSystem }} + ${{ if parameters.configProperties.instanceName }}: + instanceName: ${{ parameters.configProperties.instanceName }} + ${{ if parameters.configProperties.user }}: + user: ${{ parameters.configProperties.user }} + ${{ if parameters.configProperties.saUser }}: + saUser: ${{ parameters.configProperties.saUser }} + ${{ if parameters.configProperties.password }}: + password: ${{ parameters.configProperties.password }} + ${{ if parameters.configProperties.SQLRootPath }}: + SQLRootPath: ${{ parameters.configProperties.SQLRootPath }} + ${{ if parameters.configProperties.x64AliasRegistryPath }}: + x64AliasRegistryPath: ${{ parameters.configProperties.x64AliasRegistryPath }} + ${{ if parameters.configProperties.x86AliasRegistryPath }}: + x86AliasRegistryPath: ${{ parameters.configProperties.x86AliasRegistryPath }} + ${{ if parameters.configProperties.SQLAliasName }}: + SQLAliasName: ${{ parameters.configProperties.SQLAliasName }} + ${{ if parameters.configProperties.SQLAliasPort }}: + SQLAliasPort: ${{ parameters.configProperties.SQLAliasPort }} + ${{ if parameters.configProperties.targetNetCoreVersion }}: + targetNetCoreVersion: ${{ parameters.configProperties.targetNetCoreVersion }} + ${{ if parameters.configProperties.databaseName }}: + databaseName: ${{ parameters.configProperties.databaseName }} + ${{ if parameters.configProperties.enableLocalDB }}: + enableLocalDB: ${{ parameters.configProperties.enableLocalDB }} + ${{ if parameters.configProperties.localDbAppName }}: + LocalDbAppName: ${{ parameters.configProperties.localDbAppName }} + ${{ if parameters.configProperties.localDbSharedInstanceName }}: + LocalDbSharedInstanceName: ${{ parameters.configProperties.localDbSharedInstanceName }} + ${{ if parameters.configProperties.FileStreamDirectory }}: + fileStreamDirectory: ${{ parameters.configProperties.FileStreamDirectory }} + + - template: ../steps/build-all-tests-step.yml@self # build tests + parameters: + targetFramework: ${{ parameters.targetFramework }} + referenceType: ${{ parameters.buildType }} + testSet: ${{ parameters.testSet }} + ${{ if ne(parameters.operatingSystem, 'Windows') }}: + OSGroup: Unix + + - template: ../steps/run-all-tests-step.yml@self # run tests + parameters: + debug: ${{ parameters.debug }} + targetFramework: ${{ parameters.targetFramework }} + referenceType: ${{ parameters.buildType }} + testSet: ${{ parameters.testSet }} + operatingSystem: ${{ parameters.operatingSystem }} + + - ${{ if and(eq(parameters.enableX86Test, true), eq(parameters.operatingSystem, 'Windows')) }}: # run x86 tests + - powershell: | + dotnet --info + + Invoke-WebRequest https://dot.net/v1/dotnet-install.ps1 -OutFile dotnet-install.ps1 + + # install .net x86 + $version = "LTS" + if (!"${{parameters.targetFramework }}".StartsWith("net4")) + { + $version = "${{parameters.targetFramework }}".Substring(3, "${{parameters.targetFramework }}".Length-3) + } + + .\dotnet-install.ps1 -Channel $version -Architecture x86 -InstallDir "$(dotnetx86RootPath)" + + $(dotnetx86RootPath)dotnet.exe --info + displayName: 'Install .NET x86 ' + condition: ne(variables['dotnetx86RootPath'], '') + + - template: ../steps/run-all-tests-step.yml@self + parameters: + debug: ${{ parameters.debug }} + targetFramework: ${{ parameters.targetFramework }} + referenceType: ${{ parameters.buildType }} + testSet: ${{ parameters.testSet }} + msbuildArchitecture: x86 + dotnetx86RootPath: $(dotnetx86RootPath) + operatingSystem: ${{ parameters.operatingSystem }} + + - ${{ if and(eq(parameters.publishTestResults, true), eq(parameters.buildType, 'Project')) }}: # publish test results if build type is project + - template: ../steps/publish-test-results-step.yml@self + parameters: + debug: ${{ parameters.debug }} + targetFramework: ${{ parameters.targetFramework }} + operatingSystem: ${{ parameters.operatingSystem }} diff --git a/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml new file mode 100644 index 0000000000..e729aaea46 --- /dev/null +++ b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml @@ -0,0 +1,68 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: downloadPackageStep + type: step + default: + script: echo + + - name: packageFolderName + type: string + default: drop_build_build_signed_package + + - name: dependsOn + type: string + default: empty + + - name: isPreview + type: boolean + +jobs: +- job: run_tests_package_reference + displayName: 'Run tests with package reference' + ${{ if ne(parameters.dependsOn, 'empty')}}: + dependsOn: '${{parameters.dependsOn }}' + pool: + type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs + isCustom: true + name: ADO-1ES-Pool + vmImage: 'ADO-MMS22-SQL19' + + variables: # More settings at https://aka.ms/obpipelines/yaml/jobs + - template: ../../../libraries/mds-validation-variables.yml@self + + steps: + - template: ../steps/pre-build-step.yml + + - ${{parameters.downloadPackageStep }} + + - template: ../steps/update-nuget-config-local-feed-step.yml + parameters: + downloadedNugetPath: $(Pipeline.Workspace)\${{parameters.packageFolderName }} + ${{ if parameters.isPreview }}: + nugetPackageVersion: $(PreviewNugetPackageVersion) + + - template: ../steps/update-config-file-step.yml + parameters: + TCPConnectionString: $(SQL_TCP_CONN_STRING) + NPConnectionString: $(SQL_NP_CONN_STRING) + SupportsIntegratedSecurity: false + + - template: ../steps/prepare-test-db-step.yml + +# build & test + - template: ../steps/build-and-run-tests-netfx-step.yml + parameters: + referenceType: Package + ${{ if parameters.isPreview }}: + nugetPackageVersion: $(PreviewNugetPackageVersion) + + - template: ../steps/build-and-run-tests-netcore-step.yml + parameters: + referenceType: Package + cleanFirst: true + ${{ if parameters.isPreview }}: + nugetPackageVersion: $(PreviewNugetPackageVersion) diff --git a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml new file mode 100644 index 0000000000..286e9ffa75 --- /dev/null +++ b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml @@ -0,0 +1,349 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: downloadPackageStep + type: step + default: + script: echo + + - name: packageFolderName + type: string + default: drop_build_build_signed_package + + - name: dependsOn + type: string + default: '' + + - name: packageType + type: string + default: both + values: + - dll + - pdb + - both + + - name: assembly_file_version_netfx + type: string + default: $(AssemblyFileVersion) + + - name: assembly_file_version_core + type: string + default: $(AssemblyFileVersion) + + - name: isPreview + type: boolean + +jobs: +- job: validate_signed_package + displayName: 'Verify signed package' + ${{ if ne(parameters.dependsOn, '')}}: + dependsOn: '${{parameters.dependsOn }}' + pool: + type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs + isCustom: true + name: ADO-1ES-Pool + vmImage: 'ADO-MMS22-SQL19' + + variables: # More settings at https://aka.ms/obpipelines/yaml/jobs + - template: ../../../libraries/mds-validation-variables.yml@self + + - name: pathToDownloadedNuget # path to the downloaded nuget files + value: $(Pipeline.Workspace)\${{parameters.packageFolderName }} + + - name: ProductVersion #MDS product version (MDS validation) + value: $(NugetPackageVersion) + + - ${{ if parameters.isPreview }}: + - name: extractedNugetPath + value: $(extractedNugetRootPath).$(PreviewNugetPackageVersion) + - name: NugetPackageVersion + value: $(PreviewNugetPackageVersion) + - name: ProductVersion + value: $(PreviewNugetPackageVersion) + + steps: + - script: SET + displayName: 'Print Environment Variables' + + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet ' + + - powershell: | + #Sets Variables for AssemblyFileVersion, AssemblyVersion and NugetPackageVersion + + [Xml] $versionprops = Get-Content -Path ".\tools\props\Versions.props" + Write-Host $versionprops.Project.PropertyGroup[0].AssemblyFileVersion + + $AssemblyVersion = $versionprops.Project.PropertyGroup[0].AssemblyVersion + + Write-Host "##vso[task.setvariable variable=ASSEMBLY_VERSION;]$AssemblyVersion" + displayName: 'Update assembly version property' + + - powershell: | + # Displays the paths of all the local cache directories + nuget locals all -List + + #Clears all files from all local cache directories + nuget locals all -Clear + displayName: 'Clear local cache' + + - ${{parameters.downloadPackageStep }} + + - powershell: | + # Install nuget package + Install-Package -Name "Microsoft.Data.SqlClient" -Destination "$(TempFolderName)" -Force -Source $(pathToDownloadedNuget) -SkipDependencies + + Write-Host "--------------------------------------------------" + Write-Host '$(TempFolderName)' + ls $(TempFolderName) + Write-Host "--------------------------------------------------" + displayName: 'Extract Nuget in temp folder' + + - powershell: | + # Artifact is stored in the Nuget folder + $packageType = '${{parameters.packageType}}' + + Write-Host "--------------------------------------------------" + Write-Host "This will verify the artifact signature" -ForegroundColor Green + Write-Host "--------------------------------------------------" + + if ($packageType -eq 'dll' -or $packageType -eq 'both') + { + nuget verify -All $(pathToDownloadedNuget)\*.nupkg + } + if ($packageType -eq 'pdb' -or $packageType -eq 'both') + { + nuget verify -All $(pathToDownloadedNuget)\*.snupkg + } + displayName: 'Verify nuget signature' + + - powershell: | + if($env:CDP_BUILD_TYPE -eq 'Official') + { + # Recursively find all .dll files in TempFolder (installed nuget folder) + # Microsoft.Data.SqlClient.dll and Microsoft.Data.SqlClient.resources.dll (in localized folders) should have strong name + $dllFiles = Get-ChildItem -Path $(TempFolderName) -Recurse -Filter *.dll + $badDlls = @() + foreach ($file in $dllFiles) + { + # Run sn.k to verify the strong name on each dll + $result = & "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe" -vf $file.FullName + Write-OutPut $result + + # if thhe dll is not valid, it would be delay signed or test-signed which is not meant for production + if($result[$result.Length-1] -notlike "* is valid") + { + $badDlls += $result[$result.Length-1] + } + } + if($badDlls.Count -gt 0) + { + Write-OutPut "Error: Invalid dlls are detected. Chek below list:" + foreach($dll in $badDlls) + { + Write-Output $dll + } + Exit -1 + } + Write-Host "Strong name has been verified for all dlls" + } + else + { + Write-OutPut "Strong name verification is not required for non-official builds" + } + displayName: 'Verify strong name is generated for production' + + - powershell: | + # Checks the expected folder names such as lib, ref, runtimes + Get-ChildItem -Path $(extractedNugetPath) -Directory | select Name | foreach { + if('$(expectedFolderNames)'.contains($_.Name)){ + Write-Host expected folder name verfied: $_.Name + } + } + displayName: 'Check expected folder names' + + - powershell: | + # Checks the version of DotNetFramework and DotNet + $countErr = 0 + $countPass = 0 + $excludNamesFromRuntimeFolder = 'lib','win','unix' + + Get-ChildItem -Path $(extractedNugetPath) -Directory | foreach { + $parentname=$_.Name + Write-Host $_.FullName -ForegroundColor yellow + + if($_.Name -ne 'runtimes') { + Get-ChildItem -Path $_.FullName -Directory | select Name | foreach { + if('$(expectedDotnetVersions)'.Contains($_.Name)){ + Write-Host "`tExpected version verified in $parentname": $_.Name -ForegroundColor green + $countPass += 1 + } + else{ + Write-Host "`tUnexpected version detected in $parentname": $_.Name + $countErr += 1 + } + } + } + + elseif ($_.Name -eq 'runtimes'){ + Get-ChildItem -Depth 3 -Path $_.FullName -Exclude $excludNamesFromRuntimeFolder -Directory | foreach{ + if('$(expectedDotnetVersions)'.Contains($_.Name)){ + Write-Host "`tExpected version verfied in $parentname": $_.Name + $countPass += 1 + } + else{ + Write-Host "`tUnexpected version detected": $_.Name -ForegroundColor Red + $countErr += 1 + } + } + } + else{ + Write-Host "`tUnknown folder " $_.Name -ForegroundColor Red + Exit -1 + } + } + + Write-Host "_______________" + Write-Host "Expected: $countPass" + Write-Host "Unexpected: $countErr" + Write-Host "_______________" + if ($countErr -ne 0) + { + Write-Host "Unexpected versions are detected!" -ForegroundColor Red + Exit -1 + } + displayName: 'Check Expected framework' + + - powershell: | + # list all the child items of created temp folder + + #Verify all DLLs unzipped match "expected" hierarchy + + foreach( $folderName in (Get-ChildItem -Path $(extractedNugetPath) -Directory).Name) + { + # List all Childerns of the Path + Get-ChildItem -Path $(extractedNugetPath)\$folderName -Recurse -File + $subFiles = Get-ChildItem -Path $(extractedNugetPath)\$folderName -Recurse -File + + foreach($file in $subFiles) + { + if($subFiles[0].Name -like "*.dll" ) + { + Write-Host $subFiles[0].Name -ForegroundColor Green + Write-Host $subFiles[1].Name -ForegroundColor Green + if(($folderName -eq 'lib') -or ($folderName -eq 'ref')) + { + if($subFiles[2].Name -like "*.dll") + { + Write-Host $subFiles[2].Name -ForegroundColor Green + } + else + { + $subFiles[2].Name + Write-Host "Expected file pattern for localization did not match to *.dll" -ForegroundColor Red + Exit -1 + } + } + } + else + { + $subFiles[0].Name + $subFiles[1].Name + Write-Host "Expected file pattern did not match to *.dll" -ForegroundColor Red + Exit -1 + } + } + } + displayName: 'Verify all DLLs unzipped match "expected" hierarchy' + - powershell: | + # Verify all dlls status are Valid + + $dlls = Get-ChildItem -Path $(extractedNugetPath) -Recurse -Include *.dll + foreach ($status in $dlls | Get-AuthenticodeSignature) + { + if ($status.Status -eq "Valid") + { + Write-Host $status.Status $status.Path + } + else + { + Write-Host "dll status of '$status.Path' is not valid!" -ForegroundColor Red + $status + Exit -1 + } + } + displayName: 'Verify all dlls status are Valid' + + - powershell: | + # This will check for ProductVersion and FileVersion + # For NetFx we have a different FileVersion, but product versions are all the same some may have and extra numbering at the end. we only check for # first parts + + foreach ( $pVersion in Get-ChildItem *.dll -Path $(extractedNugetPath) -Recurse | ForEach-Object versioninfo ) + { + if ($pVersion.ProductVersion -Like '$(ProductVersion)*') + { + Write-Host Valid Product Version:"$pVersion.ProductVersion" $pVersion.ProductVersion detected for $pVersion.FileName -ForegroundColor Green + } + else + { + Write-Host "Wrong ProductVersion detected. Expected: '$(ProductVersion)', but Detected: "$pVersion.ProductVersion"" + Exit -1 + } + + if($pVersion.FileName -like '*lib\$(CurrentNetFxVersion)*'){ + + if($pVersion.FileVersion -eq '${{parameters.assembly_file_version_netfx }}') + { + Write-Host 'Correct File version Detected for net46,' $pVersion.FileVersion -ForegroundColor Green + } + else + { + Write-Host 'Wrong File version Detected for net46,' $pVersion.FileVersion -ForegroundColor Red + Exit -1 + } + } + else + { + + if($pVersion.FileVersion -eq '${{parameters.assembly_file_version_core}}') + { + Write-Host 'Correct File version Detected for netcore,' $pVersion.FileVersion -ForegroundColor Green + } + else + { + Write-Host 'Wrong File version Detected for netcore and ref folder,' $pVersion.FileVersion -ForegroundColor Red + Exit -1 + } + } + } + + Get-ChildItem *.dll -Path $(extractedNugetPath) -Recurse | ForEach-Object versioninfo + displayName: 'Verify "File Version" matches provided pipeline variable "ASSEMBLY_FILE_VERSION" for DLLs' + + - powershell: | + #Change TestMicrosoftDataSqlClientVersion + + [Xml] $versionprops = Get-Content -Path "tools/props/Versions.props" + $versionpropspath = "tools\props\Versions.props" + $versionprops.Project.PropertyGroup[$versionprops.Project.PropertyGroup.Count-1].TestMicrosoftDataSqlClientVersion ="$(NugetPackageVersion)" + Write-Host "Saving Test nuget version at $rootfolder\props ...." -ForegroundColor Green + $versionprops.Save($versionpropspath) + + displayName: 'Modify TestMicrosoftDataSqlClientVersion' + + - powershell: | + #Change TestMicrosoftDataSqlClientVersion + + [Xml] $versionprops = Get-Content -Path "tools/props/Versions.props" + $AssemblyFileVersion = $versionprops.Project.PropertyGroup[0].AssemblyFileVersion + $AssemblyVersion = $versionprops.Project.PropertyGroup[0].AssemblyVersion + + if($AssemblyFileVersion -eq $AssemblyVersion) + { + Write-Host AssemblyFileVersion: $AssemblyFileVersion should not be equal to: $AssemblyVersion + Exit -1 + } + displayName: 'Check "AssemblyFileVersion" is not same as "AssemblyVersion" in version.props' diff --git a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml new file mode 100644 index 0000000000..536812acf0 --- /dev/null +++ b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml @@ -0,0 +1,102 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: testConfigurations + type: object + + - name: dependsOn + type: string + default: '' + + - name: buildType + displayName: 'Build Type' + default: Project + values: + - Project + - Package + + - name: prebuildSteps + type: stepList + default: [] + + - name: postTestJobs + type: jobList + default: [] + +stages: +- ${{ each config in parameters.testConfigurations }}: + - ${{ each image in config.value.images }}: + - stage: ${{ image.key }} + ${{ if ne(parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + ${{ else }}: + dependsOn: [] + jobs: + - ${{ each targetFramework in config.value.TargetFrameworks }}: + - ${{ each platform in config.value.buildPlatforms }}: + - ${{ each testSet in config.value.TestSets }}: + - ${{ if contains(targetFramework, 'net4') }}: # .NET Framework + - template: ../jobs/ci-run-tests-job.yml@self + parameters: + debug: ${{ parameters.debug }} + buildType: ${{ parameters.buildType }} + poolName: ${{ config.value.pool }} + hostedPool: ${{ eq(config.value.hostedPool, true) }} + image: ${{ image.value }} + jobDisplayName: ${{ format('{0}_{1}_{2}', replace(targetFramework, '.', '_'), platform, testSet) }} + configProperties: ${{ config.value.configProperties }} + prebuildSteps: ${{ parameters.prebuildSteps }} + targetFramework: ${{ targetFramework }} + testSet: ${{ testSet }} + ${{ each codeCoveTF in config.value.codeCovTargetFrameworks }}: + ${{ if eq(codeCoveTF, targetFramework) }}: + publishTestResults: true + configSqlFor: ${{ config.value.configSqlFor }} + operatingSystem: ${{ config.value.operatingSystem }} + ${{if ne(config.value.configProperties, '{}') }}: + ${{ each x86TF in config.value.configProperties.x86TestTargetFrameworks }}: + ${{ if eq(x86TF, targetFramework) }}: + enableX86Test: true + - ${{ else }}: # .NET + - ${{ each useManagedSNI in config.value.useManagedSNI }}: + - template: ../jobs/ci-run-tests-job.yml@self + parameters: + debug: ${{ parameters.debug }} + buildType: ${{ parameters.buildType }} + poolName: ${{ config.value.pool }} + hostedPool: ${{ eq(config.value.hostedPool, true) }} + image: ${{ image.value }} + ${{if eq(usemanagedSNI, 'true') }}: + jobDisplayName: ${{ format('{0}_{1}_{2}_{3}', replace(targetFramework, '.', '_'), platform, 'ManagedSNI', testSet) }} + ${{ else }}: + jobDisplayName: ${{ format('{0}_{1}_{2}_{3}', replace(targetFramework, '.', '_'), platform, 'NativeSNI', testSet) }} + configProperties: ${{ config.value.configProperties }} + useManagedSNI: ${{ useManagedSNI }} + prebuildSteps: ${{ parameters.prebuildSteps }} + targetFramework: ${{ targetFramework }} + testSet: ${{ testSet }} + ${{ each codeCoveTF in config.value.codeCovTargetFrameworks }}: + ${{ if eq(codeCoveTF, targetFramework) }}: + publishTestResults: true + configSqlFor: ${{ config.value.configSqlFor }} + operatingSystem: ${{ config.value.operatingSystem }} + ${{if and(eq(usemanagedSNI, false), ne(config.value.configProperties, '{}')) }}: + ${{ each x86TF in config.value.configProperties.x86TestTargetFrameworks }}: + ${{ if eq(x86TF, targetFramework) }}: + enableX86Test: true + +- ${{ if ne(length(parameters.postTestJobs), 0) }}: + - stage: Post_Test + displayName: 'Post Test Jobs' + dependsOn: + - ${{ each config in parameters.testConfigurations }}: + - ${{ each image in config.value.images }}: + - ${{ image.key }} + jobs: ${{ parameters.postTestJobs }} diff --git a/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml new file mode 100644 index 0000000000..6065ce155e --- /dev/null +++ b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml @@ -0,0 +1,54 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: AssemblyFileVersion + type: string + default: $(AssemblyFileVersion) + + - name: Configuration + type: string + default: '$(Configuration)' + + - name: packageRefMdsVersion + type: string + default: '' + + - name: product + default: MDS + values: + - MDS + - AKV + - MSS + +steps: +- task: DownloadSecureFile@1 + displayName: 'Download Key Pair' + inputs: + secureFile: netfxKeypair.snk + retryCount: 5 + +- ${{ if eq(parameters.product, 'MDS') }}: + - task: MSBuild@1 + displayName: 'BuildAllConfigurations using build.proj' + inputs: + solution: '**/build.proj' + configuration: '${{parameters.Configuration }}' + msbuildArguments: '-p:AssemblyFileVersion=${{parameters.AssemblyFileVersion }} -t:BuildAllConfigurations -p:GenerateNuget=false -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' + +- ${{ if eq(parameters.product, 'AKV') }}: + - task: MSBuild@1 + displayName: 'BuildAKVNetFx using build.proj' + inputs: + solution: '**/build.proj' + configuration: '${{parameters.Configuration }}' + msbuildArguments: '-p:AssemblyFileVersion=${{parameters.AssemblyFileVersion }} -t:BuildAKVNetFx -p:NugetPackageVersion=${{parameters.packageRefMdsVersion }} -p:ReferenceType=Package -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' + + - task: MSBuild@1 + displayName: 'BuildAKVNetCoreAllOS using build.proj' + inputs: + solution: '**/build.proj' + configuration: '${{parameters.Configuration }}' + msbuildArguments: '-p:AssemblyFileVersion=${{parameters.AssemblyFileVersion }} -t:BuildAKVNetCoreAllOS -p:NugetPackageVersion=${{parameters.packageRefMdsVersion }} -p:ReferenceType=Package -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' diff --git a/eng/pipelines/common/templates/steps/build-all-tests-step.yml b/eng/pipelines/common/templates/steps/build-all-tests-step.yml new file mode 100644 index 0000000000..826be1df8b --- /dev/null +++ b/eng/pipelines/common/templates/steps/build-all-tests-step.yml @@ -0,0 +1,75 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: targetFramework + type: string + + - name: nugetPackageVersion + type: string + default: $(NugetPackageVersion) + + - name: platform + type: string + default: $(Platform) + + - name: configuration + type: string + default: '$(Configuration)' + + - name: referenceType + default: Package + values: + - Project + - Package + + - name: OSGroup + type: string + default: '' + + - name: testSet + type: string + +steps: +- ${{ if contains(parameters.targetFramework, 'net4') }}: # .NET Framework + - task: MSBuild@1 + displayName: 'Build Tests NetFx' + inputs: + solution: build.proj + platform: '${{parameters.platform }}' + configuration: '${{parameters.configuration }}' + msbuildArguments: '-t:BuildTestsNetFx -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }}' + +# - ${{else if contains(parameters.targetFramework, 'netstandard')}}: # .NET Standard +# - task: MSBuild@1 +# displayName: 'Build Tests NetStandard' +# inputs: +# solution: build.proj +# platform: '${{parameters.platform }}' +# configuration: '${{parameters.configuration }}' +# msbuildArguments: '-t:BuildTestsNetCore -p:ReferenceType=NetStandard -p:TargetNetStandardVersion=${{parameters.targetNetStandardVersion }} -p:TF=${{parameters.targetFramework }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }}' +# condition: and(succeeded(), not(startsWith(variables['TF'], 'net4')), startsWith(variables['TargetNetStandardVersion'], 'netstandard')) + +- ${{elseif eq(parameters.OSGroup, '')}}: # .NET on Windows + - task: MSBuild@1 + displayName: 'Build Tests NetCore [Win]' + inputs: + solution: build.proj + platform: '${{parameters.platform }}' + configuration: '${{parameters.configuration }}' + msbuildArguments: '-t:BuildTestsNetCore -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }}' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- ${{ else }}: # .NET on Unix + - task: DotNetCoreCLI@2 + displayName: 'Build Tests NetCore [Non-Win]' + inputs: + command: custom + projects: build.proj + custom: msbuild + arguments: '-t:BuildTestsNetCore -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }} -p:OSGroup=${{parameters.OSGroup }} -p:platform=${{parameters.platform }} -p:Configuration=${{parameters.configuration }}' + verbosityRestore: Detailed + verbosityPack: Detailed + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) diff --git a/eng/pipelines/common/templates/steps/build-and-run-tests-netcore-step.yml b/eng/pipelines/common/templates/steps/build-and-run-tests-netcore-step.yml new file mode 100644 index 0000000000..f747fa57e6 --- /dev/null +++ b/eng/pipelines/common/templates/steps/build-and-run-tests-netcore-step.yml @@ -0,0 +1,80 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: TargetNetCoreVersion + type: string + default: $(TargetNetCoreVersion) + + - name: configuration + type: string + default: $(Configuration) + + - name: referenceType + default: Project + values: + - Project + - Package + + - name: NugetPackageVersion + type: string + default: $(NugetPackageVersion) + + - name: platform + type: string + default: $(Platform) + + - name: cleanFirst + type: boolean + default: false + + - name: TestTargetOS + type: string + default: Windowsnetcoreapp + values: + - Windowsnetfx + - Windowsnetcoreapp + - Unixnetcoreapp + + - name: retryCountOnManualTests + type: number + default: 2 + +steps: +- ${{ if eq(parameters.cleanFirst, true)}}: + - task: MSBuild@1 + displayName: 'Clean artifacts folder' + inputs: + solution: build.proj + msbuildArguments: '-t:clean' + +- task: MSBuild@1 + displayName: 'Build AKV Provider .NET' + inputs: + solution: build.proj + msbuildArchitecture: x64 + msbuildArguments: '-p:Configuration=${{parameters.configuration }} -t:BuildAKVNetCore -p:ReferenceType=${{parameters.referenceType }} ' + +- task: MSBuild@1 + displayName: 'MSBuild Build Tests for ${{parameters.TargetNetCoreVersion }}' + inputs: + solution: build.proj + msbuildArchitecture: x64 + msbuildArguments: '-t:BuildTestsNetCore -p:ReferenceType=${{parameters.referenceType }} -p:TargetNetCoreVersion=${{parameters.TargetNetCoreVersion }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} -p:Configuration=${{parameters.configuration }}' + +- task: DotNetCoreCLI@2 + displayName: 'Run Functional Tests for ${{parameters.TargetNetCoreVersion }}' + inputs: + command: test + projects: 'src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj' + arguments: '-p:Platform=${{parameters.platform }} -p:TestTargetOS="${{parameters.TestTargetOS }}" -p:TargetNetCoreVersion=${{parameters.TargetNetCoreVersion }} -p:ReferenceType=${{parameters.referenceType }} -p:Configuration=${{parameters.configuration }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} --no-build -v n --filter "category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests"' + +- task: DotNetCoreCLI@2 + displayName: 'Run Manual Tests for ${{parameters.TargetNetCoreVersion }}' + inputs: + command: test + projects: 'src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj' + arguments: '-p:Platform=${{parameters.platform }} -p:TestTargetOS="${{parameters.TestTargetOS }}" -p:TargetNetCoreVersion=${{parameters.TargetNetCoreVersion }} -p:ReferenceType=${{parameters.referenceType }} -p:Configuration=${{parameters.configuration }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} --no-build -v n --filter category!=nonnetcoreapptests&category!=failing&category!=nonwindowstests --collect "Code Coverage"' + retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} diff --git a/eng/pipelines/common/templates/steps/build-and-run-tests-netfx-step.yml b/eng/pipelines/common/templates/steps/build-and-run-tests-netfx-step.yml new file mode 100644 index 0000000000..ab77af3ee9 --- /dev/null +++ b/eng/pipelines/common/templates/steps/build-and-run-tests-netfx-step.yml @@ -0,0 +1,79 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: TargetNetFxVersion + type: string + default: $(TargetNetFxVersion) + + - name: configuration + type: string + default: $(Configuration) + + - name: referenceType + default: Project + values: + - Project + - Package + + - name: NugetPackageVersion + type: string + default: $(NugetPackageVersion) + + - name: platform + type: string + default: $(Platform) + + - name: cleanFirst + type: boolean + default: false + + - name: TestTargetOS + type: string + default: Windowsnetfx + values: + - Windowsnetfx + - Windowsnetcoreapp + - Unixnetcoreapp + + - name: retryCountOnManualTests + type: number + default: 2 + +steps: +- ${{ if eq(parameters.cleanFirst, true)}}: + - task: MSBuild@1 + displayName: 'Clean artifacts folder' + inputs: + solution: build.proj + msbuildArguments: '-t:clean' + +- task: MSBuild@1 + displayName: 'Build AKV Provider .NET Framework' + inputs: + solution: build.proj + msbuildArchitecture: x64 + msbuildArguments: '-p:Configuration=${{parameters.configuration }} -t:BuildAKVNetFx -p:ReferenceType=${{parameters.referenceType }} ' + +- task: MSBuild@1 + displayName: 'MSBuild Build Tests for ${{parameters.TargetNetFxVersion }}' + inputs: + solution: build.proj + msbuildArguments: ' -t:BuildTestsNetFx -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} -p:TargetNetFxVersion=${{parameters.TargetNetFxVersion }} -p:Configuration=${{parameters.configuration }} -p:Platform=${{parameters.platform }}' + +- task: DotNetCoreCLI@2 + displayName: 'Run Functional Tests for ${{parameters.TargetNetFxVersion }}' + inputs: + command: test + projects: 'src\Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj' + arguments: '-p:Platform=${{parameters.platform }} -p:TestTargetOS="${{parameters.TestTargetOS }}" -p:TargetNetFxVersion=${{parameters.TargetNetFxVersion }} -p:ReferenceType=${{parameters.referenceType }} -p:Configuration=${{parameters.configuration }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" --collect "Code Coverage"' + +- task: DotNetCoreCLI@2 + displayName: 'Run Manual Tests for ${{parameters.TargetNetFxVersion }}' + inputs: + command: test + projects: 'src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj' + arguments: '-p:Platform=${{parameters.platform }} -p:TestTargetOS="${{parameters.TestTargetOS }}" -p:TargetNetFxVersion=${{parameters.TargetNetFxVersion }} -p:ReferenceType=${{parameters.referenceType }} -p:Configuration=${{parameters.configuration }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.NugetPackageVersion }} --no-build -v n --filter "category!=nonnetfxtests&category!=failing&category!=nonwindowstests" --collect "Code Coverage"' + retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} diff --git a/eng/pipelines/common/templates/steps/ci-prebuild-step.yml b/eng/pipelines/common/templates/steps/ci-prebuild-step.yml new file mode 100644 index 0000000000..b6f1ef56fe --- /dev/null +++ b/eng/pipelines/common/templates/steps/ci-prebuild-step.yml @@ -0,0 +1,43 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: artifactName + type: string + default: Artifacts + + - name: buildType + displayName: 'Build Type' + default: Project + values: + - Project + - Package + +steps: +- ${{if eq(parameters.debug, true)}}: + - powershell: | + Get-ChildItem env: | Sort-Object Name + displayName: 'List Environment Variables [debug]' + +- ${{if eq(parameters.buildType, 'Package')}}: + - task: DownloadPipelineArtifact@2 + displayName: 'Download NuGet Package' + inputs: + buildType: current + artifact: ${{parameters.artifactName }} + patterns: '**/*.nupkg' + targetPath: $(Pipeline.Workspace)/${{parameters.artifactName }} + + - template: update-nuget-config-local-feed-step.yml@self + parameters: + downloadedNugetPath: $(Pipeline.Workspace)\${{parameters.artifactName }} + debug: ${{ parameters.debug }} + +- ${{ else }}: # project + - template: ci-project-build-step.yml@self diff --git a/eng/pipelines/common/templates/steps/ci-project-build-step.yml b/eng/pipelines/common/templates/steps/ci-project-build-step.yml new file mode 100644 index 0000000000..205f908599 --- /dev/null +++ b/eng/pipelines/common/templates/steps/ci-project-build-step.yml @@ -0,0 +1,91 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: platform + type: string + default: $(Platform) + + - name: configuration + type: string + default: $(Configuration) + + - name: buildNumber + type: string + default: $(BuildNumber) + + - name: operatingSystem + type: string + default: deferedToRuntime + values: + - Windows + - Linux + - MacOS + - deferedToRuntime + + - name: build + type: string + default: MDS + values: + - MDS + - AKV + - all + +steps: +- ${{ if or(eq(parameters.operatingSystem, 'Windows'), eq(parameters.operatingSystem, 'deferedToRuntime')) }}: + - ${{ if or(eq(parameters.build, 'MDS'), eq(parameters.build, 'all')) }}: + - task: MSBuild@1 + displayName: 'Restore nugets [Win]' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + inputs: + solution: build.proj + msbuildArchitecture: x64 + msbuildArguments: '-t:restore' + retryCountOnTaskFailure: 1 + + - task: MSBuild@1 + displayName: 'Build Driver [Win]' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + inputs: + solution: build.proj + msbuildArchitecture: x64 + platform: '${{ parameters.platform }}' + configuration: '${{ parameters.configuration }}' + msbuildArguments: '-t:BuildAllConfigurations -p:GenerateNuGet=false -p:BuildNumber=${{ parameters.buildNumber }}' + clean: true + + - ${{ if or(eq(parameters.build, 'AKV'), eq(parameters.build, 'all')) }}: + - task: MSBuild@1 + displayName: 'Build AKV Provider NetFx [Win]' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + inputs: + solution: build.proj + msbuildArchitecture: x64 + platform: '${{ parameters.platform }}' + configuration: '${{ parameters.configuration }}' + msbuildArguments: '-t:BuildAKVNetFx -p:BuildNumber=${{ parameters.buildNumber }}' + + - task: MSBuild@1 + displayName: 'Build AKV Provider NetCore All OS [Win]' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + inputs: + solution: build.proj + msbuildArchitecture: x64 + platform: '${{ parameters.platform }}' + configuration: '${{ parameters.configuration }}' + msbuildArguments: '-t:BuildAKVNetCoreAllOS -p:BuildNumber=${{ parameters.buildNumber }}' + +- ${{ if or(eq(parameters.operatingSystem, 'Linux'), eq(parameters.operatingSystem, 'MacOS'), eq(parameters.operatingSystem, 'deferedToRuntime')) }}: + - task: DotNetCoreCLI@2 + displayName: 'Build Driver [non-Win]' + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) + inputs: + command: custom + projects: build.proj + custom: msbuild + arguments: '-t:BuildAll -p:TestEnabled=true -p:GenerateDocumentationFile=false -p:configuration=${{ parameters.configuration }}' + verbosityRestore: Detailed + verbosityPack: Detailed + retryCountOnTaskFailure: 1 diff --git a/eng/pipelines/common/templates/steps/code-analyze-step.yml b/eng/pipelines/common/templates/steps/code-analyze-step.yml new file mode 100644 index 0000000000..1ba79cda3b --- /dev/null +++ b/eng/pipelines/common/templates/steps/code-analyze-step.yml @@ -0,0 +1,51 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: analyzeType + values: + - roslyn + - inspect + - all + + - name: sourceRoot + type: string + default: $(REPOROOT) + + - name: packageRefMdsVersion + type: string + default: '' + + - name: product + default: MDS + values: + - MDS + - AKV + - MSS + +steps: +- ${{ if or(eq(parameters.analyzeType, 'roslyn'), eq(parameters.analyzeType, 'all')) }}: + - ${{ if eq(parameters.product, 'MDS') }}: + - task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@3 + displayName: 'Guardian Dotnet Analyzers ' + inputs: + msBuildVersion: 17.0 + msBuildArchitecture: x64 + setupCommandlinePicker: vs2022 + msBuildCommandline: 'msbuild ${{parameters.sourceRoot}}\build.proj -p:configuration=Release -p:GenerateNuget=false -p:BuildTools=false -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' + - ${{ if eq(parameters.product, 'AKV') }}: + - task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@3 + displayName: 'Guardian Dotnet Analyzers ' + inputs: + msBuildVersion: 17.0 + msBuildArchitecture: x64 + setupCommandlinePicker: vs2022 + msBuildCommandline: 'msbuild ${{parameters.sourceRoot}}\build.proj -p:configuration=Release -p:GenerateNuget=false -p:BuildTools=false -p:NugetPackageVersion=${{parameters.packageRefMdsVersion }} -p:ReferenceType=Package -t:BuildAKVNetCoreAllOS -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' + +- ${{ if or(eq(parameters.analyzeType, 'inspect'), eq(parameters.analyzeType, 'all')) }}: + - task: securedevelopmentteam.vss-secure-development-tools.build-task-codeinspector.CodeInspector@2 + displayName: 'Run Code Inspector' + inputs: + LogLevel: Error diff --git a/eng/pipelines/common/templates/steps/configure-sql-server-linux-step.yml b/eng/pipelines/common/templates/steps/configure-sql-server-linux-step.yml new file mode 100644 index 0000000000..2976c83939 --- /dev/null +++ b/eng/pipelines/common/templates/steps/configure-sql-server-linux-step.yml @@ -0,0 +1,64 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: password + type: string + default: $(password) + + - name: targetNetCoreVersion + type: string + default: $(MainTargetNetCoreVersion) + + - name: condition + type: string + default: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) + +steps: +# Linux only steps +- bash: | + echo ${{parameters.targetNetCoreVersion }} + + sudo systemctl stop mssql-server + + # Password for the SA user (required) + MSSQL_SA_PW=${{parameters.password }} + if [ "$MSSQL_SA_PW" = "generated_placeholder" ]; then + exit 0 + fi + + # Product ID of the version of SQL server you're installing + # Must be evaluation, developer, express, web, standard, enterprise, or your 25 digit product key + MSSQL_PID='enterprise' + + echo Running mssql-conf setup... + sudo MSSQL_SA_PASSWORD=$MSSQL_SA_PW\ + MSSQL_PID=$MSSQL_PID \ + /opt/mssql/bin/mssql-conf -n setup accept-eula + + # Connect to server and get the version: + counter=1 + errstatus=1 + while [ $counter -le 5 ] && [ $errstatus = 1 ] + do + echo Waiting for SQL Server to start... + sleep 3s + /opt/mssql-tools/bin/sqlcmd \ + -S localhost \ + -U SA \ + -P $MSSQL_SA_PW\ + -Q "SELECT @@VERSION" 2>/dev/null + errstatus=$? + ((counter++)) + done + + # Display error if connection failed: + if [ $errstatus = 1 ] + then + echo Cannot connect to SQL Server, installation aborted + exit $errstatus + fi + displayName: 'Configure SQL Server [Linux]' + condition: ${{parameters.condition }} diff --git a/eng/pipelines/common/templates/steps/configure-sql-server-step.yml b/eng/pipelines/common/templates/steps/configure-sql-server-step.yml new file mode 100644 index 0000000000..a7cb066d31 --- /dev/null +++ b/eng/pipelines/common/templates/steps/configure-sql-server-step.yml @@ -0,0 +1,111 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: +# Windows only parameters + - name: instanceName + type: string + default: MSSQLSERVER + + - name: user + type: string + default: $(user) + + - name: saUser + type: string + default: $(saUser) + + - name: SQLRootPath + type: string + default: '' + + - name: fileStreamDirectory + type: string + default: '' + + - name: x64AliasRegistryPath + type: string + default: $(x64AliasRegistryPath) + + - name: x86AliasRegistryPath + type: string + default: $(x86AliasRegistryPath) + + - name: SQLAliasName + type: string + default: $(SQLAliasName) + + - name: SQLAliasPort + type: string + default: $(SQLAliasPort) + + - name: enableLocalDB + type: boolean + default: false + + - name: localDbAppName + type: string + default: $(LocalDbAppName) + + - name: localDbSharedInstanceName + type: string + default: $(LocalDbSharedInstanceName) + +# Common parameters + - name: password + type: string + default: $(password) + + - name: targetNetCoreVersion + type: string + default: $(MainTargetNetCoreVersion) + + - name: databaseName + type: string + default: Northwind + + - name: operatingSystem + type: string + +steps: +- ${{ if eq(parameters.operatingSystem, 'Windows') }}: + # windows only steps + - template: configure-sql-server-win-step.yml@self + parameters: + instanceName: ${{parameters.instanceName}} + user: ${{parameters.user}} + saUser: ${{parameters.saUser}} + SQLRootPath: ${{parameters.SQLRootPath}} + fileStreamDirectory: ${{parameters.fileStreamDirectory}} + x64AliasRegistryPath: ${{parameters.x64AliasRegistryPath}} + x86AliasRegistryPath: ${{parameters.x86AliasRegistryPath}} + SQLAliasName: ${{parameters.SQLAliasName}} + SQLAliasPort: ${{parameters.SQLAliasPort}} + enableLocalDB: ${{parameters.enableLocalDB}} + localDbAppName: ${{parameters.localDbAppName}} + localDbSharedInstanceName: ${{parameters.localDbSharedInstanceName}} + password: ${{parameters.password}} + +- ${{ elseif eq(parameters.operatingSystem, 'Linux') }}: + # Linux only steps + - template: configure-sql-server-linux-step.yml@self + parameters: + password: ${{parameters.password}} + targetNetCoreVersion: ${{parameters.targetNetCoreVersion}} + +# Common steps +- task: DotNetCoreCLI@2 + displayName: 'Build Ext Utilities' + inputs: + arguments: '-f ${{parameters.targetNetCoreVersion }}' + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.ExtUtilities + retryCountOnTaskFailure: 1 + +- task: DotNetCoreCLI@2 + displayName: 'Create Test Database ${{parameters.databaseName }}' + inputs: + command: run + arguments: '-f ${{parameters.targetNetCoreVersion }} -- "CreateDatabase" ${{parameters.databaseName }} ' + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.ExtUtilities diff --git a/eng/pipelines/common/templates/steps/configure-sql-server-win-step.yml b/eng/pipelines/common/templates/steps/configure-sql-server-win-step.yml new file mode 100644 index 0000000000..f0c27e6152 --- /dev/null +++ b/eng/pipelines/common/templates/steps/configure-sql-server-win-step.yml @@ -0,0 +1,250 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: +# Windows only parameters + - name: instanceName + type: string + default: MSSQLSERVER + + - name: user + type: string + default: $(user) + + - name: saUser + type: string + default: $(saUser) + + - name: SQLRootPath + type: string + default: '' + + - name: fileStreamDirectory + type: string + default: '' + + - name: x64AliasRegistryPath + type: string + default: $(x64AliasRegistryPath) + + - name: x86AliasRegistryPath + type: string + default: $(x86AliasRegistryPath) + + - name: SQLAliasName + type: string + default: $(SQLAliasName) + + - name: SQLAliasPort + type: string + default: $(SQLAliasPort) + + - name: enableLocalDB + type: boolean + default: false + + - name: localDbAppName + type: string + default: $(LocalDbAppName) + + - name: localDbSharedInstanceName + type: string + default: $(LocalDbSharedInstanceName) + +# Common parameters + - name: password + type: string + default: $(password) + + - name: condition + type: string + default: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +steps: +# windows only steps +- powershell: | + try + { + # enable TCP + Import-Module "sqlps" + $smo = 'Microsoft.SqlServer.Management.Smo.' + $wmi = new-object ($smo + 'Wmi.ManagedComputer'). + # List the object properties, including the instance names. + $Wmi + + # Enable the TCP protocol on the default instance. + $Tcp = $wmi.GetSmoObject("ManagedComputer[@Name='$env:COMPUTERNAME']/ ServerInstance[@Name='${{parameters.instanceName }}']/ServerProtocol[@Name='Tcp']") + $Tcp.IsEnabled = $true + $Tcp.Alter() + + # Enable the NP protocol on the default instance. + $Np = $wmi.GetSmoObject("ManagedComputer[@Name='$env:COMPUTERNAME']/ ServerInstance[@Name='${{parameters.instanceName }}']/ServerProtocol[@Name='Np']") + $Np.IsEnabled = $true + $Np.Alter() + + $Tcp + } + catch + { + $error[0] | format-list -force + throw + } + + New-NetFirewallRule -DisplayName "SQL TCP Ports" -Direction Inbound –Protocol TCP –LocalPort 1433 -Action allow + $sqlSrvPath = (Get-WmiObject win32_service | ?{$_.DisplayName -eq 'SQL Server (${{parameters.instanceName }})'} | select @{Name="Path"; Expression={$_.PathName.split('"')[1]}}).Path + New-NetFirewallRule -DisplayName "sqlservr.exe" -Program "$sqlSrvPath" + displayName: 'Enable TCP, NP & Firewall [Win]' + condition: ${{parameters.condition }} + retryCountOnTaskFailure: 2 + +- powershell: | + $password = "${{parameters.password }}" + if ( "generated_placeholder" -eq $password ) + { + $password = [guid]::NewGuid().ToString() + } + + $machineName = $env:COMPUTERNAME + + if ("${{parameters.instanceName }}" -ne "MSSQLSERVER"){ + $machineName += "\${{parameters.instanceName }}" + } + + Write-Host $machineName + Import-Module "sqlps" + $tries = 0 + while ($true) { + $tries++ + try { + Invoke-Sqlcmd -ServerInstance "$machineName" @" + CREATE LOGIN [${{parameters.user }}] WITH PASSWORD=N'$password', + DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF; + CREATE USER [${{parameters.user }}] FROM LOGIN [${{parameters.user }}]; + ALTER SERVER ROLE [sysadmin] ADD MEMBER [${{parameters.user }}]; + ALTER LOGIN [${{parameters.saUser }}] ENABLE; + ALTER LOGIN [${{parameters.saUser }}] WITH PASSWORD = '$password'; + "@ + break + } catch { + if ($tries -ge 5) { + Write-Host "##[error]Failed to create database user after $tries tries." + break + } + Write-Host "Failed to connect to server. Retrying in 5 seconds..." + Start-Sleep -Seconds 5 + } + } + displayName: 'Create SQL user [Win]' + condition: ${{parameters.condition }} + env: + SQL_USER: ${{parameters.user }} + SQL_PASSWD: ${{parameters.password }} + +- ${{ if ne(parameters.SQLRootPath, '') }}: + - powershell: | + #Enable FileStream + $instance = "${{parameters.instanceName }}" + $wmi = Get-WmiObject -Namespace "${{parameters.SQLRootPath }}" -Class FilestreamSettings | where {$_.InstanceName -eq $instance} + $wmi.EnableFilestream(3, $instance) + + $machineName = $env:COMPUTERNAME + + if ("${{parameters.instanceName }}" -ne "MSSQLSERVER"){ + $machineName += "\${{parameters.instanceName }}" + } + + #Change the access level for FileStream for SQLServer + Set-ExecutionPolicy Unrestricted + Import-Module "sqlps" + Invoke-Sqlcmd -ServerInstance "$machineName" @" + EXEC sp_configure filestream_access_level, 2; + RECONFIGURE; + "@ + displayName: 'Enable FileStream [Win]' + condition: ${{parameters.condition }} + env: + SQL_USER: ${{parameters.user }} + SQL_PASSWD: ${{parameters.password }} + +- ${{ if ne(parameters.FileStreamDirectory, '') }}: + - powershell: | + New-Item -Path ${{ parameters.fileStreamDirectory }} -ItemType Directory + displayName: 'Create FileStreamFolder' + retryCountOnTaskFailure: 1 + condition: ${{parameters.condition }} + continueOnError: true + +- powershell: | + $SQLServerName = ("{0}" -f [System.Net.Dns]::GetHostByName($env:computerName).HostName) + Write-Host FQDN is: $SQLServerName + + if ((Test-Path -Path ${{parameters.x64AliasRegistryPath }}) -ne $true) { + New-Item ${{parameters.x64AliasRegistryPath }} + } + + if ((Test-Path -Path ${{parameters.x86AliasRegistryPath }}) -ne $true) { + New-Item ${{parameters.x86AliasRegistryPath }} + } + + $TCPAliasName = "DBMSSOCN, $SQLServerName, ${{parameters.SQLAliasPort }}" + + New-ItemProperty -Path ${{parameters.x86AliasRegistryPath }} -Name ${{parameters.SQLAliasName }} -PropertyType string -Value $TCPAliasName + New-ItemProperty -Path ${{parameters.x64AliasRegistryPath }} -Name ${{parameters.SQLAliasName }} -PropertyType string -Value $TCPAliasName + displayName: 'Setup SQL Alias [Win]' + condition: ${{parameters.condition }} + +- powershell: | + # You need to restart SQL Server for the change to persist + # -Force takes care of any dependent services, like SQL Agent. + # Note: if the instance is named, replace MSSQLSERVER with MSSQL$ followed by + # the name of the instance (e.g. MSSQL$MYINSTANCE) + + $serviceName = "${{parameters.instanceName }}" + $InstancePrefix = 'MSSQL$' + + if ( "${{parameters.instanceName }}" -ne "MSSQLSERVER" ) + { + $serviceName = $InstancePrefix+"${{parameters.instanceName }}" + } + + Restart-Service -Name "$serviceName" -Force + + displayName: 'Restart SQL Server [Win]' + condition: ${{parameters.condition }} + +- powershell: | + $arrService = Get-Service -Name "SQLBrowser" + $arrService + + if ($arrService.Status -eq 'Stopped') { + Write-Host 'Attempt to run the service ...' + # updating the startup type to make sure it's not disabled + Set-Service -StartupType Automatic $arrService.Name + $arrService.Start() + + $arrService.WaitForStatus('Running', '00:00:30') + if ($arrService.Status -eq 'Running') { + $arrService + } else { + Write-Error 'Timed out waiting for service to start.' + } + } + displayName: 'Start Sql Server Browser [Win]' + condition: ${{parameters.condition }} + +- ${{ if parameters.enableLocalDB }}: + - powershell: | + #script to enable local db + + SqlLocalDB info + #SqlLocalDB create ${{parameters.localDbAppName }} + SqlLocalDB info ${{parameters.localDbAppName }} + SqlLocalDB share ${{parameters.localDbAppName }} ${{parameters.LocalDbSharedInstanceName }} + SqlLocalDB start ${{parameters.localDbAppName }} + SqlLocalDB info ${{parameters.localDbAppName }} + + sqlcmd -S "(localdb)\.\${{parameters.LocalDbSharedInstanceName }}" -q "SELECT @@VERSION" + displayName: 'Enable LocalDB [Win]' + condition: ${{parameters.condition }} diff --git a/eng/pipelines/common/templates/steps/copy-dlls-for-test-step.yml b/eng/pipelines/common/templates/steps/copy-dlls-for-test-step.yml new file mode 100644 index 0000000000..faf54fc24d --- /dev/null +++ b/eng/pipelines/common/templates/steps/copy-dlls-for-test-step.yml @@ -0,0 +1,106 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: Configuration + type: string + default: '$(Configuration)' + + - name: symbolsFolder + type: string + default: symbols + + - name: softwareFolder + type: string + default: software + + - name: referenceType + default: project + values: + - project + - package + + - name: listOfTF + type: object + default: + - net462 + - net6.0 + - net8.0 + + - name: product + default: MDS + values: + - MDS + - AKV + - MSS + +steps: +- powershell: | + $software = '${{parameters.softwareFolder}}' + $symbols = '${{parameters.symbolsFolder}}' + + md $software + md $software\win + + md $symbols + md $symbols\win + displayName: 'Make base directories' + +- ${{ each targetFramework in parameters.listOfTF }}: + - ${{ if eq(parameters.product, 'MDS') }}: + - powershell: | + $software = '${{parameters.softwareFolder}}' + $tf = '${{ targetFramework }}' + md $software\win\$tf + + if ($tf.StartsWith('net4')) + { + Copy-Item "artifacts\${{parameters.referenceType }}\bin\Windows_NT\${{parameters.Configuration }}.AnyCPU\Microsoft.Data.SqlClient\netfx\$tf\Microsoft.Data.SqlClient.dll" "$software\win\$tf" -recurse + } + else + { + Copy-Item "artifacts\${{parameters.referenceType }}\bin\Windows_NT\${{parameters.Configuration }}.AnyCPU\Microsoft.Data.SqlClient\netcore\$tf\Microsoft.Data.SqlClient.dll" "$software\win\$tf" -recurse + } + + $symbols = '${{parameters.symbolsFolder}}' + md $symbols\win\$tf + + if ($tf.StartsWith('net4')) + { + Copy-Item "artifacts\Project\bin\Windows_NT\Release.AnyCPU\Microsoft.Data.SqlClient\netfx\$tf\Microsoft.Data.SqlClient.pdb" "$symbols\win\$tf" -recurse + } + else + { + Copy-Item "artifacts\Project\bin\Windows_NT\Release.AnyCPU\Microsoft.Data.SqlClient\netcore\$tf\Microsoft.Data.SqlClient.pdb" "$symbols\win\$tf" -recurse + } + + Write-Host "Artifacts fetched for testing" + Get-Location + displayName: 'Prepare ${{ targetFramework }} Arifacts for Testing' + + - ${{ if eq(parameters.product, 'AKV') }}: + - powershell: | + $software = '${{parameters.softwareFolder}}' + $tf = '${{ targetFramework }}' + md $software\win\$tf + + Copy-Item "artifacts\${{parameters.referenceType }}\bin\Windows_NT\${{parameters.Configuration }}.AnyCPU\AzureKeyVaultProvider\$tf\Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.dll" "$software\win\$tf" -recurse + + $symbols = '${{parameters.symbolsFolder}}' + md $symbols\win\$tf + + Copy-Item "artifacts\${{parameters.referenceType }}\bin\Windows_NT\${{parameters.Configuration }}.AnyCPU\AzureKeyVaultProvider\$tf\Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.pdb" "$symbols\win\$tf" -recurse + + Write-Host "Artifacts fetched for testing" + Get-Location + displayName: 'Prepare ${{ targetFramework }} Arifacts for Testing' + +- powershell: | + $software = '${{parameters.softwareFolder}}' + $symbols = '${{parameters.symbolsFolder}}' + + Get-ChildItem -recurse "$software\*.dll" + Get-ChildItem -recurse "$symbols\*.pdb" + displayName: 'List the prepared files' diff --git a/eng/pipelines/common/templates/steps/esrp-code-signing-step.yml b/eng/pipelines/common/templates/steps/esrp-code-signing-step.yml new file mode 100644 index 0000000000..a2851ed463 --- /dev/null +++ b/eng/pipelines/common/templates/steps/esrp-code-signing-step.yml @@ -0,0 +1,135 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: artifactType + values: + - dll + - pkg + + - name: sourceRoot + type: string + default: $(REPOROOT) + + - name: artifactDirectory + type: string + default: $(artifactDirectory) + + - name: appRegistrationClientId + type: string + default: $(appRegistrationClientId) + + - name: appRegistrationTenantId + type: string + default: $(appRegistrationTenantId) + +steps: +- ${{ if eq(parameters.artifactType, 'dll') }}: + - task: EsrpMalwareScanning@5 + displayName: 'ESRP MalwareScanning' + inputs: + ConnectedServiceName: 'ESRP Workload Identity federation service-ADO.Net' + AppRegistrationClientId: '${{parameters.appRegistrationClientId }}' + AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}' + AuthAKVName: SqlClientDrivers + AuthCertName: 'ESRP-Release-Auth' + FolderPath: '${{parameters.sourceRoot }}' + Pattern: '*.dll' + CleanupTempStorage: 1 + VerboseLogin: 1 + - task: EsrpCodeSigning@5 + displayName: 'ESRP CodeSigning' + inputs: + ConnectedServiceName: 'ESRP Workload Identity federation service-ADO.Net' + AppRegistrationClientId: '${{parameters.appRegistrationClientId }}' + AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}' + AuthAKVName: SqlClientDrivers + AuthCertName: 'ESRP-Release-Auth' + AuthSignCertName: 'ESRP-Release-Sign2' + FolderPath: '${{parameters.sourceRoot }}' + Pattern: '*.dll' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft Data SqlClient Data Provider for SQL Server" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolVerify", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + +- ${{ if eq(parameters.artifactType, 'pkg') }}: + - task: EsrpMalwareScanning@5 + displayName: 'ESRP MalwareScanning Nuget Package' + inputs: + ConnectedServiceName: 'ESRP Workload Identity federation service-ADO.Net' + AppRegistrationClientId: '${{parameters.appRegistrationClientId }}' + AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}' + AuthAKVName: SqlClientDrivers + AuthCertName: 'ESRP-Release-Auth' + FolderPath: '${{parameters.artifactDirectory }}' + Pattern: '*.*nupkg' + CleanupTempStorage: 1 + VerboseLogin: 1 + - task: EsrpCodeSigning@5 + displayName: 'ESRP CodeSigning Nuget Package' + inputs: + inputs: + ConnectedServiceName: 'ESRP Workload Identity federation service-ADO.Net' + AppRegistrationClientId: '${{parameters.appRegistrationClientId }}' + AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}' + AuthAKVName: SqlClientDrivers + AuthCertName: 'ESRP-Release-Auth' + AuthSignCertName: 'ESRP-Release-Sign2' + FolderPath: '${{parameters.artifactDirectory }}' + Pattern: '*.*nupkg' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401405", + "operationSetCode": "NuGetSign", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + }, + { + "keyCode": "CP-401405", + "operationSetCode": "NuGetVerify", + "parameters": [ ], + "toolName": "sign", + "toolVersion": "1.0" + } + ] diff --git a/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml b/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml new file mode 100644 index 0000000000..4e32f989c3 --- /dev/null +++ b/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml @@ -0,0 +1,60 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: nuspecPath + type: string + default: '$(nuspecPath)' + + - name: NugetPackageVersion + type: string + default: '$(NugetPackageVersion)' + + - name: OutputDirectory + type: string + default: '$(Build.SourcesDirectory)/packages' + + - name: Configuration + type: string + default: '$(Configuration)' + + - name: generateSymbolsPackage + type: boolean + default: true + + - name: displayName + type: string + default: 'NuGet pack with snupkg' + + - name: installNuget + type: boolean + default: true + + - name: referenceType + default: project + values: + - project + - package + +steps: +- ${{ if parameters.installNuget }}: + - task: NuGetToolInstaller@1 + displayName: 'Install Latest Nuget' + inputs: + checkLatest: true + +- powershell: | + $Commit=git rev-parse HEAD + Write-Host "##vso[task.setvariable variable=CommitHead;]$Commit" + displayName: CommitHead + +- task: NuGetCommand@2 + displayName: ${{parameters.displayName }} + inputs: + command: custom + ${{ if parameters.generateSymbolsPackage }}: + arguments: 'pack -Symbols -SymbolPackageFormat snupkg ${{parameters.nuspecPath}} -Version ${{parameters.NugetPackageVersion}} -OutputDirectory ${{parameters.OutputDirectory}} -properties "COMMITID=$(CommitHead);Configuration=${{parameters.Configuration}};ReferenceType=${{parameters.referenceType}}"' + ${{else }}: + arguments: 'pack ${{parameters.nuspecPath}} -Version ${{parameters.NugetPackageVersion}} -OutputDirectory ${{parameters.OutputDirectory}} -properties "COMMITID=$(CommitHead);Configuration=${{parameters.Configuration}};ReferenceType=${{parameters.referenceType}}"' diff --git a/eng/pipelines/common/templates/steps/pre-build-step.yml b/eng/pipelines/common/templates/steps/pre-build-step.yml new file mode 100644 index 0000000000..327b5f21a5 --- /dev/null +++ b/eng/pipelines/common/templates/steps/pre-build-step.yml @@ -0,0 +1,20 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +steps: +- script: SET + displayName: 'Print Environment Variables' + +- powershell: | + # use sqlcmd to try to connect to localdb + $svc_name = "SQLBrowser" + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + Set-Service -StartupType Automatic $svc_name + net start $svc_name + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + displayName: 'Start SQLBrowser' + +- task: NuGetToolInstaller@1 + displayName: 'Use NuGet ' diff --git a/eng/pipelines/common/templates/steps/prepare-test-db-step.yml b/eng/pipelines/common/templates/steps/prepare-test-db-step.yml new file mode 100644 index 0000000000..8597a0c9e5 --- /dev/null +++ b/eng/pipelines/common/templates/steps/prepare-test-db-step.yml @@ -0,0 +1,26 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: databaseName + type: string + default: $(Database) + + - name: targetFramework + type: string + default: net6.0 + +steps: +- task: DotNetCoreCLI@2 + displayName: 'Build Ext Utilities' + inputs: + arguments: '-f ${{parameters.targetFramework }}' + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.ExtUtilities +- task: DotNetCoreCLI@2 + displayName: 'Create Test Database' + inputs: + command: run + arguments: '-f ${{parameters.targetFramework }} -- "CreateDatabase" ${{parameters.databaseName }} ' + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.ExtUtilities diff --git a/eng/pipelines/common/templates/steps/publish-symbols-step.yml b/eng/pipelines/common/templates/steps/publish-symbols-step.yml new file mode 100644 index 0000000000..cd1954ce77 --- /dev/null +++ b/eng/pipelines/common/templates/steps/publish-symbols-step.yml @@ -0,0 +1,150 @@ +#################################################################################### +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +# # +# doc: https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL # +#################################################################################### +parameters: + - name: SymAccount + type: string + default: 'SqlClientDrivers' + + - name: publishSymbols + type: string + default: '$(PublishSymbols)' + + - name: symbolsVersion + type: string + default: '$(NuGetPackageVersion)' + + - name: symbolServer + type: string + default: '$(SymbolServer)' + + - name: symbolTokenUri + type: string + default: '$(SymbolTokenUri)' + + - name: symbolsArtifactName + type: string + + - name: publishToServers + type: object + default: + internal: true + public: true + + - name: referenceType + default: project + values: + - project + - package + + - name: product + default: MDS + values: + - MDS + - AKV + - MSS + +steps: +- powershell: 'Write-Host "##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{parameters.SymAccount}}"' + displayName: 'Update Symbol.AccountName with ${{parameters.SymAccount}}' + condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + +- ${{ if eq(parameters.product, 'MDS') }}: + - task: PublishSymbols@2 + displayName: 'Upload symbols to ${{parameters.SymAccount }} org' + inputs: + SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\${{parameters.referenceType }}\bin' + SearchPattern: | + Windows_NT/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb + Unix/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb + IndexSources: false + SymbolServerType: TeamServices + SymbolsMaximumWaitTime: 60 + SymbolExpirationInDays: 1825 # 5 years + SymbolsProduct: Microsoft.Data.SqlClient + SymbolsVersion: ${{parameters.symbolsVersion }} + SymbolsArtifactName: ${{parameters.symbolsArtifactName }} + Pat: $(System.AccessToken) + condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + +- ${{ if eq(parameters.product, 'AKV') }}: + - task: PublishSymbols@2 + displayName: 'Upload symbols to ${{parameters.SymAccount }} org' + inputs: + SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\${{parameters.referenceType }}\bin' + SearchPattern: | + Windows_NT/$(Configuration).AnyCPU/AzureKeyVaultProvider/**/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.pdb + AnyOS/$(Configuration).AnyCPU/AzureKeyVaultProvider/**/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.pdb + IndexSources: false + SymbolServerType: TeamServices + SymbolsMaximumWaitTime: 60 + SymbolExpirationInDays: 1825 # 5 years + SymbolsProduct: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider + SymbolsVersion: ${{parameters.symbolsVersion }} + SymbolsArtifactName: ${{parameters.symbolsArtifactName }} + Pat: $(System.AccessToken) + condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + +- task: AzureCLI@2 + displayName: 'Publish symbols' + condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + inputs: + azureSubscription: 'Symbols publishing Workload Identity federation service-ADO.Net' + scriptType: ps + scriptLocation: inlineScript + inlineScript: | + $publishToInternalServer = "${{parameters.publishToServers.internal }}".ToLower() + $publishToPublicServer = "${{parameters.publishToServers.public }}".ToLower() + + echo "Publishing request name: ${{parameters.symbolsArtifactName }}" + echo "Publish to internal server: $publishToInternalServer" + echo "Publish to public server: $publishToPublicServer" + + $symbolServer = "${{parameters.symbolServer }}" + $tokenUri = "${{parameters.symbolTokenUri }}" + # Registered project name in the symbol publishing pipeline: https://portal.microsofticm.com/imp/v3/incidents/incident/520844254/summary + $projectName = "Microsoft.Data.SqlClient.SNI" + + # Get the access token for the symbol publishing service + $symbolPublishingToken = az account get-access-token --resource $tokenUri --query accessToken -o tsv + + echo "> 1.Symbol publishing token acquired." + + echo "Registering the request name ..." + $requestName = "${{parameters.symbolsArtifactName }}" + $requestNameRegistrationBody = "{'requestName': '$requestName'}" + Invoke-RestMethod -Method POST -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json" -Body $requestNameRegistrationBody + + echo "> 2.Registration of request name succeeded." + + echo "Publishing the symbols ..." + $publishSymbolsBody = "{'publishToInternalServer': $publishToInternalServer, 'publishToPublicServer': $publishToPublicServer}" + echo "Publishing symbols request body: $publishSymbolsBody" + Invoke-RestMethod -Method POST -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests/$requestName" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json" -Body $publishSymbolsBody + + echo "> 3.Request to publish symbols succeeded." + + # The following REST calls are used to check publishing status. + echo "> 4.Checking the status of the request ..." + + Invoke-RestMethod -Method GET -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests/$requestName" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json" + + echo "Use below tables to interpret the values of xxxServerStatus and xxxServerResult fields from the response." + + echo "PublishingStatus" + echo "-----------------" + echo "0 NotRequested; The request has not been requested to publish." + echo "1 Submitted; The request is submitted to be published" + echo "2 Processing; The request is still being processed" + echo "3 Completed; The request has been completed processing. It can be failed or successful. Check PublishingResult to get more details" + + echo "PublishingResult" + echo "-----------------" + echo "0 Pending; The request has not completed or has not been requested." + echo "1 Succeeded; The request has published successfully" + echo "2 Failed; The request has failed to publish" + echo "3 Cancelled; The request was cancelled" diff --git a/eng/pipelines/common/templates/steps/publish-test-results-step.yml b/eng/pipelines/common/templates/steps/publish-test-results-step.yml new file mode 100644 index 0000000000..791a8201b2 --- /dev/null +++ b/eng/pipelines/common/templates/steps/publish-test-results-step.yml @@ -0,0 +1,59 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: targetFramework + type: string + + - name: platform + type: string + default: $(Platform) + + - name: configuration + type: string + default: '$(Configuration)' + + - name: operatingSystem + type: string + +steps: +- task: PublishTestResults@2 + displayName: 'Publish Test Results' + inputs: + testResultsFormat: VSTest + mergeTestResults: true + buildPlatform: '${{parameters.platform }}' + buildConfiguration: '${{parameters.configuration }}' + ${{ if eq(parameters.operatingSystem, 'Windows') }}: + testResultsFiles: 'TestResults/*.trx' + testRunTitle: 'Windows Tests' + ${{ else }}: + testResultsFiles: | + TestResults/*.trx + TestResults/**/*.coverage + testRunTitle: 'Linux Tests' + +- powershell: | + cd TestResults + $TF="${{parameters.targetFramework }}" + Get-ChildItem -Filter “*.coverage” -Recurse | Rename-Item -NewName {"$TF" + $_.name} + displayName: 'Rename coverage files' + +- ${{ if eq(parameters.debug, true)}}: + - powershell: | + cd TestResults + Get-ChildItem -Filter “*.coverage” -Recurse + displayName: 'List test result coverage files [debug]' + +- task: PublishPipelineArtifact@1 + displayName: 'Publish Pipeline Artifact' + inputs: + targetPath: TestResults + artifact: '${{parameters.targetFramework }}WinAz$(System.JobId)' + condition: succeededOrFailed() diff --git a/eng/pipelines/common/templates/steps/run-all-tests-step.yml b/eng/pipelines/common/templates/steps/run-all-tests-step.yml new file mode 100644 index 0000000000..f0eb2eff66 --- /dev/null +++ b/eng/pipelines/common/templates/steps/run-all-tests-step.yml @@ -0,0 +1,107 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: targetFramework + type: string + + - name: nugetPackageVersion + type: string + default: $(NugetPackageVersion) + + - name: platform + type: string + default: $(Platform) + + - name: configuration + type: string + default: '$(Configuration)' + + - name: referenceType + default: Package + values: + - Project + - Package + + - name: testSet + type: string + + - name: msbuildArchitecture + default: x64 + values: + - x64 + - x86 + + - name: dotnetx86RootPath # full path to the x86 dotnet root folder with trailing slash + type: string + default: '' + + - name: operatingSystem + type: string + default: 'Windows' + +steps: +- ${{ if parameters.debug }}: + - powershell: 'dotnet sdk check' + displayName: '.NET sdk check [debug]' + condition: succeededOrFailed() + +- ${{if eq(parameters.operatingSystem, 'Windows')}}: + - task: MSBuild@1 + displayName: 'Run Functional Tests ${{parameters.msbuildArchitecture }}' + inputs: + solution: build.proj + msbuildArchitecture: ${{parameters.msbuildArchitecture }} + platform: '${{parameters.platform }}' + configuration: '${{parameters.configuration }}' + ${{ if eq(parameters.msbuildArchitecture, 'x64') }}: + msbuildArguments: '-t:RunFunctionalTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }}' + ${{ else }}: # x86 + msbuildArguments: '-t:RunFunctionalTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }} -p:DotnetPath=${{parameters.dotnetx86RootPath }}' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + retryCountOnTaskFailure: 1 + + - task: MSBuild@1 + displayName: 'Run Manual Tests ${{parameters.msbuildArchitecture }}' + inputs: + solution: build.proj + msbuildArchitecture: ${{parameters.msbuildArchitecture }} + platform: '${{parameters.platform }}' + configuration: '${{parameters.configuration }}' + ${{ if eq(parameters.msbuildArchitecture, 'x64') }}: + msbuildArguments: '-t:RunManualTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }}' + ${{ else }}: # x86 + msbuildArguments: '-t:RunManualTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }} -p:DotnetPath=${{parameters.dotnetx86RootPath }}' + condition: eq(variables['Agent.OS'], 'Windows_NT') + retryCountOnTaskFailure: 2 + +- ${{ else }}: # Linux or macOS + - task: DotNetCoreCLI@2 + displayName: 'Run Functional Tests' + inputs: + command: custom + projects: build.proj + custom: msbuild + arguments: '-t:RunFunctionalTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }} -p:platform=${{parameters.platform }} -p:Configuration=${{parameters.configuration }}' + verbosityRestore: Detailed + verbosityPack: Detailed + retryCountOnTaskFailure: 1 + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) + + - task: DotNetCoreCLI@2 + displayName: 'Run Manual Tests' + inputs: + command: custom + projects: build.proj + custom: msbuild + arguments: '-t:RunManualTests -p:TF=${{parameters.targetFramework }} -p:TestSet=${{parameters.testSet }} -p:ReferenceType=${{parameters.referenceType }} -p:TestMicrosoftDataSqlClientVersion=${{parameters.nugetPackageVersion }} -p:platform=${{parameters.platform }} -p:Configuration=${{parameters.configuration }}' + verbosityRestore: Detailed + verbosityPack: Detailed + retryCountOnTaskFailure: 2 + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) diff --git a/eng/pipelines/common/templates/steps/update-config-file-step.yml b/eng/pipelines/common/templates/steps/update-config-file-step.yml new file mode 100644 index 0000000000..78a1cfebe3 --- /dev/null +++ b/eng/pipelines/common/templates/steps/update-config-file-step.yml @@ -0,0 +1,199 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: TCPConnectionString + type: string + default: '' + + - name: NPConnectionString + type: string + default: '' + + - name: TCPConnectionStringHGSVBS + type: string + default: '' + + - name: TCPConnectionStringNoneVBS + type: string + default: '' + + - name: TCPConnectionStringAASSGX + type: string + default: '' + + - name: EnclaveEnabled + type: boolean + default: false + + - name: TracingEnabled + type: boolean + default: false + + - name: AADAuthorityURL + type: string + default: '' + + - name: AADPasswordConnectionString + type: string + default: '' + + - name: AADServicePrincipalId + type: string + default: '' + + - name: AADServicePrincipalSecret + type: string + default: '' + + - name: AzureKeyVaultUrl + type: string + default: '' + + - name: AzureKeyVaultTenantId + type: string + default: '' + + - name: UseManagedSNIOnWindows + type: boolean + default: false + + - name: UserManagedIdentityClientId + type: string + default: '' + + - name: FileStreamDirectory + type: string + default: '' + + - name: LocalDbAppName + type: string + default: '' + + - name: LocalDbSharedInstanceName + type: string + default: '' + + - name: AliasName + type: string + default: '' + + - name: SupportsIntegratedSecurity + type: boolean + default: false + + - name: SupportsFileStream + type: boolean + default: false + + - name: DNSCachingConnString + type: string + default: '' + + - name: DNSCachingServerCR + type: string + default: '' + + - name: DNSCachingServerTR + type: string + default: '' + + - name: EnclaveAzureDatabaseConnString + type: string + default: '' + + - name: IsDNSCachingSupportedCR + type: boolean + default: false + + - name: IsDNSCachingSupportedTR + type: boolean + default: false + + - name: IsAzureSynapse + type: boolean + default: false + + - name: ManagedIdentitySupported + type: boolean + default: true + +steps: +# All properties should be added here, and this template should be used for any manipulation of the config.json file. +- powershell: | + $jdata = Get-Content -Raw "config.default.json" | ConvertFrom-Json + foreach ($p in $jdata) + { + $p.TCPConnectionString="${{parameters.TCPConnectionString }}" + + $p.NPConnectionString="${{parameters.NPConnectionString }}" + + $p.AADAuthorityURL="${{parameters.AADAuthorityURL }}" + + $p.AADPasswordConnectionString="${{parameters.AADPasswordConnectionString }}" + + $p.AADServicePrincipalId="${{parameters.AADServicePrincipalId }}" + + $p.AADServicePrincipalSecret="${{parameters.AADServicePrincipalSecret }}" + + $p.AzureKeyVaultUrl="${{parameters.AzureKeyVaultUrl }}" + + $p.AzureKeyVaultTenantId="${{parameters.AzureKeyVaultTenantId }}" + + $p.UserManagedIdentityClientId="${{parameters.UserManagedIdentityClientId }}" + + $p.FileStreamDirectory="${{parameters.FileStreamDirectory }}" + + $p.LocalDbSharedInstanceName="${{parameters.LocalDbSharedInstanceName }}" + + $p.AliasName="${{parameters.AliasName }}" + + $p.EnclaveAzureDatabaseConnString="${{parameters.EnclaveAzureDatabaseConnString }}" + + $p.DNSCachingServerTR="${{parameters.DNSCachingServerTR }}" + + $p.DNSCachingServerCR="${{parameters.DNSCachingServerCR }}" + + $p.DNSCachingConnString="${{parameters.DNSCachingConnString }}" + + $p.SupportsFileStream="${{parameters.SupportsFileStream }}" + + $p.LocalDbAppName="${{parameters.LocalDbAppName }}" + + $p.TCPConnectionStringAASSGX="${{parameters.TCPConnectionStringAASSGX }}" + + $p.TCPConnectionStringNoneVBS="${{parameters.TCPConnectionStringNoneVBS }}" + + $p.TCPConnectionStringHGSVBS="${{parameters.TCPConnectionStringHGSVBS }}" + + $p.UseManagedSNIOnWindows=[System.Convert]::ToBoolean("${{parameters.UseManagedSNIOnWindows }}") + $p.SupportsIntegratedSecurity=[System.Convert]::ToBoolean("${{parameters.SupportsIntegratedSecurity }}") + $p.ManagedIdentitySupported=[System.Convert]::ToBoolean("${{parameters.ManagedIdentitySupported }}") + $p.IsAzureSynapse=[System.Convert]::ToBoolean("${{parameters.IsAzureSynapse }}") + $p.IsDNSCachingSupportedTR=[System.Convert]::ToBoolean("${{parameters.IsDNSCachingSupportedTR }}") + $p.IsDNSCachingSupportedCR=[System.Convert]::ToBoolean("${{parameters.IsDNSCachingSupportedCR }}") + $p.TracingEnabled=[System.Convert]::ToBoolean("${{parameters.TracingEnabled }}") + $p.EnclaveEnabled=[System.Convert]::ToBoolean("${{parameters.EnclaveEnabled }}") + } + $jdata | ConvertTo-Json | Set-Content "config.json" + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities + displayName: 'Update config.json' + +- ${{ if eq(parameters.debug, true) }}: + - powershell: | + $jdata = Get-Content -Raw "config.json" | ConvertFrom-Json + foreach ($p in $jdata) + { + foreach ($prop in $p.PSObject.Properties) + { + Write-Host "Property: $($prop.Name) Value: $($prop.Value)" + } + } + workingDirectory: src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities + displayName: 'Read config.json [debug]' diff --git a/eng/pipelines/common/templates/steps/update-nuget-config-local-feed-step.yml b/eng/pipelines/common/templates/steps/update-nuget-config-local-feed-step.yml new file mode 100644 index 0000000000..6f5a528345 --- /dev/null +++ b/eng/pipelines/common/templates/steps/update-nuget-config-local-feed-step.yml @@ -0,0 +1,89 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: + - name: debug + type: boolean + default: false + + - name: downloadedNugetPath # path to the downloaded nuget files + type: string + + - name: nugetPackageVersion + type: string + default: $(NugetPackageVersion) + +steps: +- powershell: | + # Get a list of package sources available + Get-PackageSource + + #Current location + Get-Location + + # Register the local nuget folder to be used by nuget.config + Register-PackageSource -Name "Package Source" -Location ${{parameters.downloadedNugetPath }} -Force -ProviderName NuGet -Trusted + + # Get a list of package sources available after the change + Get-PackageSource + + #Set the NuGet.config file in the project to use extracted package + $rootFolder = Get-location + [Xml] $nugetConfig = Get-Content -Path "NuGet.config" + $Value = Resolve-Path ${{parameters.downloadedNugetPath }} + $newAdd = $nugetConfig.CreateElement("add") + $newAdd.SetAttribute("key","Package source") + $newAdd.SetAttribute("value", "$Value/" ) + $nugetConfig.configuration.packageSources.AppendChild($newAdd) + $nugetConfig.Save("$rootFolder/NuGet.config") + displayName: 'Update NuGet config file to read from Nuget folder' + +- ${{ if parameters.debug }}: + - powershell: | + # Display the content of the NuGet.config file + Get-Content -Path "NuGet.config" + displayName: 'Read NuGet.config [debug]' + +- task: DotNetCoreCLI@2 + displayName: 'Restore NuGets' + inputs: + command: 'custom' + custom: 'msbuild' + arguments: 'build.proj -t:restore' + feedsToUse: 'select' + +- powershell: | + $Doc = [xml](Get-Content "./Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj") + $parent_xpath = '/Project/ItemGroup/ProjectReference' + $node = $Doc.SelectSingleNode($parent_xpath) + $parentNode = $node.ParentNode + while($node -ne $null) { + $node.ParentNode.RemoveChild($node) + $node = $Doc.SelectSingleNode($parent_xpath) + } + + $parent_xpath = '/Project/ItemGroup/PackageReference[@Include="Microsoft.Data.SqlClient"]' + $node = $Doc.SelectSingleNode($parent_xpath) + + if($node -ne $null){ + $node.Version="${{parameters.nugetPackageVersion }}" + } + else{ + $packagerefnode = $doc.createelement("packagereference") + $value = $doc.selectsinglenode('/project/itemgroup/projectreference') + $attrinclude = $doc.createattribute("include") + $attrinclude.value = "microsoft.data.sqlclient" + $attrversion = $doc.createattribute("version") + $attrversion.value = "${{parameters.nugetPackageVersion }}" + $packagerefnode.attributes.append($attrinclude) + $packagerefnode.attributes.append($attrversion) + $parentNode.AppendChild($packageRefNode) + } + + $currentFolder = Get-Location + $filePath = Join-Path $currentFolder "Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj" + $Doc.Save($filePath) + workingDirectory: 'src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider' + displayName: 'Update AKV Project Ref to Package Ref (.NET Framework/Core)' diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml new file mode 100644 index 0000000000..52e302c347 --- /dev/null +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -0,0 +1,388 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +- name: targetFrameworks + displayName: 'Target Frameworks on Windows' + type: object + default: [net462, net6.0, net8.0] + +- name: targetFrameworksLinux + displayName: 'Target Frameworks on Non-Windows' + type: object + default: [net6.0, net8.0] + +- name: buildPlatforms + displayName: 'Build Platforms on Windows' + type: object + default: [AnyCPU] + +- name: testSets + displayName: 'Test Sets' + type: object + default: [1, 2, 3] + +- name: useManagedSNI + displayName: | + Use Managed/Native SNI on Windows, + values [false, true], [false] or [true] are allowed + type: object + default: [false, true] + +- name: codeCovTargetFrameworks + displayName: 'Code Coverage Target Frameworks' + type: object + default: [net462, net6.0] + +- name: buildType + displayName: 'Build Type' + default: Project + values: + - Project + - Package + +- name: defaultPoolName + type: string + default: $(ci_var_defaultPoolName) + +variables: + - template: libraries/ci-build-variables.yml@self + + - name: artifactName + value: Artifacts + + - name: defaultHostedPoolName + value: 'Azure Pipelines' + +stages: + - stage: build_nugets + displayName: 'Build NuGet Packages' + jobs: + - template: common/templates/jobs/ci-build-nugets-job.yml@self + parameters: + artifactName: $(artifactName) + + - template: common/templates/stages/ci-run-tests-stage.yml@self + parameters: + debug: ${{ parameters.debug }} + buildType: ${{ parameters.buildType }} + ${{ if eq(parameters.buildType, 'Package') }}: + dependsOn: build_nugets + + prebuildSteps: # steps to run prior to building and running tests on each job + - template: common/templates/steps/ci-prebuild-step.yml@self + parameters: + debug: ${{ parameters.debug }} + artifactName: $(artifactName) + buildType: ${{ parameters.buildType }} + + ${{ if eq(parameters.buildType, 'Project') }}: # only run the code coverage job if the build type is project + postTestJobs: # jobs to run after the tests are done + - template: common/templates/jobs/ci-code-coverage-job.yml@self + parameters: + debug: ${{ parameters.debug }} + downloadArtifactsSteps: + - ${{ each targetFramework in parameters.codeCovTargetFrameworks }}: + - task: DownloadPipelineArtifact@2 + displayName: 'Download Coverage Reports [${{ targetFramework }}]' + inputs: + itemPattern: '**\${{ targetFramework }}*' + ${{ if contains(targetFramework, 'net4') }}: + targetPath: '$(Build.SourcesDirectory)\coverageNetFx' + ${{ else }}: + targetPath: '$(Build.SourcesDirectory)\coverageNetCore' + +# test stages configurations + # self hosted SQL Server on Windows + testConfigurations: + windows_sql_19: # configuration name + pool: ${{parameters.defaultPoolName }} # pool name + hostedPool: false # whether the pool is hosted or not + images: # list of images to run tests on + Win22_Sql19: ADO-MMS22-SQL19 # stage display name: image name from the pool + TargetFrameworks: ${{parameters.targetFrameworks }} #[net462, net6.0, net8.0] # list of target frameworks to run + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: ${{parameters.testSets }} # [1, 2, 3] # list of test sets to run + useManagedSNI: ${{parameters.useManagedSNI }} # can be used for .NET Core only tests on Windows: [false, true], [false] or [true] values are allowed + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} # targeted frameworks that is going to participate in test result report generation + configSqlFor: local # setup Sql Server (local | azure | enclave) + operatingSystem: Windows # operating system to run tests on (Windows | Linux | Mac) + configProperties: + # config.json properties + TCPConnectionString: $(SQL_TCP_CONN_STRING) + NPConnectionString: $(SQL_NP_CONN_STRING) + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: $(SupportsIntegratedSecurity) + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + FileStreamDirectory: $(FileStreamDirectory) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + AliasName: $(SQLAliasName) + # extra config properties + x86TestTargetFrameworks: [net6.0] # target frameworks should run tests on x86 as well + SQLRootPath: $(SQL19RootPath) + enableLocalDB: true + # instanceName: default: MSSQLSERVER + # user: default: $(user) + # saUser: default: $(saUser) + # password: default: $(password) + # fileStreamDirectory: default: '' + # x64AliasRegistryPath: default: $(x64AliasRegistryPath) + # x86AliasRegistryPath: default: $(x86AliasRegistryPath) + # SQLAliasName: default: $(SQLAliasName) + # SQLAliasPort: default: $(SQLAliasPort) + # targetNetCoreVersion: default: $(MainTargetNetCoreVersion) + # databaseName: default: Northwind + # localDbAppName: default: $(LocalDbAppName) + # localDbSharedInstanceName: default: $(LocalDbSharedInstanceName) + # skipSqlConfiguration: # skips the SQL configuration step + + windows_sql_22: + pool: ${{parameters.defaultPoolName }} + images: + Win22_Sql22: ADO-MMS22-SQL22 + TargetFrameworks: ${{parameters.targetFrameworks }} + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: ${{parameters.testSets }} + useManagedSNI: ${{parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: local + operatingSystem: Windows + configProperties: + # config.json properties + TCPConnectionString: $(SQL_TCP_CONN_STRING) + NPConnectionString: $(SQL_NP_CONN_STRING) + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: $(SupportsIntegratedSecurity) + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + FileStreamDirectory: $(FileStreamDirectory) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + AliasName: $(SQLAliasName) + # extra config properties + x86TestTargetFrameworks: [net462] # target frameworks should run tests on x86 as well + SQLRootPath: $(SQL22RootPath) + enableLocalDB: true + + windows_sql_22_named_instance: + pool: ${{parameters.defaultPoolName }} + images: + Win22_Sql22_named_instance: ADO-MMS22-SQL22-WITH-NAMED-INSTANCE + TargetFrameworks: ${{parameters.targetFrameworks }} + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: ${{parameters.testSets }} + useManagedSNI: ${{parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: local + operatingSystem: Windows + configProperties: + # config.json properties + TCPConnectionString: $(SQL_TCP_INSTANCE_CONN_STRING) + NPConnectionString: $(SQL_NP_INSTANCE_CONN_STRING) + SupportsIntegratedSecurity: $(SupportsIntegratedSecurity) + # extra config properties + SQLRootPath: $(SQL22RootPath) + instanceName: $(NamedInstance) + + # Azure SQL Server - Windows + windows_azure_sql: + pool: ${{parameters.defaultPoolName }} + images: + Win22_Azure_Sql: ADO-MMS22-SQL19 + win11_Azure_Sql: ADO-CI-Win11 + TargetFrameworks: ${{parameters.targetFrameworks }} + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: ${{parameters.testSets }} + useManagedSNI: ${{parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: azure + operatingSystem: Windows + configProperties: + # config.json properties + TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING) + NPConnectionString: $(AZURE_DB_NP_CONN_STRING) + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: false + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + + windows_azure_arm64_sql: + pool: ADO-CI-PUBLIC-ARM64-1ES-EUS-POOL + images: + Win22_Azure_ARM64_Sql: ADO-WIN11-ARM64 + TargetFrameworks: ${{parameters.targetFrameworks }} + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: ${{parameters.testSets }} + useManagedSNI: ${{parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: azure + operatingSystem: Windows + configProperties: + # config.json properties + TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING_eastus) + NPConnectionString: $(AZURE_DB_NP_CONN_STRING_eastus) + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR_eastus) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: false + UserManagedIdentityClientId: $(UserManagedIdentityClientId_eastus) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + + windows_enclave_sql: + pool: ADO-CI-AE-1ES-Pool + images: + Win22_Enclave_Sql19: ADO-MMS22-SQL19 + TargetFrameworks: ${{parameters.targetFrameworks }} + buildPlatforms: ${{parameters.buildPlatforms }} + testSets: [AE] + useManagedSNI: ${{parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: enclave + operatingSystem: Windows + configProperties: + # config.json properties + TCPConnectionStringHGSVBS: $(SQL_TCP_CONN_STRING_HGSVBS) + TCPConnectionStringNoneVBS: $(SQL_TCP_CONN_STRING_NoneVBS) + TCPConnectionStringAASSGX: $(SQL_TCP_CONN_STRING_AASSGX) + EnclaveEnabled: true + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: $(SupportsIntegratedSecurity) + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + AliasName: $(SQLAliasName) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + + # self hosted SQL Server on Linux + linux_sql_19_22: + pool: ${{parameters.defaultPoolName }} + images: + Ubuntu20_Sql19: ADO-UB20-Sql19 + Ubuntu20_Sql22: ADO-UB2004-SQL2022 + TargetFrameworks: ${{parameters.targetFrameworksLinux }} + buildPlatforms: [AnyCPU] + testSets: ${{parameters.testSets }} + useManagedSNI: [true] + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: local + operatingSystem: Linux + configProperties: + # config.json properties + TCPConnectionString: $(SQL_TCP_CONN_STRING) + NPConnectionString: $(SQL_NP_CONN_STRING) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: false + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + AliasName: $(SQLAliasName) + + # Azure Sql Server - Linux + linux_azure_sql: + pool: ${{parameters.defaultPoolName }} + images: + Ubuntu20_Azure_Sql: ADO-UB20-Sql19 + TargetFrameworks: ${{parameters.targetFrameworksLinux }} + buildPlatforms: [AnyCPU] + testSets: ${{parameters.testSets }} + useManagedSNI: [true] + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: azure + operatingSystem: Linux + configProperties: + # config.json properties + TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING) + NPConnectionString: $(AZURE_DB_NP_CONN_STRING) + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: false + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + + linux_enclave_sql: + pool: ADO-CI-AE-1ES-Pool + images: + Ubuntu20_Enclave_Sql19: ADO-UB20-Sql19 + TargetFrameworks: ${{parameters.targetFrameworksLinux }} + buildPlatforms: [AnyCPU] + testSets: [AE] + useManagedSNI: [true] + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: enclave + operatingSystem: Linux + configProperties: + # config.json properties + TCPConnectionStringHGSVBS: $(SQL_TCP_CONN_STRING_HGSVBS) + TCPConnectionStringNoneVBS: $(SQL_TCP_CONN_STRING_NoneVBS) + TCPConnectionStringAASSGX: $(SQL_TCP_CONN_STRING_AASSGX) + EnclaveEnabled: true + AADAuthorityURL: $(AADAuthorityURL) + AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalSecret: $(AADServicePrincipalSecret) + AzureKeyVaultUrl: $(AzureKeyVaultUrl) + AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) + SupportsIntegratedSecurity: false + UserManagedIdentityClientId: $(UserManagedIdentityClientId) + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + + # Azure Sql Server - Mac + mac_azure_sql: + pool: $(defaultHostedPoolName) + hostedPool: true + images: + MacOS12_Azure_Sql: macOS-12 + TargetFrameworks: ${{parameters.targetFrameworksLinux }} + buildPlatforms: [AnyCPU] + testSets: ${{parameters.testSets }} + useManagedSNI: [true] + codeCovTargetFrameworks: ${{parameters.codeCovTargetFrameworks }} + configSqlFor: azure + operatingSystem: Mac + configProperties: + # config.json properties + TCPConnectionString: $(AZURE_DB_SP_TCP_CONN_STRING) + NPConnectionString: $(AZURE_DB_SP_NP_CONN_STRING) + SupportsIntegratedSecurity: false + ManagedIdentitySupported: false + LocalDbAppName: $(LocalDbAppName) + LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) diff --git a/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml new file mode 100644 index 0000000000..20c2102f23 --- /dev/null +++ b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml @@ -0,0 +1,94 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +name: $(DayOfYear)$(Rev:rr) +trigger: + batch: true + branches: + include: + - main + - internal/main + paths: + include: + - src\Microsoft.Data.SqlClient\netcore\ref + - src\Microsoft.Data.SqlClient\netfx\ref + - src\Microsoft.Data.SqlClient\ref + - eng + - tools + - .config + - Nuget.config + +schedules: +- cron: '0 4 * * Fri' + displayName: Weekly Thursday 9:00 PM (UTC - 7) Build + branches: + include: + - internal/main + always: true + +- cron: '0 0 * * Mon-Fri' + displayName: Daily build 5:00 PM (UTC - 7) Build + branches: + include: + - main + always: true + +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +- name: targetFrameworks + displayName: 'Target Frameworks on Windows' + type: object + default: [net462, net6.0, net8.0] + +- name: targetFrameworksLinux + displayName: 'Target Frameworks on Non-Windows' + type: object + default: [net6.0, net8.0] + +- name: buildPlatforms + displayName: 'Build Platforms on Windows' + type: object + default: [AnyCPU] + +- name: testSets + displayName: 'Test Sets' + type: object + default: [1, 2, 3] + +- name: useManagedSNI + displayName: | + Use Managed/Native SNI on Windows, + values [false, true], [false] or [true] are allowed + type: object + default: [false, true] + +- name: codeCovTargetFrameworks + displayName: 'Code Coverage Target Frameworks' + type: object + default: [net462, net6.0] + +- name: buildType + displayName: 'Build Type' + default: Package + values: + - Project + - Package + +extends: + template: dotnet-sqlclient-ci-core.yml@self + parameters: + debug: ${{ parameters.debug }} + targetFrameworks: ${{ parameters.targetFrameworks }} + targetFrameworksLinux: ${{ parameters.targetFrameworksLinux }} + buildPlatforms: ${{ parameters.buildPlatforms }} + testSets: ${{ parameters.testSets }} + useManagedSNI: ${{ parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{ parameters.codeCovTargetFrameworks }} + buildType: ${{ parameters.buildType }} diff --git a/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml new file mode 100644 index 0000000000..c1ce940d69 --- /dev/null +++ b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml @@ -0,0 +1,86 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +name: $(DayOfYear)$(Rev:rr) +trigger: + batch: true + branches: + include: + - main + - internal/main + paths: + include: + - src + - eng + - tools + - .config + - build.proj + - Nuget.config + +schedules: +- cron: '0 5 * * Thu' + displayName: Weekly Wednesday 10:00 PM (UTC - 7) Build + branches: + include: + - internal/main + always: true + +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +- name: targetFrameworks + displayName: 'Target Frameworks on Windows' + type: object + default: [net462, net6.0, net8.0] + +- name: targetFrameworksLinux + displayName: 'Target Frameworks on Non-Windows' + type: object + default: [net6.0, net8.0] + +- name: buildPlatforms + displayName: 'Build Platforms on Windows' + type: object + default: [AnyCPU] + +- name: testSets + displayName: 'Test Sets' + type: object + default: [1, 2, 3] + +- name: useManagedSNI + displayName: | + Use Managed/Native SNI on Windows, + values [false, true], [false] or [true] are allowed + type: object + default: [false, true] + +- name: codeCovTargetFrameworks + displayName: 'Code Coverage Target Frameworks' + type: object + default: [net462, net6.0] + +- name: buildType + displayName: 'Build Type' + default: Project + values: + - Project + - Package + +extends: + template: dotnet-sqlclient-ci-core.yml@self + parameters: + debug: ${{ parameters.debug }} + targetFrameworks: ${{ parameters.targetFrameworks }} + targetFrameworksLinux: ${{ parameters.targetFrameworksLinux }} + buildPlatforms: ${{ parameters.buildPlatforms }} + testSets: ${{ parameters.testSets }} + useManagedSNI: ${{ parameters.useManagedSNI }} + codeCovTargetFrameworks: ${{ parameters.codeCovTargetFrameworks }} + buildType: ${{ parameters.buildType }} diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml new file mode 100644 index 0000000000..124741642c --- /dev/null +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -0,0 +1,174 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +name: $(Year:YY)$(DayOfYear)$(Rev:.r) +trigger: + branches: + include: + - internal/main + paths: + include: + - src + - eng + - tools + - .config + - build.proj + - Nuget.config + - '*.cmd' + - '*.sh' + +schedules: +- cron: '30 4 * * Mon' + displayName: Weekly Sunday 9:30 PM (UTC - 7) Build + branches: + include: + - internal/main + always: true + +- cron: '30 3 * * Mon-Fri' + displayName: Mon-Fri 8:30 PM (UTC - 7) Build + branches: + include: + - internal/main + +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: true + +- name: publishSymbols + displayName: 'Publish symbols' + type: boolean + default: false + +- name: MDS_PackageRef_Version + displayName: 'MDS package version of AKV Provider (build AKV)' + type: string + default: 5.1.5 + +- name: CurrentNetFxVersion + displayName: 'Lowest supported .NET Framework version (MDS validation)' + type: string + default: 'net462' + +- name: oneBranchType + displayName: 'Select OneBranch template' + default: Official + values: + - NonOfficial + - Official + +- name: isPreview + displayName: 'Is this a preview build?' + type: boolean + default: false + +variables: + - template: /eng/pipelines/libraries/variables.yml@self + - name: packageFolderName + value: drop_buildMDS_build_signed_package + - name: PublishSymbols + value: ${{ parameters['publishSymbols'] }} + - name: MDS_PackageRef_Version + value: ${{ parameters['MDS_PackageRef_Version'] }} + - name: CurrentNetFxVersion + value: ${{ parameters['CurrentNetFxVersion'] }} + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +extends: + template: v2/OneBranch.${{parameters.oneBranchType }}.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates + parameters: + featureFlags: + WindowsHostVersion: 1ESWindows2022 + globalSdl: # https://aka.ms/obpipelines/sdl + apiscan: + enabled: ${{ not(parameters['isPreview']) }} + softwareFolder: $(softwareFolder) + symbolsFolder: $(symbolsFolder) + softwarename: Microsoft.Data.SqlClient + versionNumber: $(AssemblyFileVersion) + tsa: + enabled: ${{ not(parameters['isPreview']) }} # onebranch publish all sdl results to TSA. If TSA is disabled all SDL tools will forced into 'break' build mode. + codeql: + compiled: + enabled: ${{ not(parameters['isPreview']) }} + sbom: + enabled: ${{ not(parameters['isPreview']) }} + packageName: Microsoft.Data.SqlClient + packageVersion: $(NugetPackageVersion) + policheck: + enabled: ${{ not(parameters['isPreview']) }} + break: true # always break the build on policheck issues. You can disable it by setting to 'false' + exclusionsFile: $(REPOROOT)\.config\PolicheckExclusions.xml + asyncSdl: + enabled: false + credscan: + enabled: ${{ not(parameters['isPreview']) }} + suppressionsFile: $(REPOROOT)/.config/CredScanSuppressions.json + binskim: + enabled: ${{ not(parameters['isPreview']) }} + armory: + enabled: ${{ not(parameters['isPreview']) }} + break: true + eslint: # TypeScript and JavaScript + enabled: false + roslyn: + enabled: ${{ not(parameters['isPreview']) }} + break: true + publishLogs: + enabled: ${{ not(parameters['isPreview']) }} + tsaOptionsPath: $(REPOROOT)\.config\tsaoptions.json + disableLegacyManifest: true + stages: + - stage: buildAKV + displayName: 'Build AKV Provider' + jobs: + - template: eng/pipelines/common/templates/jobs/build-signed-akv-package-job.yml@self + parameters: + symbolsFolder: $(symbolsFolder) + softwareFolder: $(softwareFolder) + publishSymbols: ${{ parameters['publishSymbols'] }} + + - stage: buildMDS + displayName: 'Build MDS' + jobs: + - template: eng/pipelines/common/templates/jobs/build-signed-package-job.yml@self + parameters: + symbolsFolder: $(symbolsFolder) + softwareFolder: $(softwareFolder) + publishSymbols: ${{ parameters['publishSymbols'] }} + isPreview: ${{ parameters['isPreview'] }} + + - stage: mds_package_validation + displayName: 'MDS Package Validation' + dependsOn: buildMDS + jobs: + - template: eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self + parameters: + packageFolderName: $(packageFolderName) + isPreview: ${{ parameters['isPreview'] }} + downloadPackageStep: + download: current + artifact: $(packageFolderName) + patterns: '**/*.*nupkg' + displayName: 'Download NuGet Package' + + - template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self + parameters: + packageFolderName: $(packageFolderName) + isPreview: ${{ parameters['isPreview'] }} + downloadPackageStep: + download: current + artifact: $(packageFolderName) + patterns: '**/*.nupkg' + displayName: 'Download NuGet Package' diff --git a/eng/pipelines/libraries/akv-variables.yml b/eng/pipelines/libraries/akv-variables.yml new file mode 100644 index 0000000000..259ae19dba --- /dev/null +++ b/eng/pipelines/libraries/akv-variables.yml @@ -0,0 +1,15 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - group: AKV Release Variables + + - name: AKVNugetPackageVersion + value: $(AKVMajor).$(AKVMinor).$(AKVPatch) + - name: AKVAssemblyFileVersion + value: '$(AKVMajor).$(AKVMinor)$(AKVPatch).$(Build.BuildNumber)' + - name: akvNuspecPath + value: tools/specs/add-ons/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.nuspec diff --git a/eng/pipelines/libraries/build-variables.yml b/eng/pipelines/libraries/build-variables.yml new file mode 100644 index 0000000000..1c26f26a69 --- /dev/null +++ b/eng/pipelines/libraries/build-variables.yml @@ -0,0 +1,10 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - template: common-variables.yml@self + - template: akv-variables.yml@self + - template: mds-variables.yml@self diff --git a/eng/pipelines/libraries/ci-build-variables.yml b/eng/pipelines/libraries/ci-build-variables.yml new file mode 100644 index 0000000000..d9e100f635 --- /dev/null +++ b/eng/pipelines/libraries/ci-build-variables.yml @@ -0,0 +1,25 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - group: 'ADO Build properties' + - group: 'ADO CI Packaging' + - group: 'ADO Test Configuration Properties' + + - name: buildNumber + value: '$(Build.BuildNumber)' + - name: TFNetCore + value: 'net6.0' + - name: SQLTarget + value: 'localhost' + - name: NugetPackageVersion + value: $(Major).$(Minor)$(Patch)-pull.1$(buildnumber) + - name: skipComponentGovernanceDetection + value: true + - name: runCodesignValidationInjection + value: false + - name: packagePath + value: '$(Build.SourcesDirectory)/packages' diff --git a/eng/pipelines/libraries/common-variables.yml b/eng/pipelines/libraries/common-variables.yml new file mode 100644 index 0000000000..7b2bc00cb1 --- /dev/null +++ b/eng/pipelines/libraries/common-variables.yml @@ -0,0 +1,23 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - name: Configuration + value: Release + - name: CommitHead + value: '' # the value will be extracted from the repo's head + - name: REPOROOT + value: $(Build.SourcesDirectory) + - name: softwareFolder + value: $(REPOROOT)/software + - name: symbolsFolder + value: $(REPOROOT)/symbols + - name: artifactDirectory + value: '$(REPOROOT)/packages' + - name: appRegistrationClientId + value: 'a0d18a38-fde1-4ba7-92e1-15be16cb6a8e' + - name: appRegistrationTenantId + value: '72f988bf-86f1-41af-91ab-2d7cd011db47' diff --git a/eng/pipelines/libraries/mds-validation-variables.yml b/eng/pipelines/libraries/mds-validation-variables.yml new file mode 100644 index 0000000000..667f56aa6a --- /dev/null +++ b/eng/pipelines/libraries/mds-validation-variables.yml @@ -0,0 +1,36 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - template: common-variables.yml@self + - template: mds-variables.yml@self + + - name: TempFolderName # extract the nuget package here + value: temp + - name: extractedNugetRootPath + value: $(Build.SourcesDirectory)\$(TempFolderName)\Microsoft.Data.SqlClient + - name: extractedNugetPath + value: $(extractedNugetRootPath).$(NugetPackageVersion) + - name: expectedFolderNames + value: lib,ref,runtimes + - name: expectedDotnetVersions + value: net462,net6.0,net8.0 + - name: Database + value: Northwind + - name: platform + value: AnyCPU + - name: TargetNetFxVersion + value: net481 + - name: TargetNetCoreVersion + value: net8.0 + - name: SQLTarget + value: localhost + - name: encrypt + value: false + - name: SQL_NP_CONN_STRING + value: Data Source=np:$(SQLTarget);Initial Catalog=$(Database);Integrated Security=true;Encrypt=$(ENCRYPT);TrustServerCertificate=true; + - name: SQL_TCP_CONN_STRING + value: Data Source=tcp:$(SQLTarget);Initial Catalog=$(Database);Integrated Security=true;Encrypt=$(ENCRYPT);TrustServerCertificate=true; diff --git a/eng/pipelines/libraries/mds-variables.yml b/eng/pipelines/libraries/mds-variables.yml new file mode 100644 index 0000000000..551e9b63a9 --- /dev/null +++ b/eng/pipelines/libraries/mds-variables.yml @@ -0,0 +1,17 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - group: Release Variables + + - name: NugetPackageVersion + value: $(Major).$(Minor).$(Patch) + - name: PreviewNugetPackageVersion + value: $(Major).$(Minor).$(Patch)$(Preview)$(Revision).$(Build.BuildNumber) + - name: AssemblyFileVersion + value: '$(Major).$(Minor)$(Patch).$(Build.BuildNumber)' + - name: nuspecPath + value: '$(REPOROOT)/tools/specs/Microsoft.Data.SqlClient.nuspec' diff --git a/eng/pipelines/libraries/variables.yml b/eng/pipelines/libraries/variables.yml new file mode 100644 index 0000000000..57894459d3 --- /dev/null +++ b/eng/pipelines/libraries/variables.yml @@ -0,0 +1,17 @@ +################################################################################# +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################# + +variables: + - template: build-variables.yml@self + # onebranch template variables + - name: ob_outputDirectory + value: '$(artifactDirectory)' # this directory is uploaded to pipeline artifacts, reddog and cloudvault. More info at https://aka.ms/obpipelines/artifacts + - name: ob_sdl_binskim_break + value: true # https://aka.ms/obpipelines/sdl + - name: Packaging.EnableSBOMSigning + value: true + - name: WindowsContainerImage + value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' # Docker image which is used to build the project https://aka.ms/obpipelines/containers diff --git a/porting-cheat-sheet.md b/porting-cheat-sheet.md index d09c16c77e..f0c4dc584f 100644 --- a/porting-cheat-sheet.md +++ b/porting-cheat-sheet.md @@ -53,6 +53,12 @@ For .NET Framework projects it may be necessary to include the following in your | Using DateTime object as value for SqlParameter with type `DbType.Date` would send date and time to SQL Server. | DateTime object's time components will be truncated when sent to SQL Server using `DbType.Date`. | | `Encrypt` defaults to `false`. | Starting in v4.0, default encryption settings were made more secure, requiring opt-in to non-encrypted connections. `Encrypt` defaults to `true` and the driver will always validate the server certificate based on `TrustServerCertificate`. (Previously, server certificates would only be validated if `Encrypt` was also `true`.)

If you need to turn off encryption, you must specify `Encrypt=false`. If you use encryption with a self-signed certificate on the server, you must specify `TrustServerCertificate=true`.

In v5.0, `SqlConnectionStringBuilder.Encrypt` is no longer a `bool`. It's a `SqlConnectionEncryptOption` with multiple values to support `Strict` encryption mode (TDS 8.0). It uses implicit conversion operators to remain code-backwards compatible, but it was a binary breaking change, requiring a recompile of applications. | +## .NET Framework to .NET Considerations + +In .NET Framework and .NET versions prior to .NET 5, globalization APIs use National Language Support (NLS) on Windows. Starting in .NET 5, .NET globalization APIs changed to use International Components for Unicode (ICU) on Windows in order to be consistent across all platforms (Windows, Linux, macOS, etc.). This affects the behavior of comparisons of some SqlStrings in System.Data.SqlTypes. Comparisons using ICU don't always match NLS for some strings. Since SQL Server still uses NLS on the server side for string comparisons, this difference can result in SqlString comparisons behaving differently than server side string comparisons. If your application relies on SqlString behavior matching server side behavior, you need to resolve this issue. For detailed information in .NET, see [Globalization and ICU](https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu). + +If your application is affected, the workaround is to [Use NLS instead of ICU](https://learn.microsoft.com/en-us/dotnet/core/extensions/globalization-icu#use-nls-instead-of-icu) in your application. + ## Contribute to this Cheat Sheet We would love the SqlClient community to help enhance this cheat sheet by contributing experiences and challenges faced when porting their applications. diff --git a/release-notes/2.0/2.0.0-preview1.md b/release-notes/2.0/2.0.0-preview1.md index 5afdd97fb1..bb9918328d 100644 --- a/release-notes/2.0/2.0.0-preview1.md +++ b/release-notes/2.0/2.0.0-preview1.md @@ -22,7 +22,7 @@ This update brings the below changes over the previous release: - Improved performance of Managed SNI by enhancing utilization of resources [#173](https://github.com/dotnet/SqlClient/pull/173) - Ported [dotnet/corefx#35363](https://github.com/dotnet/corefx/pull/35363) and [dotnet/corefx#40732](https://github.com/dotnet/corefx/pull/40732) - Improved performance of Managed SNI RPC Parameter Usage [#209](https://github.com/dotnet/SqlClient/pull/209) - Ported [dotnet/corefx#34049](https://github.com/dotnet/corefx/pull/34049) - Changed enclave key map to be lazy initialized [#372](https://github.com/dotnet/SqlClient/pull/372) -- Changed `Recieve()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) +- Changed `Receive()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) - Changed `EnclaveProviderBase` caching implementation to support Async Scenarios _(Introduces breaking changes)_ [#346](https://github.com/dotnet/SqlClient/pull/346) ### Breaking Changes diff --git a/release-notes/2.0/2.0.0.md b/release-notes/2.0/2.0.0.md index 7059a015d0..e12b6583fd 100644 --- a/release-notes/2.0/2.0.0.md +++ b/release-notes/2.0/2.0.0.md @@ -81,7 +81,7 @@ All changes in Microsoft.Data.SqlClient v2.0 over v1.1: - Improved performance of Managed SNI by enhancing utilization of resources [#173](https://github.com/dotnet/SqlClient/pull/173) - Ported [dotnet/corefx#35363](https://github.com/dotnet/corefx/pull/35363) and [dotnet/corefx#40732](https://github.com/dotnet/corefx/pull/40732) - Improved performance of Managed SNI RPC Parameter Usage [#209](https://github.com/dotnet/SqlClient/pull/209) - Ported [dotnet/corefx#34049](https://github.com/dotnet/corefx/pull/34049) - Changed enclave key map to be lazy initialized [#372](https://github.com/dotnet/SqlClient/pull/372) -- Changed `Recieve()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) +- Changed `Receive()` and `ReceiveAsync()` implementation to receive null packets on failure [#350](https://github.com/dotnet/SqlClient/pull/350) - Changed `EnclaveProviderBase` caching implementation to support Async Scenarios _(Introduces breaking changes)_ [#346](https://github.com/dotnet/SqlClient/pull/346) - Updated all driver assemblies to be CLS Compliant [#396](https://github.com/dotnet/SqlClient/pull/396) - Updated Bulk Copy error messages to also include Column, Row and non-encrypted Data information [#437](https://github.com/dotnet/SqlClient/pull/437) diff --git a/release-notes/2.1/2.1.7.md b/release-notes/2.1/2.1.7.md new file mode 100644 index 0000000000..6117bf347c --- /dev/null +++ b/release-notes/2.1/2.1.7.md @@ -0,0 +1,81 @@ +# Release Notes + +## Microsoft.Data.SqlClient 2.1.7 released 9 January 2024 + +This update brings the below changes over the previous stable release: + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +### Target Platform Support + +- .NET Framework 4.6+ (Windows x86, Windows x64) +- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Ensure connections fail when encryption is required + +In scenarios where client encryption libraries were disabled or unavailable, it was possible for unencrypted connections to be made when Encrypt was set to true or the server required encryption. + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 2.1.1 +- Microsoft.Identity.Client 4.21.1 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Core 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 2.1.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Microsoft.Identity.Client 4.21.1 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Core 3.1 + +- Microsoft.Data.SqlClient.SNI.runtime 2.1.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Microsoft.Identity.Client 4.21.1 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Standard 2.0 + +- Microsoft.Data.SqlClient.SNI.runtime 2.1.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Buffers 4.5.1 +- System.Memory 4.5.4 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Runtime.Caching 4.7.0 +- Microsoft.Identity.Client 4.21.1 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Standard 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 2.1.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Buffers 4.5.1 +- System.Memory 4.5.4 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Runtime.Caching 4.7.0 +- Microsoft.Identity.Client 4.21.1 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 diff --git a/release-notes/2.1/2.1.md b/release-notes/2.1/2.1.md index 96cbf4cce0..395c19e60e 100644 --- a/release-notes/2.1/2.1.md +++ b/release-notes/2.1/2.1.md @@ -4,6 +4,7 @@ The following Microsoft.Data.SqlClient 2.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/01/09 | 2.1.7 | [release notes](2.1.7.md) | | 2023/04/27 | 2.1.6 | [release notes](2.1.6.md) | | 2022/08/30 | 2.1.5 | [release notes](2.1.5.md) | | 2021/09/20 | 2.1.4 | [release notes](2.1.4.md) | diff --git a/release-notes/2.1/README.md b/release-notes/2.1/README.md index 96cbf4cce0..395c19e60e 100644 --- a/release-notes/2.1/README.md +++ b/release-notes/2.1/README.md @@ -4,6 +4,7 @@ The following Microsoft.Data.SqlClient 2.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/01/09 | 2.1.7 | [release notes](2.1.7.md) | | 2023/04/27 | 2.1.6 | [release notes](2.1.6.md) | | 2022/08/30 | 2.1.5 | [release notes](2.1.5.md) | | 2021/09/20 | 2.1.4 | [release notes](2.1.4.md) | diff --git a/release-notes/3.1/3.1.4.md b/release-notes/3.1/3.1.4.md new file mode 100644 index 0000000000..712a873297 --- /dev/null +++ b/release-notes/3.1/3.1.4.md @@ -0,0 +1,78 @@ +# Release Notes + +## Microsoft.Data.SqlClient 3.1.4 released 31 October 2023 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) +- Fixed FormatException when event source tracing is enabled. [#1291](https://github.com/dotnet/SqlClient/pull/1291) + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework 4.6.1 + +- Microsoft.Data.SqlClient.SNI 3.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Core 3.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Buffers 4.5.1 +- System.Memory 4.5.4 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Loader 4.3.0 diff --git a/release-notes/3.1/3.1.5.md b/release-notes/3.1/3.1.5.md new file mode 100644 index 0000000000..b11176ebe0 --- /dev/null +++ b/release-notes/3.1/3.1.5.md @@ -0,0 +1,75 @@ +# Release Notes + +## Microsoft.Data.SqlClient 3.1.5 released 9 January 2024 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework 4.6.1 + +- Microsoft.Data.SqlClient.SNI 3.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Core 3.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.1 +- Microsoft.Win32.Registry 4.7.0 +- System.Buffers 4.5.1 +- System.Memory 4.5.4 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Loader 4.3.0 diff --git a/release-notes/3.1/3.1.7.md b/release-notes/3.1/3.1.7.md new file mode 100644 index 0000000000..b6a5db7132 --- /dev/null +++ b/release-notes/3.1/3.1.7.md @@ -0,0 +1,81 @@ +# Release Notes + +## Microsoft.Data.SqlClient 3.1.7 released 20 August 2024 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool. [#2301](https://github.com/dotnet/SqlClient/pull/2301) [#2434](https://github.com/dotnet/SqlClient/pull/2434) +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2709](https://github.com/dotnet/SqlClient/pull/2709) +- Fixed the signing issue with `Microsoft.Data.SqlClient` assembly. [#2789](https://github.com/dotnet/SqlClient/pull/2789) + +### Changed + +- Updated Microsoft.Data.SqlClient.SNI version 3.0.1 to 3.0.2 [#2676](https://github.com/dotnet/SqlClient/pull/2676) which includes the fix for AppDomain crashing in issue [#1418](https://github.com/dotnet/SqlClient/issues/1418) and various code refactors. +- Code health improvements: [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2515](https://github.com/dotnet/SqlClient/pull/2515), [#2517](https://github.com/dotnet/SqlClient/pull/2517) addresses [CVE-2019-0545](https://github.com/advisories/GHSA-2xjx-v99w-gqf3), [#2539](https://github.com/dotnet/SqlClient/pull/2539) + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework 4.6.1 + +- Microsoft.Data.SqlClient.SNI 3.0.2 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.2 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Core 3.1 + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.2 +- Microsoft.Win32.Registry 4.7.0 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Diagnostics.DiagnosticSource 4.7.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 3.0.2 +- Microsoft.Win32.Registry 4.7.0 +- System.Buffers 4.5.1 +- System.Memory 4.5.4 +- System.Security.Principal.Windows 4.7.0 +- System.Text.Encoding.CodePages 4.7.0 +- System.Text.Encodings.Web 4.7.2 +- System.Runtime.Caching 4.7.0 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- System.Configuration.ConfigurationManager 4.7.0 +- System.Runtime.Loader 4.3.0 diff --git a/release-notes/3.1/3.1.md b/release-notes/3.1/3.1.md index de9cc9f612..af831bde67 100644 --- a/release-notes/3.1/3.1.md +++ b/release-notes/3.1/3.1.md @@ -4,6 +4,9 @@ The following Microsoft.Data.SqlClient 3.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/20 | 3.1.7 | [release notes](3.1.7.md) | +| 2024/01/09 | 3.1.5 | [release notes](3.1.5.md) | +| 2023/10/31 | 3.1.4 | [release notes](3.1.4.md) | | 2023/03/10 | 3.1.3 | [release notes](3.1.3.md) | | 2023/02/03 | 3.1.2 | [release notes](3.1.2.md) | | 2022/08/12 | 3.1.1 | [release notes](3.1.1.md) | diff --git a/release-notes/3.1/README.md b/release-notes/3.1/README.md index de9cc9f612..af831bde67 100644 --- a/release-notes/3.1/README.md +++ b/release-notes/3.1/README.md @@ -4,6 +4,9 @@ The following Microsoft.Data.SqlClient 3.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/20 | 3.1.7 | [release notes](3.1.7.md) | +| 2024/01/09 | 3.1.5 | [release notes](3.1.5.md) | +| 2023/10/31 | 3.1.4 | [release notes](3.1.4.md) | | 2023/03/10 | 3.1.3 | [release notes](3.1.3.md) | | 2023/02/03 | 3.1.2 | [release notes](3.1.2.md) | | 2022/08/12 | 3.1.1 | [release notes](3.1.1.md) | diff --git a/release-notes/4.0/4.0.4.md b/release-notes/4.0/4.0.4.md new file mode 100644 index 0000000000..da0520dcc6 --- /dev/null +++ b/release-notes/4.0/4.0.4.md @@ -0,0 +1,73 @@ +# Release Notes + +## Microsoft.Data.SqlClient 4.0.4 released 30 October 2023 + +This update brings the below changes over the previous preview release: + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Security.Cryptography.Algorithms 4.3.1 +- System.Security.Cryptography.Primitives 4.3.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.Diagnostics.DiagnosticSource 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/4.0/4.0.5.md b/release-notes/4.0/4.0.5.md new file mode 100644 index 0000000000..38a11beb94 --- /dev/null +++ b/release-notes/4.0/4.0.5.md @@ -0,0 +1,71 @@ +# Release Notes + +## Microsoft.Data.SqlClient 4.0.5 released 9 January 2024 + +This update brings the below changes over the previous preview release: + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Security.Cryptography.Algorithms 4.3.1 +- System.Security.Cryptography.Primitives 4.3.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.Diagnostics.DiagnosticSource 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/4.0/4.0.6.md b/release-notes/4.0/4.0.6.md new file mode 100644 index 0000000000..6f80632ec6 --- /dev/null +++ b/release-notes/4.0/4.0.6.md @@ -0,0 +1,75 @@ +# Release Notes + +## Microsoft.Data.SqlClient 4.0.6 released 21 August 2024 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) [#2435](https://github.com/dotnet/SqlClient/pull/2435) +- Fixed AcquireTokenAsync timeout handling for edge cases in ActiveDirectoryAuthenticationProvider [#2707](https://github.com/dotnet/SqlClient/pull/2707) + +### Changed + +- Code health improvements: [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2513](https://github.com/dotnet/SqlClient/pull/2513), [#2519](https://github.com/dotnet/SqlClient/pull/2519) + +## Target Platform Support + +- .NET Framework 4.6.1+ (Windows x86, Windows x64) +- .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Security.Cryptography.Algorithms 4.3.1 +- System.Security.Cryptography.Primitives 4.3.0 +- System.Text.Encodings.Web 4.7.2 + +#### .NET Core + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.Diagnostics.DiagnosticSource 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 4.0.1 +- Azure.Identity 1.3.0 +- Microsoft.Identity.Client 4.22.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.8.0 +- Microsoft.IdentityModel.JsonWebTokens 6.8.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 5.0.0 +- System.IO 4.3.0 +- System.Runtime.Caching 5.0.0 +- System.Text.Encoding.CodePages 5.0.0 +- System.Text.Encodings.Web 4.7.2 +- System.Resources.ResourceManager 4.3.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/4.0/4.0.md b/release-notes/4.0/4.0.md index a39e188c44..98c70eb646 100644 --- a/release-notes/4.0/4.0.md +++ b/release-notes/4.0/4.0.md @@ -4,6 +4,9 @@ The following Microsoft.Data.SqlClient 4.0 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/21 | 4.0.6 | [release notes](4.0.6.md) | +| 2024/01/09 | 4.0.5 | [release notes](4.0.5.md) | +| 2023/10/30 | 4.0.4 | [release notes](4.0.4.md) | | 2023/04/20 | 4.0.3 | [release notes](4.0.3.md) | | 2022/09/13 | 4.0.2 | [release notes](4.0.2.md) | | 2022/01/17 | 4.0.1 | [release notes](4.0.1.md) | diff --git a/release-notes/4.0/README.md b/release-notes/4.0/README.md index a39e188c44..98c70eb646 100644 --- a/release-notes/4.0/README.md +++ b/release-notes/4.0/README.md @@ -4,6 +4,9 @@ The following Microsoft.Data.SqlClient 4.0 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/21 | 4.0.6 | [release notes](4.0.6.md) | +| 2024/01/09 | 4.0.5 | [release notes](4.0.5.md) | +| 2023/10/30 | 4.0.4 | [release notes](4.0.4.md) | | 2023/04/20 | 4.0.3 | [release notes](4.0.3.md) | | 2022/09/13 | 4.0.2 | [release notes](4.0.2.md) | | 2022/01/17 | 4.0.1 | [release notes](4.0.1.md) | diff --git a/release-notes/5.0/5.0.0-preview1.md b/release-notes/5.0/5.0.0-preview1.md index 55faad3c70..51ae6ea74f 100644 --- a/release-notes/5.0/5.0.0-preview1.md +++ b/release-notes/5.0/5.0.0-preview1.md @@ -4,6 +4,11 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [EngRajabi](https://github.com/EngRajabi) + ### Added - Added SqlDataSourceEnumerator. [#1430](https://github.com/dotnet/SqlClient/pull/1430), [Read more](#sql-data-source-enumerator-support) diff --git a/release-notes/5.0/5.0.0-preview2.md b/release-notes/5.0/5.0.0-preview2.md index 16158a05fb..59afe13509 100644 --- a/release-notes/5.0/5.0.0-preview2.md +++ b/release-notes/5.0/5.0.0-preview2.md @@ -4,6 +4,11 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) + ### Breaking changes over preview release v5.0.0-preview1 - Dropped support for .NET Framework 4.6.1 [#1574](https://github.com/dotnet/SqlClient/pull/1574) diff --git a/release-notes/5.0/5.0.0-preview3.md b/release-notes/5.0/5.0.0-preview3.md index 19819018bd..b54eb000ec 100644 --- a/release-notes/5.0/5.0.0-preview3.md +++ b/release-notes/5.0/5.0.0-preview3.md @@ -4,6 +4,13 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [EngRajabi](https://github.com/EngRajabi) +- [tf-micwil](https://github.com/tf-micwil) +- [swh-cb](https://github.com/swh-cb) + ### Breaking changes over preview release v5.0.0-preview2 - Added a dependency on the [Microsoft.SqlServer.Server](https://github.com/dotnet/SqlClient/tree/main/src/Microsoft.SqlServer.Server) package. This new dependency may cause namespace conflicts if your application references that namespace and still has package references (direct or indirect) to System.Data.SqlClient from .NET Core. diff --git a/release-notes/5.0/5.0.0.md b/release-notes/5.0/5.0.0.md index 1bf0f071c5..62522eb424 100644 --- a/release-notes/5.0/5.0.0.md +++ b/release-notes/5.0/5.0.0.md @@ -4,6 +4,14 @@ This update includes the following changes over the 4.1 release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [EngRajabi](https://github.com/EngRajabi) +- [tf-micwil](https://github.com/tf-micwil) +- [swh-cb](https://github.com/swh-cb) + ### Breaking changes - As part of the [`TDS 8` feature](#tds-8-enhanced-security), the `SqlConnectionStringBuilder.Encrypt` property has changed from a `bool` to a `SqlConnectionEncryptOption`. `SqlConnectionEncryptOption` has implicit conversion rules to convert to/from a `bool` so that existing code remains backwards compatible, however this is a binary-breaking change and a recompile is required against this version. diff --git a/release-notes/5.0/5.0.1.md b/release-notes/5.0/5.0.1.md index 39d36cc579..dad582d560 100644 --- a/release-notes/5.0/5.0.1.md +++ b/release-notes/5.0/5.0.1.md @@ -4,6 +4,9 @@ This update includes the following changes over the 5.0.0 release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + ### Fixed - Fixed missing `HostNameInCertificate` connection string property in .NET Framework. [#1782](https://github.com/dotnet/SqlClient/pull/1782) diff --git a/release-notes/5.0/5.0.2.md b/release-notes/5.0/5.0.2.md index 6d972f1592..2c6452286b 100644 --- a/release-notes/5.0/5.0.2.md +++ b/release-notes/5.0/5.0.2.md @@ -4,6 +4,10 @@ This update includes the following changes over the 5.0.1 release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) + ### Fixed - Fixed memory leak regression from [#1785](https://github.com/dotnet/SqlClient/pull/1785) using a `DisposableTemporaryOnStack` struct. [#1980](https://github.com/dotnet/SqlClient/pull/1980) diff --git a/release-notes/5.1/5.1.0-preview1.md b/release-notes/5.1/5.1.0-preview1.md index 222f10f7d5..9bee9f1288 100644 --- a/release-notes/5.1/5.1.0-preview1.md +++ b/release-notes/5.1/5.1.0-preview1.md @@ -4,6 +4,11 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [sorensenmatias](https://github.com/sorensenmatias) + ### Fixed - Fixed `ReadAsync()` behavior to register Cancellation token action before streaming results. [#1781](https://github.com/dotnet/SqlClient/pull/1781) diff --git a/release-notes/5.1/5.1.0-preview2.md b/release-notes/5.1/5.1.0-preview2.md index 93b58078a0..9098c7b044 100644 --- a/release-notes/5.1/5.1.0-preview2.md +++ b/release-notes/5.1/5.1.0-preview2.md @@ -4,6 +4,12 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [panoskj](https://github.com/panoskj) + ### Breaking changes over preview release v5.1.0-preview1 - Add support for .NET 6.0 and Dropped support for .NET Core 3.1. [#1704](https://github.com/dotnet/SqlClient/pull/1704) [#1823](https://github.com/dotnet/SqlClient/pull/1823) diff --git a/release-notes/5.1/5.1.0.md b/release-notes/5.1/5.1.0.md index 015b8966b9..adbf449e63 100644 --- a/release-notes/5.1/5.1.0.md +++ b/release-notes/5.1/5.1.0.md @@ -4,6 +4,15 @@ This update includes the following changes over the 5.0 release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [roji](https://github.com/roji) +- [panoskj](https://github.com/panoskj) +- [teo-tsirpanis](https://github.com/teo-tsirpanis) +- [sorensenmatias](https://github.com/sorensenmatias) + ### Breaking changes - Dropped support for .NET Core 3.1. [#1704](https://github.com/dotnet/SqlClient/pull/1704) [#1823](https://github.com/dotnet/SqlClient/pull/1823) @@ -70,7 +79,7 @@ The default value of the `ServerCertificate` connection setting is an empty stri #### .NET -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.7.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.JsonWebTokens 6.24.0 @@ -86,7 +95,7 @@ The default value of the `ServerCertificate` connection setting is an empty stri #### .NET Standard -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.7.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 diff --git a/release-notes/5.1/5.1.1.md b/release-notes/5.1/5.1.1.md index 81f652ec4f..057466a565 100644 --- a/release-notes/5.1/5.1.1.md +++ b/release-notes/5.1/5.1.1.md @@ -4,6 +4,9 @@ This update includes the following changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + ### Fixed - Fixed an incorrect exception when a symmetric key fails to decrypt a column using Always Encrypted. [#1968](https://github.com/dotnet/SqlClient/pull/1968) @@ -34,7 +37,7 @@ This update includes the following changes over the previous release: #### .NET -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.7.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.JsonWebTokens 6.24.0 @@ -50,7 +53,7 @@ This update includes the following changes over the previous release: #### .NET Standard -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.7.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 diff --git a/release-notes/5.1/5.1.2.md b/release-notes/5.1/5.1.2.md new file mode 100644 index 0000000000..cb9ccc5992 --- /dev/null +++ b/release-notes/5.1/5.1.2.md @@ -0,0 +1,78 @@ +# Release Notes + +## Microsoft.Data.SqlClient 5.1.2 released 26 October 2023 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [emidah](https://github.com/emidah) + +### Fixed + +- Fixed access violation when using SQL Express user instance. [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed LocalDb and managed SNI by improving the error messages and avoid falling back to the local service. [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed .NET and .NET Standard file version. [2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed non-string values and `SqlConnectionStringBuilder` property indexer issue. [#2018](https://github.com/dotnet/SqlClient/pull/2018) +- Fixed `SqlConnectionEncryptOption` type conversion by introducing the `SqlConnectionEncryptOptionConverter` attribute when using **appsettings.json** files. [#2057](https://github.com/dotnet/SqlClient/pull/2057) +- Fixed Transient fault handling issue with `OpenAsync`. [#1983](https://github.com/dotnet/SqlClient/pull/1983) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) + +### Changed + +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET Core/Standard dependency) version to `5.1.1`. [#2123](https://github.com/dotnet/SqlClient/pull/2123) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.0 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.1/5.1.3.md b/release-notes/5.1/5.1.3.md new file mode 100644 index 0000000000..7889bf61bb --- /dev/null +++ b/release-notes/5.1/5.1.3.md @@ -0,0 +1,67 @@ +# Release Notes + +## Microsoft.Data.SqlClient 5.1.3 released 9 January 2024 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + +### Fixed + +- Fixed encryption downgrade issue. [CVE-2024-0056](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0056) +- Fixed certificate chain validation logic flow. + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.0 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.7.0 +- Microsoft.Identity.Client 4.47.2 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.1/5.1.4.md b/release-notes/5.1/5.1.4.md new file mode 100644 index 0000000000..c1638b1eee --- /dev/null +++ b/release-notes/5.1/5.1.4.md @@ -0,0 +1,70 @@ +# Release Notes + +## Microsoft.Data.SqlClient 5.1.4 released 9 January 2024 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + +### Fixed + +- Fixed a deadlock problem for distributed transactions when on .NET. + +### Changed + +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27). + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.0 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.1/5.1.5.md b/release-notes/5.1/5.1.5.md new file mode 100644 index 0000000000..e05c26861f --- /dev/null +++ b/release-notes/5.1/5.1.5.md @@ -0,0 +1,72 @@ +# Release Notes + +## Microsoft.Data.SqlClient 5.1.5 released 29 January 2024 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [ErikEJ](https://github.com/ErikEJ) + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2321](https://github.com/dotnet/SqlClient/pull/2321) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2324](https://github.com/dotnet/SqlClient/pull/2324) + +### Changed + +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2320](https://github.com/dotnet/SqlClient/pull/2320) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.0 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.2 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.1/5.1.6.md b/release-notes/5.1/5.1.6.md new file mode 100644 index 0000000000..a5404c84da --- /dev/null +++ b/release-notes/5.1/5.1.6.md @@ -0,0 +1,75 @@ +# Release Notes + +## Microsoft.Data.SqlClient 5.1.6 released 27 August 2024 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + +### Fixed + +- Fixed Transient fault handling issue with `OpenAsync`. [#1983](https://github.com/dotnet/SqlClient/pull/1983) [#2508](https://github.com/dotnet/SqlClient/pull/2508) +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2706](https://github.com/dotnet/SqlClient/pull/2706) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2618](https://github.com/dotnet/SqlClient/pull/2618) [#2818](https://github.com/dotnet/SqlClient/pull/2818) + +### Changed + +- Upgraded `Azure.Identity` version from 1.11.3 to 1.11.4 [#2649] (https://github.com/dotnet/SqlClient/pull/2649) [#2529] (https://github.com/dotnet/SqlClient/pull/2529) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Upgraded `Microsoft.Identity.Client` version from 4.60.0 to 4.61.3 [#2649] (https://github.com/dotnet/SqlClient/pull/2649) [#2529] (https://github.com/dotnet/SqlClient/pull/2529) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Added caching to `TokenCredential` objects to take advantage of token caching. [#2776](https://github.com/dotnet/SqlClient/pull/2776) +- Code health improvements: [#2490] (https://github.com/dotnet/SqlClient/pull/2490) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.1.1 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encodings.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.0 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI.runtime 5.1.1 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.1/5.1.md b/release-notes/5.1/5.1.md index 58721cc2f7..99db6d4c58 100644 --- a/release-notes/5.1/5.1.md +++ b/release-notes/5.1/5.1.md @@ -4,6 +4,11 @@ The following Microsoft.Data.SqlClient 5.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/27 | 5.1.6 | [release notes](5.1.6.md) | +| 2024/01/29 | 5.1.5 | [release notes](5.1.5.md) | +| 2024/01/09 | 5.1.4 | [release notes](5.1.4.md) | +| 2024/01/09 | 5.1.3 | [release notes](5.1.3.md) | +| 2023/10/26 | 5.1.2 | [release notes](5.1.2.md) | | 2023/03/28 | 5.1.1 | [release notes](5.1.1.md) | | 2023/01/19 | 5.1.0 | [release notes](5.1.0.md) | diff --git a/release-notes/5.1/README.md b/release-notes/5.1/README.md index 58721cc2f7..99db6d4c58 100644 --- a/release-notes/5.1/README.md +++ b/release-notes/5.1/README.md @@ -4,6 +4,11 @@ The following Microsoft.Data.SqlClient 5.1 stable releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | +| 2024/08/27 | 5.1.6 | [release notes](5.1.6.md) | +| 2024/01/29 | 5.1.5 | [release notes](5.1.5.md) | +| 2024/01/09 | 5.1.4 | [release notes](5.1.4.md) | +| 2024/01/09 | 5.1.3 | [release notes](5.1.3.md) | +| 2023/10/26 | 5.1.2 | [release notes](5.1.2.md) | | 2023/03/28 | 5.1.1 | [release notes](5.1.1.md) | | 2023/01/19 | 5.1.0 | [release notes](5.1.0.md) | diff --git a/release-notes/5.2/5.2.0-preview1.md b/release-notes/5.2/5.2.0-preview1.md index 7773019542..152b3169b8 100644 --- a/release-notes/5.2/5.2.0-preview1.md +++ b/release-notes/5.2/5.2.0-preview1.md @@ -4,6 +4,13 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [kant2002](https://github.com/kant2002) +- [mattjohnsonpint](https://github.com/mattjohnsonpint) + ### Added - Added support of `SqlDiagnosticListener` on **.NET Standard**. [#1931](https://github.com/dotnet/SqlClient/pull/1931) @@ -56,7 +63,7 @@ This update brings the below changes over the previous release: #### .NET -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.8.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.JsonWebTokens 6.24.0 @@ -75,7 +82,7 @@ This update brings the below changes over the previous release: #### .NET Standard -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.6.0 - Microsoft.Identity.Client 4.47.2 - Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 diff --git a/release-notes/5.2/5.2.0-preview2.md b/release-notes/5.2/5.2.0-preview2.md index 3cb604878d..360894b93a 100644 --- a/release-notes/5.2/5.2.0-preview2.md +++ b/release-notes/5.2/5.2.0-preview2.md @@ -4,6 +4,12 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [azerios](https://github.com/azerios) +- [jinek](https://github.com/jinek) + ### Added - Added new property `RowsCopied64` to `SqlBulkCopy`. [#2004](https://github.com/dotnet/SqlClient/pull/2004) [Read more](#added-new-property-rowscopied64-to-sqlbulkcopy) @@ -78,7 +84,7 @@ Example usage: #### .NET -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.8.0 - Microsoft.Identity.Client 4.53.0 - Microsoft.IdentityModel.JsonWebTokens 6.24.0 @@ -97,7 +103,7 @@ Example usage: #### .NET Standard -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.6.0 - Microsoft.Identity.Client 4.53.0 - Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 diff --git a/release-notes/5.2/5.2.0-preview3.md b/release-notes/5.2/5.2.0-preview3.md index 0980ed4a2b..82173a5744 100644 --- a/release-notes/5.2/5.2.0-preview3.md +++ b/release-notes/5.2/5.2.0-preview3.md @@ -4,6 +4,11 @@ This update brings the below changes over the previous release: +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [kant2002](https://github.com/kant2002) +- [christothes](https://github.com/christothes) + ### Added - Added a new `AccessTokenCallBack` API to `SqlConnection`. [#1260](https://github.com/dotnet/SqlClient/pull/1260) @@ -76,7 +81,7 @@ Example usage: #### .NET -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.8.0 - Microsoft.Identity.Client 4.53.0 - Microsoft.IdentityModel.JsonWebTokens 6.24.0 @@ -95,7 +100,7 @@ Example usage: #### .NET Standard -- Microsoft.Data.SqlClient.SNI 5.1.0 +- Microsoft.Data.SqlClient.SNI.runtime 5.1.0 - Azure.Identity 1.6.0 - Microsoft.Identity.Client 4.53.0 - Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 diff --git a/release-notes/5.2/5.2.0-preview4.md b/release-notes/5.2/5.2.0-preview4.md new file mode 100644 index 0000000000..eb94c0c73f --- /dev/null +++ b/release-notes/5.2/5.2.0-preview4.md @@ -0,0 +1,145 @@ +# Release Notes + +## [Preview Release 5.2.0-preview4.23342.2] - 2023-12-08 + +This update brings the below changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [panoskj](https://github.com/panoskj) +- [saitama951](https://github.com/saitama951) +- [danielmarbach](https://github.com/danielmarbach) +- [wsugarman](https://github.com/wsugarman) +- [ViktorHofer](https://github.com/ViktorHofer) +- [emidah](https://github.com/emidah) + +### Added + +- Added `SqlBatch` support on .NET 6+[#1825](https://github.com/dotnet/SqlClient/pull/1825), [#2223](https://github.com/dotnet/SqlClient/pull/2223) +- Added Workload Identity authentication support [#2159](https://github.com/dotnet/SqlClient/pull/2159), [#2264](https://github.com/dotnet/SqlClient/pull/2264) +- Added Localization support on .NET [#2210](https://github.com/dotnet/SqlClient/pull/2110) +- Added support for Georgian collation [#2194](https://github.com/dotnet/SqlClient/pull/2194) +- Added support for Big Endian systems [#2170](https://github.com/dotnet/SqlClient/pull/2170) + +### Changed + +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET/.NET Standard dependency) version to `v5.2.0-preview1.23340.1`. [#2257](https://github.com/dotnet/SqlClient/pull/2257), which includes removing dead code and addressing static analysis warnings +- Improved CPU usage when `AppContext` switches are in use [#2227](https://github.com/dotnet/SqlClient/pull/2227) +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27), [#2188](https://github.com/dotnet/SqlClient/pull/2188) +- Improved error messages when validating server certificates in managed SNI (Linux/macOS) [#2060](https://github.com/dotnet/SqlClient/pull/2060) + +### Fixed + +- Fixed an issue when using the Authentication option, but not encrypting on .NET Framework where the server certificate was being incorrectly validated [#2224](https://github.com/dotnet/SqlClient/pull/2224) +- Fixed a deadlock problem for distributed transactions when on .NET [#2161](https://github.com/dotnet/SqlClient/pull/2161) +- Fixed an issue with connecting to named instances on named pipes in managed SNI (Linux/macOS)[#2142](https://github.com/dotnet/SqlClient/pull/2142) +- Fixed LocalDb connection issue with an invalid source when using managed SNI [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed an `AccessViolationException` when using a SQL Express user instance [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed a metadata query issue when connecting to Azure SQL Edge [#2099](https://github.com/dotnet/SqlClient/pull/2099) +- Fixed file version information for .NET and .NET Standard binaries[#2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed the SPN sent for a named instance when using Kerberos authentication on Linux/macOS [#2240](https://github.com/dotnet/SqlClient/pull/2240) +- Various code improvements [#2091](https://github.com/dotnet/SqlClient/pull/2091), [#2098](https://github.com/dotnet/SqlClient/pull/2098), [#2121](https://github.com/dotnet/SqlClient/pull/2121), [#2122](https://github.com/dotnet/SqlClient/pull/2122), [#2132](https://github.com/dotnet/SqlClient/pull/2132), [#2136](https://github.com/dotnet/SqlClient/pull/2136), [#2144](https://github.com/dotnet/SqlClient/pull/2144), [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2157](https://github.com/dotnet/SqlClient/pull/2157), [#2164](https://github.com/dotnet/SqlClient/pull/2164), [#2166](https://github.com/dotnet/SqlClient/pull/2166), [#2168](https://github.com/dotnet/SqlClient/pull/2168), [#2186](https://github.com/dotnet/SqlClient/pull/2186) + +### SQLBatch API + +```csharp +using Microsoft.Data.SqlClient; + +class Program +{ + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + // Optionally Prepare + batch.Prepare(); + + var results = new List(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } +} +``` + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 + +#### .NET Standard + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 +- Microsoft.IdentityModel.JsonWebTokens 6.24.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 diff --git a/release-notes/5.2/5.2.0-preview5.md b/release-notes/5.2/5.2.0-preview5.md new file mode 100644 index 0000000000..87de1c81ea --- /dev/null +++ b/release-notes/5.2/5.2.0-preview5.md @@ -0,0 +1,107 @@ +# Release Notes + +## [Preview Release 5.2.0-preview5.24024.3] - 2024-01-24 + +This update brings the below changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. +- [ErikEJ](https://github.com/ErikEJ) + +### Added + +- Added .NET 8 support [#2230](https://github.com/dotnet/SqlClient/pull/2230) +- Added explicit version for major .NET version dependencies on System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0, and System.Diagnostics.DiagnosticSource 8.0.0 [#2303](https://github.com/dotnet/SqlClient/pull/2303) +- Added the ability to generate debugging symbols in a separate package file [#2137](https://github.com/dotnet/SqlClient/pull/2137) + +### Changed + +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2290](https://github.com/dotnet/SqlClient/pull/2290) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) + +### Fixed + +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2275](https://github.com/dotnet/SqlClient/pull/2275) +- Fixed token caching to prevent expired access tokens from being reused in a connection pool [#2273](https://github.com/dotnet/SqlClient/pull/2273) +- Code health improvements: [#2288](https://github.com/dotnet/SqlClient/pull/2288), [#2305](https://github.com/dotnet/SqlClient/pull/2305), [#2254](https://github.com/dotnet/SqlClient/pull/2254), [#2317](https://github.com/dotnet/SqlClient/pull/2317) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET 6 + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 + +#### .NET 8 + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 8.0.0 +- System.Diagnostics.DiagnosticSource 8.0.0 +- System.Runtime.Caching 8.0.0 + +#### .NET Standard 2.0 + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard 2.1 + +- Microsoft.Data.SqlClient.SNI 5.2.0-preview1.23340.1 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 \ No newline at end of file diff --git a/release-notes/5.2/5.2.0.md b/release-notes/5.2/5.2.0.md index 5d1675b7a3..b431e7c675 100644 --- a/release-notes/5.2/5.2.0.md +++ b/release-notes/5.2/5.2.0.md @@ -1,5 +1,277 @@ -| Release Date | Version | Notes | -| :-- | :-- | :--: | -| 2023/07/20 | 5.2.0-preview3.23201.1 | [relese notes](5.2.0-preview3.md) | -| 2023/06/08 | 5.2.0-preview2.23159.1 | [relese notes](5.2.0-preview2.md) | -| 2023/04/20 | 5.2.0-preview1.23109.1 | [release notes](5.2.0-preview1.md) | +# Release Notes + +## Microsoft.Data.SqlClient 5.2.0 released 28 February 2024 + +This update includes the following changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + +- [Wraith2](https://github.com/Wraith2) +- [ErikEJ](https://github.com/ErikEJ) +- [kant2002](https://github.com/kant2002) +- [mattjohnsonpint](https://github.com/mattjohnsonpint) +- [azerios](https://github.com/azerios) +- [jinek](https://github.com/jinek) +- [christothes](https://github.com/christothes) +- [panoskj](https://github.com/panoskj) +- [saitama951](https://github.com/saitama951) +- [danielmarbach](https://github.com/danielmarbach) +- [wsugarman](https://github.com/wsugarman) +- [ViktorHofer](https://github.com/ViktorHofer) +- [emidah](https://github.com/emidah) + +### Added + +- Added a new `AccessTokenCallback` API to `SqlConnection`. [#1260](https://github.com/dotnet/SqlClient/pull/1260) [Read more](#added-new-property-accesstokencallback-to-sqlconnection) +- Added `SqlBatch` support on .NET 6+ [#1825](https://github.com/dotnet/SqlClient/pull/1825), [#2223](https://github.com/dotnet/SqlClient/pull/2223), [#2371](https://github.com/dotnet/SqlClient/pull/2371), [#2373](https://github.com/dotnet/SqlClient/pull/2373) [Read more](#added-new-property-sqlbatch-api) +- Added support of `SqlDiagnosticListener` on **.NET Standard**. [#1931](https://github.com/dotnet/SqlClient/pull/1931) +- Added new property `RowsCopied64` to `SqlBulkCopy`. [#2004](https://github.com/dotnet/SqlClient/pull/2004) [Read more](#added-new-property-rowscopied64-to-sqlbulkcopy) +- Added support for the `SuperSocketNetLib` registry option for Encrypt on .NET on Windows. [#2047](https://github.com/dotnet/SqlClient/pull/2047) +- Added the ability to generate debugging symbols in a separate package file [#2137](https://github.com/dotnet/SqlClient/pull/2137) +- Added Workload Identity authentication support [#2159](https://github.com/dotnet/SqlClient/pull/2159), [#2264](https://github.com/dotnet/SqlClient/pull/2264) +- Added support for Big Endian systems [#2170](https://github.com/dotnet/SqlClient/pull/2170) +- Added support for Georgian collation [#2194](https://github.com/dotnet/SqlClient/pull/2194) +- Added Localization support on .NET [#2210](https://github.com/dotnet/SqlClient/pull/2110) +- Added .NET 8 support [#2230](https://github.com/dotnet/SqlClient/pull/2230) +- Added explicit version for major .NET version dependencies on System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0, and System.Diagnostics.DiagnosticSource 8.0.0 [#2303](https://github.com/dotnet/SqlClient/pull/2303) + +### Fixed + +- Fixed Always Encrypted secure enclave retry logic for async queries. [#1988](https://github.com/dotnet/SqlClient/pull/1988) +- Fixed activity correlator to continue use of same GUID for connection activity. [#1997](https://github.com/dotnet/SqlClient/pull/1997) +- Fixed behavior when error class is greater than 20 on connection retry. [#1953](https://github.com/dotnet/SqlClient/pull/1953) +- Fixed error message when symmetric key decryption failed using Always Encrypted. [#1948](https://github.com/dotnet/SqlClient/pull/1948) +- Fixed TransactionScope connection issue when Enlist is enable, Pooling is disabled and network connection type is Redirect. [#1960](https://github.com/dotnet/SqlClient/pull/1960) +- Fixed TDS RPC error on large queries in SqlCommand.ExecuteReaderAsync. [#1936](https://github.com/dotnet/SqlClient/pull/1936) +- Fixed throttling of token requests by calling AcquireTokenSilent. [#1925](https://github.com/dotnet/SqlClient/pull/1925) +- Fixed Linux code coverage result in Build proj. [#1950](https://github.com/dotnet/SqlClient/pull/1950) +- Fixed NullReferenceException in GetBytesAsync. [#1906](https://github.com/dotnet/SqlClient/pull/1906) +- Fixed Transient fault handling issue with OpenAsync. [#1983](https://github.com/dotnet/SqlClient/pull/1983) +- Fixed invariant mode checks. [#1917](https://github.com/dotnet/SqlClient/pull/1917) +- Fixed GC behavior in TdsParser by adding array rental capability in TryReadPlpUnicodeChars. [#1866](https://github.com/dotnet/SqlClient/pull/1866) +- Fixed socket synchronization issue during connect in managed SNI. [#1029](https://github.com/dotnet/SqlClient/pull/1029) +- Fixed issue with `SqlConnectionStringBuilder` property indexer not supporting non-string values. [#2018](https://github.com/dotnet/SqlClient/pull/2018) +- Fixed `SqlDataAdapter.Fill` and configurable retry logic issue on .NET Framework. [#2084](https://github.com/dotnet/SqlClient/pull/2084) +- Fixed `SqlConnectionEncryptOption` type conversion by introducing the `SqlConnectionEncryptOptionConverter` attribute when using **appsettings.json** files. [#2057](https://github.com/dotnet/SqlClient/pull/2057) +- Fixed th-TH culture info issue on Managed SNI. [#2066](https://github.com/dotnet/SqlClient/pull/2066) +- Fixed an issue when using the Authentication option, but not encrypting on .NET Framework where the server certificate was being incorrectly validated [#2224](https://github.com/dotnet/SqlClient/pull/2224) +- Fixed a deadlock problem for distributed transactions when on .NET [#2161](https://github.com/dotnet/SqlClient/pull/2161) +- Fixed an issue with connecting to named instances on named pipes in managed SNI (Linux/macOS) [#2142](https://github.com/dotnet/SqlClient/pull/2142) +- Fixed LocalDb connection issue with an invalid source when using managed SNI [#2129](https://github.com/dotnet/SqlClient/pull/2129) +- Fixed an `AccessViolationException` when using a SQL Express user instance [#2101](https://github.com/dotnet/SqlClient/pull/2101) +- Fixed a metadata query issue when connecting to Azure SQL Edge [#2099](https://github.com/dotnet/SqlClient/pull/2099) +- Fixed file version information for .NET and .NET Standard binaries [#2093](https://github.com/dotnet/SqlClient/pull/2093) +- Fixed the SPN sent for a named instance when using Kerberos authentication on Linux/macOS [#2240](https://github.com/dotnet/SqlClient/pull/2240) +- Fixed connection to unsubscribe from transaction completion events before returning it to the connection pool [#2301](https://github.com/dotnet/SqlClient/pull/2301) +- Fixed InvalidCastException when reading an Always Encrypted date or time column [#2275](https://github.com/dotnet/SqlClient/pull/2275) +- Fixed token caching to prevent expired access tokens from being reused in a connection pool [#2273](https://github.com/dotnet/SqlClient/pull/2273) + +### Changed + +- Improved parsing buffered characters in `TdsParser`. [#1544](https://github.com/dotnet/SqlClient/pull/1544) +- Added Microsoft.SqlServer.Types to verify support for SqlHierarchyId and Spatial for .NET Core. [#1848](https://github.com/dotnet/SqlClient/pull/1848) +- Moved to new System.Data.SqlTypes APIs in **.NET 7** and upper. [#1934](https://github.com/dotnet/SqlClient/pull/1934) and [#1981](https://github.com/dotnet/SqlClient/pull/1981) +- Removed reference to Microsoft.Win32.Registry since it's shipped starting with .NET 6.0. [#1974](https://github.com/dotnet/SqlClient/pull/1974) +- Changed **[UseOneSecFloorInTimeoutCalculationDuringLogin](https://learn.microsoft.com/sql/connect/ado-net/appcontext-switches#enable-a-minimum-timeout-during-login)** App Context switch default to **true** and extended its effect to .NET and .NET Standard. [#2012](https://github.com/dotnet/SqlClient/pull/2012) +- Updated `Microsoft.Identity.Client` version from 4.47.2 to 4.53.0. [#2031](https://github.com/dotnet/SqlClient/pull/2031), [#2055](https://github.com/dotnet/SqlClient/pull/2055) +- Switched to the new .NET [NegotiateAuthentication](https://learn.microsoft.com/en-us/dotnet/api/system.net.security.negotiateauthentication?view=net-7.0) API on .NET 7.0 and above for SSPI token negotiation using Managed SNI. [#2063](https://github.com/dotnet/SqlClient/pull/2063) +- Removed `ignoreSniOpenTimeout` in open connection process on Windows. [#2067](https://github.com/dotnet/SqlClient/pull/2067) +- Enforce explicit ordinal for internal `StringComparison` operations. [#2068](https://github.com/dotnet/SqlClient/pull/2068) +- Improved error messages when validating server certificates in managed SNI (Linux/macOS) [#2060](https://github.com/dotnet/SqlClient/pull/2060) +- Improved CPU usage when `AppContext` switches are in use [#2227](https://github.com/dotnet/SqlClient/pull/2227) +- Upgraded `Azure.Identity` dependency version to [1.10.3](https://www.nuget.org/packages/Azure.Identity/1.10.3) to address [CVE-2023-36414](https://github.com/advisories/GHSA-5mfx-4wcx-rv27), [#2189](https://github.com/dotnet/SqlClient/pull/2189) +- Changed Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Protocols.OpenIdConnect version 6.24.0 to 6.35.0 [#2290](https://github.com/dotnet/SqlClient/pull/2290) to address [CVE-2024-21319](https://www.cve.org/CVERecord?id=CVE-2024-21319) +- Updated `Microsoft.Data.SqlClient.SNI` (.NET Framework dependency) and `Microsoft.Data.SqlClient.SNI.runtime` (.NET/.NET Standard dependency) version to `v5.2.0`. [#2363](https://github.com/dotnet/SqlClient/pull/2363), which includes removing dead code and addressing static analysis warnings +- Code health improvements: [#1198](https://github.com/dotnet/SqlClient/pull/1198), [#1829](https://github.com/dotnet/SqlClient/pull/1829), [#1943](https://github.com/dotnet/SqlClient/pull/1943), [#1949](https://github.com/dotnet/SqlClient/pull/1949), [#1959](https://github.com/dotnet/SqlClient/pull/1959), [#1985](https://github.com/dotnet/SqlClient/pull/1985), [#2071](https://github.com/dotnet/SqlClient/pull/2071), [#2073](https://github.com/dotnet/SqlClient/pull/2073), [#2088](https://github.com/dotnet/SqlClient/pull/2088), [#2091](https://github.com/dotnet/SqlClient/pull/2091), [#2098](https://github.com/dotnet/SqlClient/pull/2098), [#2121](https://github.com/dotnet/SqlClient/pull/2121), [#2122](https://github.com/dotnet/SqlClient/pull/2122), [#2132](https://github.com/dotnet/SqlClient/pull/2132), [#2136](https://github.com/dotnet/SqlClient/pull/2136), [#2144](https://github.com/dotnet/SqlClient/pull/2144), [#2147](https://github.com/dotnet/SqlClient/pull/2147), [#2157](https://github.com/dotnet/SqlClient/pull/2157), [#2164](https://github.com/dotnet/SqlClient/pull/2164), [#2166](https://github.com/dotnet/SqlClient/pull/2166), [#2168](https://github.com/dotnet/SqlClient/pull/2168), [#2186](https://github.com/dotnet/SqlClient/pull/2186), [#2254](https://github.com/dotnet/SqlClient/pull/2254), [#2288](https://github.com/dotnet/SqlClient/pull/2288), [#2305](https://github.com/dotnet/SqlClient/pull/2305), [#2317](https://github.com/dotnet/SqlClient/pull/2317) + +## New features + +### Added new property `SQLBatch API` + +```csharp +using Microsoft.Data.SqlClient; + +class Program +{ + static void Main() + { + string str = "Data Source=(local);Initial Catalog=Northwind;" + + "Integrated Security=SSPI;Encrypt=False"; + RunBatch(str); + } + + static void RunBatch(string connString) + { + using var connection = new SqlConnection(connString); + connection.Open(); + + var batch = new SqlBatch(connection); + + const int count = 10; + const string parameterName = "parameter"; + for (int i = 0; i < count; i++) + { + var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value"); + batchCommand.Parameters.Add(new SqlParameter(parameterName, i)); + batch.BatchCommands.Add(batchCommand); + } + + // Optionally Prepare + batch.Prepare(); + + var results = new List(count); + using (SqlDataReader reader = batch.ExecuteReader()) + { + do + { + while (reader.Read()) + { + results.Add(reader.GetFieldValue(0)); + } + } while (reader.NextResult()); + } + Console.WriteLine(string.Join(", ", results)); + } +} +``` + +### Added new property `RowsCopied64` to SqlBulkCopy + +SqlBulkCopy has a new property `RowsCopied64` which supports `long` value types. + +**Note that the existing `SqlBulkCopy.RowsCopied` behavior is unchanged. When the value exceeds `int.MaxValue`, `RowsCopied` can return a negative number.** + +Example usage: + +```C# + using (SqlConnection srcConn = new SqlConnection(srcConstr)) + using (SqlCommand srcCmd = new SqlCommand("select top 5 * from employees", srcConn)) + { + srcConn.Open(); + using (DbDataReader reader = srcCmd.ExecuteReader()) + { + using (SqlBulkCopy bulkcopy = new SqlBulkCopy(dstConn)) + { + bulkcopy.DestinationTableName = dstTable; + SqlBulkCopyColumnMappingCollection ColumnMappings = bulkcopy.ColumnMappings; + + ColumnMappings.Add("EmployeeID", "col1"); + ColumnMappings.Add("LastName", "col2"); + ColumnMappings.Add("FirstName", "col3"); + + bulkcopy.WriteToServer(reader); + long rowsCopied = bulkcopy.RowsCopied64; + } + } + } +``` + +### Added new property `AccessTokenCallback` to SqlConnection + +SqlConnection supports `TokenCredential` authentication by introducing a new `AccessTokenCallback` property as a `Func>` delegate to return a federated authentication access token. + +Example usage: + +```C# + using Microsoft.Data.SqlClient; + using Azure.Identity; + + const string defaultScopeSuffix = "/.default"; + string connectionString = GetConnectionString(); + using SqlConnection connection = new SqlConnection(connectionString); + + connection.AccessTokenCallback = async (authParams, cancellationToken) => + { + var cred = new DefaultAzureCredential(); + string scope = authParams.Resource.EndsWith(defaultScopeSuffix) ? authParams.Resource : authParams.Resource + defaultScopeSuffix; + AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new[] { scope }), cancellationToken); + return new SqlAuthenticationToken(token.Token, token.ExpiresOn); + } + + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); +``` + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.2.0 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET 6 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 + +#### .NET 8 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 8.0.0 +- System.Diagnostics.DiagnosticSource 8.0.0 +- System.Runtime.Caching 8.0.0 + +#### .NET Standard 2.0 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.10.3 +- Microsoft.Identity.Client 4.56.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + diff --git a/release-notes/5.2/5.2.1.md b/release-notes/5.2/5.2.1.md new file mode 100644 index 0000000000..a64a4f4589 --- /dev/null +++ b/release-notes/5.2/5.2.1.md @@ -0,0 +1,99 @@ +# Release Notes + +## [Stable release 5.2.1] - 2024-05-31 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed connection errors on Linux when Data Source property contains both named instance and port [#2436](https://github.com/dotnet/SqlClient/pull/2436) +- Fixed `SqlConnection.FireInfoMessageEventOnUserErrors` when set to true throws an exception [#2505](https://github.com/dotnet/SqlClient/pull/2505) +- Fixed exception when using `DATETIMEOFFSET(n)` in a TVP if `n` is 1, 2, 3, or 4 [#2506](https://github.com/dotnet/SqlClient/pull/2506) +- Reverted PR [#1983](https://github.com/dotnet/SqlClient/pull/1938) which caused connection failure delays when using `OpenAsync` [#2507](https://github.com/dotnet/SqlClient/pull/2507) +- Fixed `SqlConnection.Clone()` to include `AccessTokenCallback` [#2527](https://github.com/dotnet/SqlClient/pull/2527) + +### Changed + +- Upgraded `Azure.Identity` version from 1.10.3 to 1.11.3 [#2492](https://github.com/dotnet/SqlClient/pull/2492), [#2528](https://github.com/dotnet/SqlClient/pull/2528) +- Upgraded `Microsoft.Identity.Client` version from 4.56.0 to 4.60.3 [#2492](https://github.com/dotnet/SqlClient/pull/2492) +- Code Health improvements: [#2467](https://github.com/dotnet/SqlClient/pull/2467) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.2.0 +- Azure.Identity 1.11.3 +- Microsoft.Identity.Client 4.60.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encoding.Web 6.0.0 + +#### .NET 6 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.3 +- Microsoft.Identity.Client 4.60.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 + +#### .NET 8 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.3 +- Microsoft.Identity.Client 4.60.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 8.0.0 +- System.Runtime.Caching 8.0.0 + +#### .NET Standard 2.0 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.3 +- Microsoft.Identity.Client 4.60.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.3 +- Microsoft.Identity.Client 4.60.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + diff --git a/release-notes/5.2/5.2.2.md b/release-notes/5.2/5.2.2.md new file mode 100644 index 0000000000..1947d5f373 --- /dev/null +++ b/release-notes/5.2/5.2.2.md @@ -0,0 +1,100 @@ +# Release Notes + +## [Stable release 5.2.2] - 2024-08-27 + +This update brings the below changes over the previous release: + +### Fixed + +- Fixed `AcquireTokenAsync` timeout handling for edge cases in `ActiveDirectoryAuthenticationProvider`. [#2650](https://github.com/dotnet/SqlClient/pull/2650) +- Fixed issue with `Socket.Connect` in managed SNI. [#2779](https://github.com/dotnet/SqlClient/pull/2779) +- Fixed path for `AssemblyAttributes` in obj folder causing NET 8.0 assembly to appear in NET 6.0 dll. [#2789](https://github.com/dotnet/SqlClient/pull/2789) +- Fixed SSPI retry negotiation with default port in .NET. [#2815](https://github.com/dotnet/SqlClient/pull/2815) +- Fixed `ArgumentNullException` on `SqlDataRecord.GetValue` when using user-defined data type on .NET. [#2816](https://github.com/dotnet/SqlClient/pull/2816) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2817](https://github.com/dotnet/SqlClient/pull/2817) + +### Changed + +- Upgraded `Azure.Identity` version from 1.11.3 to 1.11.4 [#2648](https://github.com/dotnet/SqlClient/pull/2648) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Upgraded `Microsoft.Identity.Client` version from 4.60.0 to 4.61.3 [#2648](https://github.com/dotnet/SqlClient/pull/2648) to address [CVE-2024-35255](https://github.com/advisories/GHSA-m5vv-6r4h-3vj9). +- Added caching to `TokenCredential` objects to take advantage of token caching. [#2775](https://github.com/dotnet/SqlClient/pull/2775) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) +- .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 5.2.0 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.InteropServices.RuntimeInformation 4.3.0 +- System.Text.Encodings.Web 6.0.0 + +#### .NET 6 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Runtime.Caching 6.0.0 + +#### .NET 8 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 8.0.0 +- System.Runtime.Caching 8.0.0 + +#### .NET Standard 2.0 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Buffers 4.5.1 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + +#### .NET Standard 2.1 + +- Microsoft.Data.SqlClient.SNI.runtime 5.2.0 +- Azure.Identity 1.11.4 +- Microsoft.Identity.Client 4.61.3 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.35.0 +- Microsoft.IdentityModel.JsonWebTokens 6.35.0 +- Microsoft.SqlServer.Server 1.0.0 +- Microsoft.Win32.Registry 5.0.0 +- System.Configuration.ConfigurationManager 6.0.1 +- System.Diagnostics.DiagnosticSource 6.0.1 +- System.Runtime.Caching 6.0.0 +- System.Text.Encoding.CodePages 6.0.0 +- System.Text.Encodings.Web 6.0.0 +- System.Runtime.Loader 4.3.0 +- System.Security.Cryptography.Cng 5.0.0 +- System.Security.Principal.Windows 5.0.0 + diff --git a/release-notes/5.2/5.2.md b/release-notes/5.2/5.2.md new file mode 100644 index 0000000000..e94144af62 --- /dev/null +++ b/release-notes/5.2/5.2.md @@ -0,0 +1,20 @@ +# Microsoft.Data.SqlClient 5.2 Releases + +The following Microsoft.Data.SqlClient 5.2 stable releases have been shipped: + +| Release Date | Version | Notes | +| :-- | :-- | :--: | +| 2024/08/27 | 5.2.2 | [release notes](5.2.2.md) | +| 2024/05/31 | 5.2.1 | [release notes](5.2.1.md) | +| 2024/02/28 | 5.2.0 | [release notes](5.2.0.md) | + +The following Microsoft.Data.SqlClient 5.2 preview releases have been shipped: + +| Release Date | Version | Notes | +| :-- | :-- | :--: | +| 2024/01/24 | 5.2.0-preview5.24024.3 | [release notes](5.2.0-preview5.md) | +| 2023/12/08 | 5.2.0-preview4.23342.2 | [release notes](5.2.0-preview4.md) | +| 2023/07/20 | 5.2.0-preview3.23201.1 | [release notes](5.2.0-preview3.md) | +| 2023/06/08 | 5.2.0-preview2.23159.1 | [release notes](5.2.0-preview2.md) | +| 2023/04/20 | 5.2.0-preview1.23109.1 | [release notes](5.2.0-preview1.md) | + diff --git a/release-notes/5.2/README.md b/release-notes/5.2/README.md index 592b0a61ca..ed6f4a377a 100644 --- a/release-notes/5.2/README.md +++ b/release-notes/5.2/README.md @@ -1,9 +1,19 @@ # Microsoft.Data.SqlClient 5.2 Releases +The following Microsoft.Data.SqlClient 5.2 stable releases have been shipped: + +| Release Date | Version | Notes | +| :-- | :-- | :--: | +| 2024/08/27 | 5.2.2 | [release notes](5.2.2.md) | +| 2024/05/31 | 5.2.1 | [release notes](5.2.1.md) | +| 2024/02/28 | 5.2.0 | [release notes](5.2.0.md) | + The following Microsoft.Data.SqlClient 5.2 preview releases have been shipped: | Release Date | Version | Notes | | :-- | :-- | :--: | -| 2023/07/20 | 5.2.0-preview3.23201.1 | [relese notes](5.2.0-preview3.md) | +| 2024/01/24 | 5.2.0-preview5.24024.3 | [release notes](5.2.0-preview5.md) | +| 2023/12/08 | 5.2.0-preview4.23342.2 | [release notes](5.2.0-preview4.md) | +| 2023/07/20 | 5.2.0-preview3.23201.1 | [release notes](5.2.0-preview3.md) | | 2023/06/08 | 5.2.0-preview2.23159.1 | [release notes](5.2.0-preview2.md) | | 2023/04/20 | 5.2.0-preview1.23109.1 | [release notes](5.2.0-preview1.md) | diff --git a/release-notes/6.0/6.0.0-preview1.md b/release-notes/6.0/6.0.0-preview1.md new file mode 100644 index 0000000000..86589346d8 --- /dev/null +++ b/release-notes/6.0/6.0.0-preview1.md @@ -0,0 +1,100 @@ +# Release Notes + +## [Preview Release 6.0.0-preview1.24240.8] - 2024-08-27 + +This update brings the below changes over the previous release: + +### Contributors +Thanks to the following public contributors. Their efforts toward this project are very much appreciated. + +- [ErikEJ](https://github.com/ErikEJ) +- [edwardneal](https://github.com/edwardneal) +- [Wraith2](https://github.com/Wraith2) +- [twsouthwick](https://github.com/twsouthwick) +- [0xced](https://github.com/0xced) +- [wilbit](https://github.com/wilbit) +- [TrayanZapryanov](https://github.com/TrayanZapryanov) + +### Breaking Changes + +- Removed support for .NET Standard. [#2386](https://github.com/dotnet/SqlClient/pull/2386) +- Removed UWP (uap) references. [#2483](https://github.com/dotnet/SqlClient/pull/2483) + +### Added + +- Added `TokenCredential` object to take advantage of token caching in `ActiveDirectoryAuthenticationProvider`. [#2380](https://github.com/dotnet/SqlClient/pull/2380) +- Added `DateOnly` and `TimeOnly` support to `DataTable` as a structured parameter. [#2258](https://github.com/dotnet/SqlClient/pull/2258) +- Added `Microsoft.Data.SqlClient.Diagnostics.SqlClientDiagnostic` type in .NET. [#2226](https://github.com/dotnet/SqlClient/pull/2226) +- Added scope trace for `GenerateSspiClientContext`. [#2497](https://github.com/dotnet/SqlClient/pull/2497), [#2725](https://github.com/dotnet/SqlClient/pull/2725) + +### Fixed + +- Fixed `Socket.Connect` timeout issue caused by thread starvation. [#2777](https://github.com/dotnet/SqlClient/pull/2777) +- Fixed pending data with `SqlDataReader` against an encrypted column. [#2618](https://github.com/dotnet/SqlClient/pull/2618) +- Fixed Entra authentication when using infinite connection timeout in `ActiveDirectoryAuthenticationProvider`. [#2651](https://github.com/dotnet/SqlClient/pull/2651) +- Fixed `GetSchema` by excluding unsupported engines due to lack of support for `ASSEMBLYPROPERTY` function. [#2593](https://github.com/dotnet/SqlClient/pull/2593) +- Fixed SSPI retry negotiation with default port in .NET. [#2559](https://github.com/dotnet/SqlClient/pull/2559) +- Fixed assembly path in .NET 8.0 and `.AssemblyAttributes`. [#2550](https://github.com/dotnet/SqlClient/pull/2550) +- Fixed certificate chain validation. [#2487](https://github.com/dotnet/SqlClient/pull/2487) +- Fixed clone of `SqlConnection` to include `AccessTokenCallback`. [#2525](https://github.com/dotnet/SqlClient/pull/2525) +- Fixed issue with `DateTimeOffset` in table-valued parameters, which was introduced in 5.2. [#2453](https://github.com/dotnet/SqlClient/pull/2453) +- Fixed `ArgumentNullException` on `SqlDataRecord.GetValue` when using user-defined data type on .NET. [#2448](https://github.com/dotnet/SqlClient/pull/2448) +- Fixed `SqlBuffer` and `SqlGuild` when it's null. [#2310](https://github.com/dotnet/SqlClient/pull/2310) +- Fixed `SqlBulkCopy.WriteToServer` state in a consecutive calls. [#2375](https://github.com/dotnet/SqlClient/pull/2375) +- Fixed null reference exception with `SqlConnection.FireInfoMessageEventOnUserErrors` after introducing the batch command. [#2399](https://github.com/dotnet/SqlClient/pull/2399) + +### Changed + +- Updated Microsoft.Data.SqlClient.SNI version to `6.0.0-preview1.24226.4`. [#2772](https://github.com/dotnet/SqlClient/pull/2772) +- Improved access to `SqlAuthenticationProviderManager.Instance` and avoid early object initiation. [#2636](https://github.com/dotnet/SqlClient/pull/2636) +- Removed undocumented properties of `Azure.Identity` in `ActiveDirectoryAuthenticationProvider`. [#2562](https://github.com/dotnet/SqlClient/pull/2562) +- Replaced `System.Runtime.Caching` with `Microsoft.Extensions.Caching.Memory`. [#2493](https://github.com/dotnet/SqlClient/pull/2493) +- Updated `EnableOptimizedParameterBinding` to only accept text mode commands. [#2417](https://github.com/dotnet/SqlClient/pull/2417) +- Updated `Azure.Identity` version from `1.10.3` to `1.11.4`. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Updated `Azure.Core` version from `1.35.0` to `1.38.0`. [#2462](https://github.com/dotnet/SqlClient/pull/2462) +- Updated `Azure.Security.KeyVault.Keys` version from `4.4.0` to `4.5.0`. [#2462](https://github.com/dotnet/SqlClient/pull/2462) +- Updated `Microsoft.IdentityModel.JsonWebTokens` and `Microsoft.IdentityModel.Protocols.OpenIdConnect` from `6.35.0` to `7.5.0`. [#2429](https://github.com/dotnet/SqlClient/pull/2429) +- Removed direct dependency to `Microsoft.Identity.Client` to take the transient dependecy through `Azure.Identity`. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Removed unnecessary references `Microsoft.Extensions.Caching.Memory` and `System.Security.Cryptography.Cng` after removing .NET Standard. [#2577](https://github.com/dotnet/SqlClient/pull/2577) +- Improved memory allocation when reader opened by `CommandBehavior.SequentialAccess` over the big string columns. [#2356](https://github.com/dotnet/SqlClient/pull/2356) +- Improved SSPI by consolidating the context generation to single abstraction and using memory/span for SSPI generation. [#2255](https://github.com/dotnet/SqlClient/pull/2255), [#2447](https://github.com/dotnet/SqlClient/pull/2447) +- Reverted the [#2281](https://github.com/dotnet/SqlClient/pull/2281) code changes on ManagedSNI. [#2395](https://github.com/dotnet/SqlClient/pull/2395) +- Updated assembly version to 6.0.0.0. [#2382](https://github.com/dotnet/SqlClient/pull/2382) +- Code health improvements: [#2366](https://github.com/dotnet/SqlClient/pull/2366), [#2369](https://github.com/dotnet/SqlClient/pull/2369), [#2381](https://github.com/dotnet/SqlClient/pull/2381), [#2390](https://github.com/dotnet/SqlClient/pull/2390), [#2392](https://github.com/dotnet/SqlClient/pull/2392), [#2403](https://github.com/dotnet/SqlClient/pull/2403), [#2410](https://github.com/dotnet/SqlClient/pull/2410), [#2413](https://github.com/dotnet/SqlClient/pull/2413), [#2425](https://github.com/dotnet/SqlClient/pull/2425), [#2428](https://github.com/dotnet/SqlClient/pull/2428), [#2440](https://github.com/dotnet/SqlClient/pull/2440), [#2443](https://github.com/dotnet/SqlClient/pull/2443), [#2450](https://github.com/dotnet/SqlClient/pull/2450), [#2466](https://github.com/dotnet/SqlClient/pull/2466), [#2486](https://github.com/dotnet/SqlClient/pull/2486), [#2521](https://github.com/dotnet/SqlClient/pull/2521), [#2522](https://github.com/dotnet/SqlClient/pull/2522), [#2533](https://github.com/dotnet/SqlClient/pull/2533), [#2552](https://github.com/dotnet/SqlClient/pull/2552), [#2560](https://github.com/dotnet/SqlClient/pull/2560), [#2726](https://github.com/dotnet/SqlClient/pull/2726), [#2751](https://github.com/dotnet/SqlClient/pull/2751), [#2811](https://github.com/dotnet/SqlClient/pull/2811) + +## Target Platform Support + +- .NET Framework 4.6.2+ (Windows x86, Windows x64) +- .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS) + +### Dependencies + +#### .NET Framework + +- Microsoft.Data.SqlClient.SNI 6.0.0-preview1.24226.4 +- Azure.Identity 1.11.4 +- Microsoft.Extensions.Caching.Memory 6.0.1 +- Microsoft.IdentityModel.JsonWebTokens 7.5.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 7.5.0 +- System.Buffers 4.5.1 +- System.Text.Encodings.Web 6.0.0 + +#### .NET 6 + +- Microsoft.Data.SqlClient.SNI.runtime 6.0.0-preview1.24226.4 +- Azure.Identity 1.11.4 +- Microsoft.Extensions.Caching.Memory 6.0.1 +- Microsoft.IdentityModel.JsonWebTokens 7.5.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 7.5.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 6.0.1 + +#### .NET 8 + +- Microsoft.Data.SqlClient.SNI.runtime 6.0.0-preview1.24226.4 +- Azure.Identity 1.11.4 +- Microsoft.Extensions.Caching.Memory 8.0.0 +- Microsoft.IdentityModel.JsonWebTokens 7.5.0 +- Microsoft.IdentityModel.Protocols.OpenIdConnect 7.5.0 +- Microsoft.SqlServer.Server 1.0.0 +- System.Configuration.ConfigurationManager 8.0.0 diff --git a/release-notes/6.0/6.0.md b/release-notes/6.0/6.0.md new file mode 100644 index 0000000000..83272ac61d --- /dev/null +++ b/release-notes/6.0/6.0.md @@ -0,0 +1,7 @@ +# Microsoft.Data.SqlClient 6.0 Releases + +The following Microsoft.Data.SqlClient 6.0 preview releases have been shipped: + +| Release Date | Version | Notes | +| :-- | :-- | :--: | +| 2024-08-27 | 6.0.0-preview1.24240.8 | [release notes](6.0.0-preview1.md) | diff --git a/release-notes/6.0/README.md b/release-notes/6.0/README.md new file mode 100644 index 0000000000..83272ac61d --- /dev/null +++ b/release-notes/6.0/README.md @@ -0,0 +1,7 @@ +# Microsoft.Data.SqlClient 6.0 Releases + +The following Microsoft.Data.SqlClient 6.0 preview releases have been shipped: + +| Release Date | Version | Notes | +| :-- | :-- | :--: | +| 2024-08-27 | 6.0.0-preview1.24240.8 | [release notes](6.0.0-preview1.md) | diff --git a/release-notes/README.md b/release-notes/README.md index f98322d8cb..8a23b21e3b 100644 --- a/release-notes/README.md +++ b/release-notes/README.md @@ -1,6 +1,6 @@ # Microsoft.Data.SqlClient Release Notes -The latest stable release is [Microsoft.Data.SqlClient 5.1](5.1). +The latest stable release is [Microsoft.Data.SqlClient 5.2](5.2). ## Release Information @@ -18,10 +18,11 @@ The latest stable release is [Microsoft.Data.SqlClient 5.1](5.1). # Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider Release Notes -The latest stable release is [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 3.0](add-ons/AzureKeyVaultProvider/3.0). +The latest stable release is [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 5.1](add-ons/AzureKeyVaultProvider/5.1). ## Release Information +- [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 5.1](add-ons/AzureKeyVaultProvider/5.1) - [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 3.0](add-ons/AzureKeyVaultProvider/3.0) - [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 2.0](add-ons/AzureKeyVaultProvider/2.0) - [Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 1.2](add-ons/AzureKeyVaultProvider/1.2) diff --git a/release-notes/add-ons/AzureKeyVaultProvider/5.1/5.1.0.md b/release-notes/add-ons/AzureKeyVaultProvider/5.1/5.1.0.md new file mode 100644 index 0000000000..159a1072d5 --- /dev/null +++ b/release-notes/add-ons/AzureKeyVaultProvider/5.1/5.1.0.md @@ -0,0 +1,72 @@ +# Release Notes + +## General Availability of Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider + +_**5.1.0 released 01 February 2024**_ + +This library contains the implementation of `Microsoft.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider` for accessing Azure Key Vault, and the provider class is named `SqlColumnEncryptionAzureKeyVaultProvider`. + +### Changed + +- Changed Microsoft.Data.SqlClient version 3.0.0 to 5.1.5 [#2330](https://github.com/dotnet/SqlClient/pull/2330) +- Changed Azure.Core version 1.6.0 to 1.35.0 [#2330](https://github.com/dotnet/SqlClient/pull/2330) +- Changed Azure.Security.KeyVault.Keys 4.0.3 to 4.5.0 [#2330](https://github.com/dotnet/SqlClient/pull/2330) +- Changed Microsoft.Extensions.Caching.Memory 5.0.0 to 8.0.0 for .Net 8.0 and 6.0.1 for other Target frameworks [#2330](https://github.com/dotnet/SqlClient/pull/2330) + +### Working with SQLColumnEncryptionAzureKeyVaultProvider + +`SqlColumnEncryptionAzureKeyVaultProvider` **v5.1** is implemented against `Microsoft.Data.SqlClient` **v5.1** and supports .NET Framework 4.6.2+, .NET Core 6.0+, and .NET Standard 2.0+. The provider name identifier for this library is "**AZURE_KEY_VAULT**" and it is not registered in the driver by default. Client applications may initialize this provider by providing an `Azure.Core.TokenCredential` and registering it with the driver using any of the below APIs: + +- [SqlConnection.RegisterColumnEncryptionKeyStoreProviders](https://docs.microsoft.com/dotnet/api/microsoft.data.sqlclient.sqlconnection.registercolumnencryptionkeystoreproviders?view=sqlclient-dotnet-5.1) +- [SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection](https://docs.microsoft.com/dotnet/api/microsoft.data.sqlclient.sqlconnection.registercolumnencryptionkeystoreprovidersonconnection?view=sqlclient-dotnet-5.1) (Added in version 3.0.0) +- [SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand](https://docs.microsoft.com/dotnet/api/microsoft.data.sqlclient.sqlcommand.registercolumnencryptionkeystoreprovidersoncommand?view=sqlclient-dotnet-5.1) (Added in version 3.0.0) + +Once the provider is registered, it can be used to perform Always Encrypted operations by creating a Column Master Key using the Azure Key Vault Key Identifier URL. + +The linked C# samples below demonstrate using Always Encrypted with secure enclaves with Azure Key Vault: + +- Legacy API support (Always Encrypted): [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/AzureKeyVaultProviderLegacyExample_2_0.cs) +- New API support (Always Encrypted): [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/AzureKeyVaultProviderExample_2_0.cs) +- Legacy API support (Always Encrypted with secure enclaves): [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/doc\samples\AzureKeyVaultProviderWithEnclaveProviderExample.cs) +- New API support (Always Encrypted with secure enclaves): [AzureKeyVaultProviderExample.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/doc\samples\AzureKeyVaultProviderWithEnclaveProviderExample_2_0.cs) +- Column Encryption Key cache scope example: [AzureKeyVaultProvider_ColumnEncryptionKeyCacheScope.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/AzureKeyVaultProvider_ColumnEncryptionKeyCacheScope.cs) +- Registering custom key store provider - Connection Precedence: [RegisterCustomKeyStoreProvider_ConnectionPrecedence.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/RegisterCustomKeyStoreProvider_ConnectionPrecedence.cs) +- Registering custom key store provider - Command Precedence: [RegisterCustomKeyStoreProvider_CommandPrecedence.cs](https://github.com/dotnet/SqlClient/blob/main/doc/samples/RegisterCustomKeyStoreProvider_CommandPrecedence.cs) + +For further details, refer to [Using the Azure Key Vault provider](https://docs.microsoft.com/sql/connect/ado-net/sql/sqlclient-support-always-encrypted#using-the-azure-key-vault-provider) + +## Target Platform Support + +- .NET Framework 4.6.2+ +- .NET Core 6.0+ (Windows x86, Windows x64, Linux, macOS) +- .NET Standard 2.0+ + +### Dependencies + +#### .NET Framework + +- Azure.Core 1.35.0 +- Azure.Security.KeyVault.Keys 4.5.0 +- Microsoft.Data.SqlClient 5.1.5 +- Microsoft.Extensions.Caching.Memory 6.0.1 + +##### .NET 6 + +- Azure.Core 1.35.0 +- Azure.Security.KeyVault.Keys 4.5.0 +- Microsoft.Data.SqlClient 5.1.5 +- Microsoft.Extensions.Caching.Memory 6.0.1 + +#### .NET 8 + +- Azure.Core 1.35.0 +- Azure.Security.KeyVault.Keys 4.5.0 +- Microsoft.Data.SqlClient 5.1.5 +- Microsoft.Extensions.Caching.Memory 8.0.0 + +#### .NET Standard + +- Azure.Core 1.35.0 +- Azure.Security.KeyVault.Keys 4.5.0 +- Microsoft.Data.SqlClient 5.1.5 +- Microsoft.Extensions.Caching.Memory 6.0.1 diff --git a/release-notes/add-ons/AzureKeyVaultProvider/5.1/README.md b/release-notes/add-ons/AzureKeyVaultProvider/5.1/README.md new file mode 100644 index 0000000000..55d9d38bc4 --- /dev/null +++ b/release-notes/add-ons/AzureKeyVaultProvider/5.1/README.md @@ -0,0 +1,7 @@ +# Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 5.1 Releases + +The following Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 5.1 stable releases have been shipped: + +| Release Date | Description | Notes | +| :-- | :-- | :--: | +| 2024/02/01 | 5.1.0 | [release notes](5.1.0.md) | diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b686f9fe8f..246b651f13 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,10 +15,8 @@ "Project" => Build and run tests with Microsoft.Data.SqlClient as Project Reference "Package" => Build and run tests with Microsoft.Data.SqlClient as Package Reference with configured "TestMicrosoftDataSqlClientVersion" in "Versions.props" file. - "NetStandard" => Build and run tests with Microsoft.Data.SqlClient as Project Reference via .NET Standard Library - "NetStandardPackage" => Build and run tests with Microsoft.Data.SqlClient as Package Reference via .NET Standard Library - ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" AND "NETSTANDARDPACKAGE" REFERENCE TYPES *************** + ************** IMPORTANT NOTE BEFORE PROCEEDING WITH "PACKAGE" REFERENCE TYPE *************** CREATE A NUGET PACKAGE WITH BELOW COMMAND AND ADD TO LOCAL FOLDER + UPDATE NUGET CONFIG FILE TO READ FROM THAT LOCATION > msbuild -p:configuration=Release --> @@ -51,6 +49,7 @@ $(ManagedSourceCode)src\Resources\ $(ManagedSourceCode)add-ons\ $(RepoRoot)src\Microsoft.SqlServer.Server\ + $(RepoRoot)src\Microsoft.Data.SqlClient\src\ $(Artifacts)obj\ $(NetCoreSource)src\Common\src $(NetCoreSource)src\Common\tests @@ -71,11 +70,31 @@ $(DefineConstants);ENCLAVE_SIMULATOR + + + portable + true + false + true + true + false + + + true + + + - + + + + + + false + diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index c5b34945a0..05767c597f 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -11,9 +11,6 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TDS.Servers", "Microsoft.Data.SqlClient\tests\tools\TDS\TDS.Servers\TDS.Servers.csproj", "{978063D3-FBB5-4E10-8C45-67C90BE1B931}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TDS", "Microsoft.Data.SqlClient\tests\tools\TDS\TDS\TDS.csproj", "{8DC9D1A0-351B-47BC-A90F-B9DA542550E9}" - ProjectSection(ProjectDependencies) = postProject - {FDA6971D-9F57-4DA4-B10A-261C91684CFC} = {FDA6971D-9F57-4DA4-B10A-261C91684CFC} - EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.Tests", "Microsoft.Data.SqlClient\tests\FunctionalTests\Microsoft.Data.SqlClient.Tests.csproj", "{D2D1E2D1-B6E0-489F-A36D-1F3047AB87B9}" ProjectSection(ProjectDependencies) = postProject @@ -28,7 +25,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "netfx", "netfx", "{3FDD425C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Address", "Microsoft.Data.SqlClient\tests\ManualTests\SQL\UdtTest\UDTs\Address\Address.csproj", "{D1392B54-998A-4F27-BC17-4CE149117BCC}" ProjectSection(ProjectDependencies) = postProject - {FDA6971D-9F57-4DA4-B10A-261C91684CFC} = {FDA6971D-9F57-4DA4-B10A-261C91684CFC} {37431336-5307-4184-9356-C4B7E47DC714} = {37431336-5307-4184-9356-C4B7E47DC714} {407890AC-9876-4FEF-A6F1-F36A876BAADE} = {407890AC-9876-4FEF-A6F1-F36A876BAADE} EndProjectSection @@ -40,13 +36,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.Ma EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Circle", "Microsoft.Data.SqlClient\tests\ManualTests\SQL\UdtTest\UDTs\Circle\Circle.csproj", "{6C88F00F-9597-43AD-9E5F-9B344DA3B16F}" ProjectSection(ProjectDependencies) = postProject - {FDA6971D-9F57-4DA4-B10A-261C91684CFC} = {FDA6971D-9F57-4DA4-B10A-261C91684CFC} {37431336-5307-4184-9356-C4B7E47DC714} = {37431336-5307-4184-9356-C4B7E47DC714} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shapes", "Microsoft.Data.SqlClient\tests\ManualTests\SQL\UdtTest\UDTs\Shapes\Shapes.csproj", "{B73A7063-37C3-415D-AD53-BB3DA20ABD6E}" ProjectSection(ProjectDependencies) = postProject - {FDA6971D-9F57-4DA4-B10A-261C91684CFC} = {FDA6971D-9F57-4DA4-B10A-261C91684CFC} {37431336-5307-4184-9356-C4B7E47DC714} = {37431336-5307-4184-9356-C4B7E47DC714} EndProjectSection EndProject @@ -72,8 +66,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.Al EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "add-ons", "add-ons", "{C9726AED-D6A3-4AAC-BA04-92DD1F079594}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.XUnitExtensions", "Microsoft.Data.SqlClient\tests\tools\Microsoft.DotNet.XUnitExtensions\Microsoft.DotNet.XUnitExtensions.csproj", "{FDA6971D-9F57-4DA4-B10A-261C91684CFC}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{ED952CF7-84DF-437A-B066-F516E9BE1C2C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "snippets", "snippets", "{71F356DC-DFA3-4163-8BFE-D268722CE189}" @@ -81,11 +73,13 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data", "Microsoft.Data", "{908C7DD3-C999-40A6-9433-9F5ACA7C36F5}" ProjectSection(SolutionItems) = preProject ..\doc\snippets\Microsoft.Data\OperationAbortedException.xml = ..\doc\snippets\Microsoft.Data\OperationAbortedException.xml + ..\doc\snippets\Microsoft.Data\SqlDbTypeExtensions.xml = ..\doc\snippets\Microsoft.Data\SqlDbTypeExtensions.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.Sql", "Microsoft.Data.Sql", "{0CE216CE-8072-4985-B248-61F0D0BE9C2E}" ProjectSection(SolutionItems) = preProject ..\doc\snippets\Microsoft.Data.Sql\SqlNotificationRequest.xml = ..\doc\snippets\Microsoft.Data.Sql\SqlNotificationRequest.xml + ..\doc\snippets\Microsoft.Data.Sql\SqlDataSourceEnumerator.xml = ..\doc\snippets\Microsoft.Data.Sql\SqlDataSourceEnumerator.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", "Microsoft.Data.SqlClient", "{C05F4FFE-6A14-4409-AA0A-10630BE4F1EE}" @@ -100,10 +94,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationParameters.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationParameters.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationProvider.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationProvider.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationToken.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlAuthenticationToken.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatch.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatch.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatchCommand.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatchCommand.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatchCommandCollection.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBatchCommandCollection.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopy.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopy.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnMapping.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnMapping.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnMappingCollection.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnMappingCollection.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyOptions.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyOptions.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientDiagnostic.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientDiagnostic.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientFactory.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientFactory.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientLogger.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientLogger.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientMetaDataCollectionNames.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlClientMetaDataCollectionNames.xml @@ -147,6 +145,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", ..\doc\snippets\Microsoft.Data.SqlClient\SqlRowUpdatingEventArgs.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRowUpdatingEventArgs.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlRowUpdatingEventHandler.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRowUpdatingEventHandler.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlTransaction.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlTransaction.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnOrderHint.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnOrderHint.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnOrderHintCollection.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlBulkCopyColumnOrderHintCollection.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlConfigurableRetryFactory.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConfigurableRetryFactory.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionIPAddressPreference.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionIPAddressPreference.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionOverrides.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionOverrides.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryingEventArgs.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryingEventArgs.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryIntervalBaseEnumerator.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryIntervalBaseEnumerator.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicBase.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicBase.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicBaseProvider.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicBaseProvider.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicOption.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlRetryLogicOption.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient.DataClassification", "Microsoft.Data.SqlClient.DataClassification", "{5D1F0032-7B0D-4FB6-A969-FCFB25C9EA1D}" @@ -156,38 +164,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient.Da ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\Label.xml = ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\Label.xml ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityClassification.xml = ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityClassification.xml ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityProperty.xml = ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityProperty.xml + ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityRank.xml = ..\doc\snippets\Microsoft.Data.SqlClient.DataClassification\SensitivityRank.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient.Server", "Microsoft.Data.SqlClient.Server", "{650EB7FA-EB0D-4F8E-AB2C-161C3AD8E363}" ProjectSection(SolutionItems) = preProject - ..\doc\snippets\Microsoft.Data.SqlClient.Server\DataAccessKind.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\DataAccessKind.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\Format.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\Format.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\IBinarySerialize.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\IBinarySerialize.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\InvalidUdtException.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\InvalidUdtException.xml ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlDataRecord.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlDataRecord.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlFacetAttribute.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlFacetAttribute.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlFunctionAttribute.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlFunctionAttribute.xml ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlMetaData.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlMetaData.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlMethodAttribute.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlMethodAttribute.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlUserDefinedAggregateAttribute.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlUserDefinedAggregateAttribute.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlUserDefinedTypeAttribute.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SqlUserDefinedTypeAttribute.xml - ..\doc\snippets\Microsoft.Data.SqlClient.Server\SystemDataAccessKind.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\SystemDataAccessKind.xml ..\doc\snippets\Microsoft.Data.SqlClient.Server\TriggerAction.xml = ..\doc\snippets\Microsoft.Data.SqlClient.Server\TriggerAction.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlTypes", "Microsoft.Data.SqlTypes", "{5A7600BD-AED8-44AB-8F2A-7CB33A8D9C02}" ProjectSection(SolutionItems) = preProject ..\doc\snippets\Microsoft.Data.SqlTypes\SqlFileStream.xml = ..\doc\snippets\Microsoft.Data.SqlTypes\SqlFileStream.xml + ..\doc\snippets\Microsoft.Data.SqlTypes\SqlJson.xml = ..\doc\snippets\Microsoft.Data.SqlTypes\SqlJson.xml EndProjectSection EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.NSLibrary", "Microsoft.Data.SqlClient\tests\NSLibrary\Microsoft.Data.SqlClient.NSLibrary.csproj", "{E7336BFB-8521-423A-A140-3123F9065C5D}" - ProjectSection(ProjectDependencies) = postProject - {37431336-5307-4184-9356-C4B7E47DC714} = {37431336-5307-4184-9356-C4B7E47DC714} - {407890AC-9876-4FEF-A6F1-F36A876BAADE} = {407890AC-9876-4FEF-A6F1-F36A876BAADE} - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.TestUtilities", "Microsoft.Data.SqlClient\tests\tools\Microsoft.Data.SqlClient.TestUtilities\Microsoft.Data.SqlClient.TestUtilities.csproj", "{89D6D382-9B36-43C9-A912-03802FDA8E36}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.ExtUtilities", "Microsoft.Data.SqlClient\tests\tools\Microsoft.Data.SqlClient.ExtUtilities\Microsoft.Data.SqlClient.ExtUtilities.csproj", "{E4C08DCE-DC29-4FEB-B655-1E7287DB5A2B}" @@ -202,9 +196,30 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.PerformanceTests", "Microsoft.Data.SqlClient\tests\PerformanceTests\Microsoft.Data.SqlClient.PerformanceTests.csproj", "{599A336B-2A5F-473D-8442-1223ED37C93E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4F3CD363-B1E6-4D6D-9466-97D78A56BE45}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlServer.Server", "Microsoft.SqlServer.Server\Microsoft.SqlServer.Server.csproj", "{A314812A-7820-4565-A2A8-ABBE391C11E4}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.SqlServer.Server", "Microsoft.SqlServer.Server", "{869A9BCC-D303-4365-9BF7-958CD6387916}" + ProjectSection(SolutionItems) = preProject + ..\doc\snippets\Microsoft.SqlServer.Server\DataAccessKind.xml = ..\doc\snippets\Microsoft.SqlServer.Server\DataAccessKind.xml + ..\doc\snippets\Microsoft.SqlServer.Server\Format.xml = ..\doc\snippets\Microsoft.SqlServer.Server\Format.xml + ..\doc\snippets\Microsoft.SqlServer.Server\IBinarySerialize.xml = ..\doc\snippets\Microsoft.SqlServer.Server\IBinarySerialize.xml + ..\doc\snippets\Microsoft.SqlServer.Server\InvalidUdtException.xml = ..\doc\snippets\Microsoft.SqlServer.Server\InvalidUdtException.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SqlFacetAttribute.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SqlFacetAttribute.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SqlFunctionAttribute.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SqlFunctionAttribute.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SqlMethodAttribute.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SqlMethodAttribute.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SqlUserDefinedAggregateAttribute.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SqlUserDefinedAggregateAttribute.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SqlUserDefinedTypeAttribute.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SqlUserDefinedTypeAttribute.xml + ..\doc\snippets\Microsoft.SqlServer.Server\SystemDataAccessKind.xml = ..\doc\snippets\Microsoft.SqlServer.Server\SystemDataAccessKind.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestClr", "TestClr", "{CDE508A5-F5D0-4A59-A4EF-978833830727}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlClient", "Microsoft.Data.SqlClient\src\Microsoft.Data.SqlClient.csproj", "{9A8996A8-6484-4AA7-B50F-F861430EDE2F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -383,18 +398,6 @@ Global {9073ABEF-92E0-4702-BB23-2C99CEF9BDD7}.Release|x64.Build.0 = Release|Any CPU {9073ABEF-92E0-4702-BB23-2C99CEF9BDD7}.Release|x86.ActiveCfg = Release|Any CPU {9073ABEF-92E0-4702-BB23-2C99CEF9BDD7}.Release|x86.Build.0 = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|x64.ActiveCfg = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|x64.Build.0 = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|x86.ActiveCfg = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Debug|x86.Build.0 = Debug|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|Any CPU.Build.0 = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|x64.ActiveCfg = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|x64.Build.0 = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|x86.ActiveCfg = Release|Any CPU - {FDA6971D-9F57-4DA4-B10A-261C91684CFC}.Release|x86.Build.0 = Release|Any CPU {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Debug|x64.ActiveCfg = Debug|Any CPU {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Debug|x64.Build.0 = Debug|Any CPU @@ -405,18 +408,6 @@ Global {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Release|x64.Build.0 = Release|Any CPU {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Release|x86.ActiveCfg = Release|Any CPU {F5DF2FDC-C860-4CB3-8B24-7C903C6FC076}.Release|x86.Build.0 = Release|Any CPU - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|x64.ActiveCfg = Debug|x64 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|x64.Build.0 = Debug|x64 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|x86.ActiveCfg = Debug|x86 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Debug|x86.Build.0 = Debug|x86 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|Any CPU.Build.0 = Release|Any CPU - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|x64.ActiveCfg = Release|x64 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|x64.Build.0 = Release|x64 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|x86.ActiveCfg = Release|x86 - {E7336BFB-8521-423A-A140-3123F9065C5D}.Release|x86.Build.0 = Release|x86 {89D6D382-9B36-43C9-A912-03802FDA8E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89D6D382-9B36-43C9-A912-03802FDA8E36}.Debug|Any CPU.Build.0 = Debug|Any CPU {89D6D382-9B36-43C9-A912-03802FDA8E36}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -489,6 +480,12 @@ Global {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x64.Build.0 = Release|Any CPU {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.ActiveCfg = Release|Any CPU {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.Build.0 = Release|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Debug|x64.ActiveCfg = Debug|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Debug|x86.ActiveCfg = Debug|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Release|x64.ActiveCfg = Release|Any CPU + {9A8996A8-6484-4AA7-B50F-F861430EDE2F}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -500,17 +497,12 @@ Global {8DC9D1A0-351B-47BC-A90F-B9DA542550E9} = {0CC4817A-12F3-4357-912C-09315FAAD008} {D2D1E2D1-B6E0-489F-A36D-1F3047AB87B9} = {0CC4817A-12F3-4357-912C-09315FAAD008} {37431336-5307-4184-9356-C4B7E47DC714} = {28E5EFE6-C9DD-4FF9-9FEC-532F72DFFA6E} - {D1392B54-998A-4F27-BC17-4CE149117BCC} = {0CC4817A-12F3-4357-912C-09315FAAD008} {45DB5F86-7AE3-45C6-870D-F9357B66BDB5} = {0CC4817A-12F3-4357-912C-09315FAAD008} - {6C88F00F-9597-43AD-9E5F-9B344DA3B16F} = {0CC4817A-12F3-4357-912C-09315FAAD008} - {B73A7063-37C3-415D-AD53-BB3DA20ABD6E} = {0CC4817A-12F3-4357-912C-09315FAAD008} - {E0A6BB21-574B-43D9-890D-6E1144F2EE9E} = {0CC4817A-12F3-4357-912C-09315FAAD008} {A2E7E470-5EFF-4828-B55E-FCBA3650F51C} = {28E5EFE6-C9DD-4FF9-9FEC-532F72DFFA6E} {1C9FC4B8-54BC-4B6C-BB3A-F5CD59D80A9B} = {A2E7E470-5EFF-4828-B55E-FCBA3650F51C} {771F3F1E-7A68-4A9D-ADA8-A24F1D5BE71D} = {3FDD425C-FE01-4B56-863E-1FCDD0677CF5} {412BCCC8-19F6-489A-B594-E9A506816155} = {771F3F1E-7A68-4A9D-ADA8-A24F1D5BE71D} {9073ABEF-92E0-4702-BB23-2C99CEF9BDD7} = {C9726AED-D6A3-4AAC-BA04-92DD1F079594} - {FDA6971D-9F57-4DA4-B10A-261C91684CFC} = {0CC4817A-12F3-4357-912C-09315FAAD008} {71F356DC-DFA3-4163-8BFE-D268722CE189} = {ED952CF7-84DF-437A-B066-F516E9BE1C2C} {908C7DD3-C999-40A6-9433-9F5ACA7C36F5} = {71F356DC-DFA3-4163-8BFE-D268722CE189} {0CE216CE-8072-4985-B248-61F0D0BE9C2E} = {71F356DC-DFA3-4163-8BFE-D268722CE189} @@ -518,13 +510,19 @@ Global {5D1F0032-7B0D-4FB6-A969-FCFB25C9EA1D} = {71F356DC-DFA3-4163-8BFE-D268722CE189} {650EB7FA-EB0D-4F8E-AB2C-161C3AD8E363} = {71F356DC-DFA3-4163-8BFE-D268722CE189} {5A7600BD-AED8-44AB-8F2A-7CB33A8D9C02} = {71F356DC-DFA3-4163-8BFE-D268722CE189} - {E7336BFB-8521-423A-A140-3123F9065C5D} = {0CC4817A-12F3-4357-912C-09315FAAD008} {89D6D382-9B36-43C9-A912-03802FDA8E36} = {0CC4817A-12F3-4357-912C-09315FAAD008} {E4C08DCE-DC29-4FEB-B655-1E7287DB5A2B} = {0CC4817A-12F3-4357-912C-09315FAAD008} {B499E477-C9B1-4087-A5CF-5C762D90E433} = {0CC4817A-12F3-4357-912C-09315FAAD008} {B93A3149-67E8-491E-A1E5-19D65F9D9E98} = {0CC4817A-12F3-4357-912C-09315FAAD008} {599A336B-2A5F-473D-8442-1223ED37C93E} = {0CC4817A-12F3-4357-912C-09315FAAD008} {A314812A-7820-4565-A2A8-ABBE391C11E4} = {4F3CD363-B1E6-4D6D-9466-97D78A56BE45} + {869A9BCC-D303-4365-9BF7-958CD6387916} = {71F356DC-DFA3-4163-8BFE-D268722CE189} + {CDE508A5-F5D0-4A59-A4EF-978833830727} = {0CC4817A-12F3-4357-912C-09315FAAD008} + {D1392B54-998A-4F27-BC17-4CE149117BCC} = {CDE508A5-F5D0-4A59-A4EF-978833830727} + {6C88F00F-9597-43AD-9E5F-9B344DA3B16F} = {CDE508A5-F5D0-4A59-A4EF-978833830727} + {B73A7063-37C3-415D-AD53-BB3DA20ABD6E} = {CDE508A5-F5D0-4A59-A4EF-978833830727} + {E0A6BB21-574B-43D9-890D-6E1144F2EE9E} = {CDE508A5-F5D0-4A59-A4EF-978833830727} + {9A8996A8-6484-4AA7-B50F-F861430EDE2F} = {4F3CD363-B1E6-4D6D-9466-97D78A56BE45} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {01D48116-37A2-4D33-B9EC-94793C702431} diff --git a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj index 3f2267451e..294a5c02b2 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj +++ b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj @@ -16,13 +16,27 @@ MIT true + + + true + $(SigningKeyPath) + + + $(SigningKeyPath) + + + $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(GeneratedSourceFileName)')) + + + + + - diff --git a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/SqlColumnEncryptionAzureKeyVaultProvider.cs b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/SqlColumnEncryptionAzureKeyVaultProvider.cs index d06063f8c0..eb8c8d77c4 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/SqlColumnEncryptionAzureKeyVaultProvider.cs +++ b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/SqlColumnEncryptionAzureKeyVaultProvider.cs @@ -241,7 +241,7 @@ byte[] DecryptEncryptionKey() byte[] message = new byte[encryptedColumnEncryptionKey.Length - signatureLength]; Buffer.BlockCopy(encryptedColumnEncryptionKey, 0, message, 0, encryptedColumnEncryptionKey.Length - signatureLength); - if (null == message) + if (message == null) { throw ADP.NullHashFound(); } diff --git a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Utils.cs b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Utils.cs index 2909422c1a..f71080ffab 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Utils.cs +++ b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Utils.cs @@ -45,7 +45,7 @@ internal static void ValidateNotNullOrWhitespaceForEach(string[] parameters, str internal static void ValidateEncryptionAlgorithm(string encryptionAlgorithm, bool isSystemOp) { // This validates that the encryption algorithm is RSA_OAEP - if (null == encryptionAlgorithm) + if (encryptionAlgorithm == null) { throw ADP.NullAlgorithm(isSystemOp); } @@ -124,8 +124,9 @@ internal static ArgumentException InvalidSignatureTemplate(string masterKeyPath) internal static ArgumentException InvalidAKVPath(string masterKeyPath, bool isSystemOp) { - string errorMessage = null == masterKeyPath ? Strings.NullAkvPath - : string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvPathTemplate, masterKeyPath); + string errorMessage = masterKeyPath == null + ? Strings.NullAkvPath + : string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvPathTemplate, masterKeyPath); if (isSystemOp) { return new ArgumentNullException(Constants.AeParamMasterKeyPath, errorMessage); diff --git a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props index 2cce61f7ac..d0bf4f7757 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props +++ b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props @@ -11,13 +11,12 @@ Project $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true - $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) + $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFramework)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) net462 - netstandard2.0 net6.0 @@ -28,15 +27,14 @@ - $(TargetNetFxVersion);$(TargetNetCoreVersion);$(TargetNetStandardVersion) - $(TargetNetCoreVersion);$(TargetNetStandardVersion) + $(TargetNetCoreVersion);$(TargetNetFxVersion) + $(TargetNetCoreVersion) - netstandard2.0;netstandard2.1 - net6.0;net7.0 + net6.0;net8.0 net462 diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.NetStandard.cs deleted file mode 100644 index bdb2042b84..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.NetStandard.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the http://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -namespace Microsoft.Data.SqlClient -{ - /// - public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthenticationProvider - { - /// - public void SetParentActivityOrWindowFunc(System.Func parentActivityOrWindowFunc) { } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index 92cb042b76..99f8058a21 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -13,7 +13,15 @@ public sealed partial class OperationAbortedException : System.SystemException { internal OperationAbortedException() { } } + + /// + public static class SqlDbTypeExtensions + { + /// + public const System.Data.SqlDbType Json = (System.Data.SqlDbType)35; + } } + namespace Microsoft.Data.Sql { /// @@ -92,6 +100,25 @@ public override void EndWrite(System.IAsyncResult asyncResult) { } /// public override void WriteByte(byte value) { } } + + /// + public class SqlJson : System.Data.SqlTypes.INullable + { + /// + public SqlJson() { } + /// + public SqlJson(string jsonString) { } + /// + public SqlJson(System.Text.Json.JsonDocument jsonDoc) { } + /// + public bool IsNull => throw null; + /// + public static SqlJson Null => throw null; + /// + public string Value { get { throw null; } } + /// + virtual public SqlJson GetSqlJson(int i) { throw null; } + } } namespace Microsoft.Data.SqlClient { @@ -160,12 +187,16 @@ protected SqlAuthenticationInitializer() { } /// public enum SqlAuthenticationMethod { + /// + NotSpecified = 0, + /// + SqlPassword = 1, + /// + ActiveDirectoryPassword = 2, /// ActiveDirectoryIntegrated = 3, /// ActiveDirectoryInteractive = 4, - /// - ActiveDirectoryPassword = 2, /// ActiveDirectoryServicePrincipal = 5, /// @@ -176,10 +207,8 @@ public enum SqlAuthenticationMethod ActiveDirectoryMSI = 8, /// ActiveDirectoryDefault = 9, - /// - NotSpecified = 0, - /// - SqlPassword = 1 + /// + ActiveDirectoryWorkloadIdentity = 10 } /// public class SqlAuthenticationParameters @@ -187,23 +216,23 @@ public class SqlAuthenticationParameters /// protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int connectionTimeout) { } /// - public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string Authority { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Authority { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public System.Guid ConnectionId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public System.Guid ConnectionId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string DatabaseName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string DatabaseName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string Password { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Password { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public int ConnectionTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public int ConnectionTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } /// public abstract partial class SqlAuthenticationProvider @@ -229,9 +258,9 @@ public partial class SqlAuthenticationToken /// public SqlAuthenticationToken(string accessToken, System.DateTimeOffset expiresOn) { } /// - public string AccessToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public string AccessToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } /// - public System.DateTimeOffset ExpiresOn { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public System.DateTimeOffset ExpiresOn { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } /// public sealed partial class SqlBulkCopy : System.IDisposable @@ -304,13 +333,13 @@ public sealed partial class SqlBulkCopyColumnMapping { /// public SqlBulkCopyColumnMapping() { } - /// + /// public SqlBulkCopyColumnMapping(int sourceColumnOrdinal, int destinationOrdinal) { } - /// + /// public SqlBulkCopyColumnMapping(int sourceColumnOrdinal, string destinationColumn) { } - /// + /// public SqlBulkCopyColumnMapping(string sourceColumn, int destinationOrdinal) { } - /// + /// public SqlBulkCopyColumnMapping(string sourceColumn, string destinationColumn) { } /// public string DestinationColumn { get { throw null; } set { } } @@ -329,13 +358,13 @@ internal SqlBulkCopyColumnMappingCollection() { } public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping this[int index] { get { throw null; } } /// public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping Add(Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping bulkCopyColumnMapping) { throw null; } - /// + /// public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping Add(int sourceColumnIndex, int destinationColumnIndex) { throw null; } - /// + /// public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping Add(int sourceColumnIndex, string destinationColumn) { throw null; } - /// + /// public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping Add(string sourceColumn, int destinationColumnIndex) { throw null; } - /// + /// public Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping Add(string sourceColumn, string destinationColumn) { throw null; } /// public new void Clear() { } @@ -355,7 +384,7 @@ public void Remove(Microsoft.Data.SqlClient.SqlBulkCopyColumnMapping value) { } /// public sealed class SqlBulkCopyColumnOrderHint { - /// + /// public SqlBulkCopyColumnOrderHint(string column, SortOrder sortOrder) { } /// public string Column { get { throw null; } set { } } @@ -426,6 +455,30 @@ internal SqlClientFactory() { } public override System.Data.Common.DbDataAdapter CreateDataAdapter() { throw null; } /// public override System.Data.Common.DbParameter CreateParameter() { throw null; } + /// + public override System.Data.Common.DbDataSourceEnumerator CreateDataSourceEnumerator() { throw null; } + /// + public override bool CanCreateBatch { get { throw null; } } + /// + public override System.Data.Common.DbBatch CreateBatch() { throw null; } + /// + public override System.Data.Common.DbBatchCommand CreateBatchCommand() { throw null; } + } + /// + public partial class SqlClientLogger + { + /// + public SqlClientLogger() { } + /// + public bool IsLoggingEnabled { get { throw null; } } + /// + public void LogWarning(string type, string method, string message) { } + /// + public bool LogAssert(bool value, string type, string method, string message) { throw null; } + /// + public void LogError(string type, string method, string message) { } + /// + public void LogInfo(string type, string method, string message) { } } /// public partial class SqlClientLogger @@ -477,7 +530,7 @@ public static partial class SqlClientMetaDataCollectionNames /// public static readonly string StructuredTypeMembers; } -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET6_0_OR_GREATER /// public enum SqlConnectionAttestationProtocol { @@ -676,15 +729,15 @@ public event System.Data.StatementCompletedEventHandler StatementCompleted { add public System.IAsyncResult BeginExecuteNonQuery(System.AsyncCallback callback, object stateObject) { throw null; } /// public System.IAsyncResult BeginExecuteReader() { throw null; } - /// + /// public System.IAsyncResult BeginExecuteReader(System.AsyncCallback callback, object stateObject) { throw null; } - /// + /// public System.IAsyncResult BeginExecuteReader(System.AsyncCallback callback, object stateObject, System.Data.CommandBehavior behavior) { throw null; } /// public System.IAsyncResult BeginExecuteReader(System.Data.CommandBehavior behavior) { throw null; } /// public System.IAsyncResult BeginExecuteXmlReader() { throw null; } - /// + /// public System.IAsyncResult BeginExecuteXmlReader(System.AsyncCallback callback, object stateObject) { throw null; } /// public override void Cancel() { } @@ -697,7 +750,7 @@ public override void Cancel() { } public new Microsoft.Data.SqlClient.SqlParameter CreateParameter() { throw null; } /// public int EndExecuteNonQuery(System.IAsyncResult asyncResult) { throw null; } - /// + /// public Microsoft.Data.SqlClient.SqlDataReader EndExecuteReader(System.IAsyncResult asyncResult) { throw null; } /// public System.Xml.XmlReader EndExecuteXmlReader(System.IAsyncResult asyncResult) { throw null; } @@ -854,6 +907,7 @@ public void RegisterColumnEncryptionKeyStoreProvidersOnConnection(System.Collect [System.ComponentModel.DesignerSerializationVisibilityAttribute(0)] internal string SQLDNSCachingSupportedStateBeforeRedirect { get { throw null; } } + /// object System.ICloneable.Clone() { throw null; } /// [System.ComponentModel.DesignerSerializationVisibilityAttribute(0)] @@ -1016,7 +1070,7 @@ public SqlConnectionStringBuilder(string connectionString) { } [System.ComponentModel.DisplayNameAttribute("Data Source")] [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)] public string DataSource { get { throw null; } set { } } -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER +#if NET6_0_OR_GREATER /// [System.ComponentModel.DisplayNameAttribute("Attestation Protocol")] [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)] @@ -1105,7 +1159,8 @@ public SqlConnectionStringBuilder(string connectionString) { } /// [System.ComponentModel.DisplayNameAttribute("Pool Blocking Period")] [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)] - public PoolBlockingPeriod PoolBlockingPeriod { get { throw null; } set { } }/// + public PoolBlockingPeriod PoolBlockingPeriod { get { throw null; } set { } } + /// [System.ComponentModel.DisplayNameAttribute("Pooling")] [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)] public bool Pooling { get { throw null; } set { } } @@ -1185,9 +1240,13 @@ public SqlDataAdapter(string selectCommandText, string selectConnectionString) { /// [System.ComponentModel.DefaultValueAttribute(null)] public new Microsoft.Data.SqlClient.SqlCommand SelectCommand { get { throw null; } set { } } + /// System.Data.IDbCommand System.Data.IDbDataAdapter.DeleteCommand { get { throw null; } set { } } + /// System.Data.IDbCommand System.Data.IDbDataAdapter.InsertCommand { get { throw null; } set { } } + /// System.Data.IDbCommand System.Data.IDbDataAdapter.SelectCommand { get { throw null; } set { } } + /// System.Data.IDbCommand System.Data.IDbDataAdapter.UpdateCommand { get { throw null; } set { } } /// public override int UpdateBatchSize { get { throw null; } set { } } @@ -1202,6 +1261,7 @@ public event Microsoft.Data.SqlClient.SqlRowUpdatingEventHandler RowUpdating { a protected override void OnRowUpdated(System.Data.Common.RowUpdatedEventArgs value) { } /// protected override void OnRowUpdating(System.Data.Common.RowUpdatingEventArgs value) { } + /// object System.ICloneable.Clone() { throw null; } } /// @@ -1441,9 +1501,13 @@ internal SqlException() { } public override string Source { get { throw null; } } /// public byte State { get { throw null; } } + /// -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)] +#endif +#if NET8_0_OR_GREATER + [System.Obsolete("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] #endif public override void GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) { } /// @@ -1452,6 +1516,7 @@ public override void GetObjectData(System.Runtime.Serialization.SerializationInf /// public sealed partial class SqlInfoMessageEventArgs : System.EventArgs { + /// internal SqlInfoMessageEventArgs() { } /// public Microsoft.Data.SqlClient.SqlErrorCollection Errors { get { throw null; } } @@ -1572,6 +1637,7 @@ public SqlParameter(string parameterName, System.Data.SqlDbType dbType, int size public SqlParameter(string parameterName, System.Data.SqlDbType dbType, int size, string sourceColumn) { } /// public SqlParameter(string parameterName, object value) { } + /// object System.ICloneable.Clone() { throw null; } /// [System.ComponentModel.BrowsableAttribute(false)] @@ -1646,6 +1712,7 @@ public void ResetSqlDbType() { } [System.ComponentModel.ListBindableAttribute(false)] public sealed partial class SqlParameterCollection : System.Data.Common.DbParameterCollection { + /// internal SqlParameterCollection() { } /// public override int Count { get { throw null; } } @@ -1895,6 +1962,316 @@ public sealed class SqlConfigurableRetryFactory public static SqlRetryLogicBaseProvider CreateNoneRetryProvider() { throw null; } } } +namespace Microsoft.Data.SqlClient.Diagnostics +{ + /// + public abstract class SqlClientDiagnostic : System.Collections.Generic.IReadOnlyList> + { + internal SqlClientDiagnostic() { } + /// + protected const int CommonPropertyCount = 3; + /// + protected SqlClientDiagnostic(System.Guid operationId, string operation, long timestamp) { } + /// + public System.Guid OperationId => throw null; + /// + public string Operation => throw null; + /// + public long Timestamp => throw null; + /// > + public int Count => CommonPropertyCount + GetDerivedCount(); + /// > + public System.Collections.Generic.KeyValuePair this[int index] => throw null; + /// > + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + /// > + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); + /// + protected bool TryGetCommonProperty(int index, out System.Collections.Generic.KeyValuePair property) => throw null; + /// + protected abstract int GetDerivedCount(); + /// + protected abstract System.Collections.Generic.KeyValuePair GetDerivedProperty(int index); + } + + /// + public sealed class SqlClientCommandBefore : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandBefore"; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// > + protected sealed override int GetDerivedCount() => 3; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientCommandAfter : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandAfter"; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientCommandError : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandError"; + /// + public System.Guid? ConnectionId => throw null; + /// + public long? TransactionId => throw null; + /// + public SqlCommand Command => throw null; + /// + public System.Exception Exception { get; } + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionOpenBefore : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenBefore"; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// > + protected override int GetDerivedCount() => 2; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionOpenAfter : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenAfter"; + /// + public System.Guid ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// > + protected override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionOpenError : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenError"; + /// + public System.Guid ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public string ClientVersion => throw null; + /// + public System.Exception Exception => throw null; + /// > + protected override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionCloseBefore : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseBefore"; + /// + public System.Guid? ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// > + protected sealed override int GetDerivedCount() => 3; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionCloseAfter : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseAfter"; + + /// + public System.Guid? ConnectionId => throw null; + + /// + public SqlConnection Connection => throw null; + + /// + public System.Collections.IDictionary Statistics => throw null; + + /// > + protected sealed override int GetDerivedCount() => 3; + + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientConnectionCloseError : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseError"; + /// + public System.Guid? ConnectionId => throw null; + /// + public SqlConnection Connection => throw null; + /// + public System.Collections.IDictionary Statistics => throw null; + /// + public System.Exception Exception => throw null; + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionCommitBefore : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitBefore"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// > + protected sealed override int GetDerivedCount() => 3; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionCommitAfter : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitAfter"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// > + protected sealed override int GetDerivedCount() => 3; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionCommitError : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitError"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public System.Exception Exception => throw null; + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionRollbackBefore : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackBefore"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionRollbackAfter : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackAfter"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// > + protected sealed override int GetDerivedCount() => 4; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } + + /// + public sealed class SqlClientTransactionRollbackError : SqlClientDiagnostic + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackError"; + /// + public System.Data.IsolationLevel IsolationLevel => throw null; + /// + public SqlConnection Connection => throw null; + /// + public long? TransactionId => throw null; + /// + public string TransactionName => throw null; + /// + public System.Exception Exception => throw null; + /// > + protected sealed override int GetDerivedCount() => 5; + /// > + protected sealed override System.Collections.Generic.KeyValuePair GetDerivedProperty(int index) => throw null; + } +} namespace Microsoft.Data.SqlClient.Server { /// diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj index 96308eae65..41a471847e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj @@ -1,28 +1,32 @@  false - net7.0;net6.0;netstandard2.0;netstandard2.1 - netstandard2.1 + net6.0;net8.0 $(ObjFolder)$(Configuration)\$(AssemblyName)\ref\ $(BinFolder)$(Configuration)\$(AssemblyName)\ref\ $(OutputPath)\$(TargetFramework)\Microsoft.Data.SqlClient.xml Core $(BaseProduct) Debug;Release; netcoreapp - netstandard AnyCPU;x64;x86 + + + true + $(SigningKeyPath) + $(SigningKeyPath) + + + $(SigningKeyPath) + + - - - - - - + + - + diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/Interop.Libraries.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/Interop.Libraries.cs similarity index 92% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/Interop.Libraries.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/Interop.Libraries.cs index c4f2f36493..7b74001a4f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/Interop.Libraries.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/Interop.Libraries.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + internal static partial class Interop { internal static partial class Libraries @@ -10,3 +12,5 @@ internal static partial class Libraries internal const string NetSecurityNative = "System.Net.Security.Native"; } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs index b08b41aeb2..34bc0b18dd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssApiException.cs @@ -2,9 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Data; +#if !NET8_0_OR_GREATER + using System; using System.Runtime.InteropServices; +using Microsoft.Data; internal static partial class Interop { @@ -56,3 +58,5 @@ private static string GetGssApiDisplayStatus(Status status, bool isMinor) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs index 0f479a8c62..112289bc7d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.GssBuffer.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Data; +#if !NET8_0_OR_GREATER + using System; using System.Diagnostics; using System.Runtime.InteropServices; +using Microsoft.Data; internal static partial class Interop { @@ -74,3 +76,5 @@ static GssBuffer() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs index 489d1cf8a9..f5e7d18f24 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs @@ -2,8 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; -using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; @@ -126,3 +127,5 @@ static NetSecurityNative() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates.cs index 2fb8e48a1d..6b8e616894 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; using System.Runtime.InteropServices; @@ -24,3 +26,5 @@ internal static extern bool CertVerifyCertificateChainPolicy( [In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates_types.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates_types.cs index cbf5c3309e..c120f1ba71 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/Crypt32/Interop.certificates_types.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; using System.Runtime.InteropServices; @@ -125,3 +127,5 @@ internal unsafe struct CERT_CHAIN_POLICY_STATUS } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs index 435de74c59..dfd98621d6 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/Interop.SECURITY_STATUS.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + internal static partial class Interop { internal enum SECURITY_STATUS @@ -358,3 +360,5 @@ internal static string MapSecurityStatus(uint statusCode) } #endif // TRACE_VERBOSE } + +#endif // !NET8_OR_GREATER diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/Interop.SecPkgContext_ApplicationProtocol.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/Interop.SecPkgContext_ApplicationProtocol.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/Interop.SecPkgContext_ApplicationProtocol.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/Interop.SecPkgContext_ApplicationProtocol.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs index 57b6eb3405..762c3ea146 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/SChannel/SecPkgContext_ConnectionInfo.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -45,3 +46,5 @@ internal unsafe SecPkgContext_ConnectionInfo(byte[] nativeBuffer) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.CloseHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.CloseHandle.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.CloseHandle.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.CloseHandle.cs index ff41f939f1..f133f10156 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.CloseHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.CloseHandle.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; using System.Runtime.InteropServices; @@ -13,3 +15,5 @@ internal partial class Kernel32 internal static extern bool CloseHandle(IntPtr handle); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.FreeLibrary.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.FreeLibrary.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.FreeLibrary.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.FreeLibrary.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetProcAddress.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.GetProcAddress.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetProcAddress.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.GetProcAddress.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.LoadLibraryEx.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.LoadLibraryEx.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.LoadLibraryEx.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/kernel32/Interop.LoadLibraryEx.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/GlobalSSPI.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/GlobalSSPI.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/GlobalSSPI.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/GlobalSSPI.cs index 78571c5c96..6077ba5a77 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/GlobalSSPI.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/GlobalSSPI.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + namespace System.Net { internal static class GlobalSSPI @@ -10,3 +12,5 @@ internal static class GlobalSSPI internal static readonly SSPIInterface SSPISecureChannel = new SSPISecureChannelType(); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/Interop.SSPI.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/Interop.SSPI.cs index 8ceed0e870..bb8d1ede6a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/Interop.SSPI.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; using System.Net.Security; using System.Runtime.InteropServices; @@ -388,3 +390,5 @@ internal static extern unsafe SECURITY_STATUS SspiEncodeStringsAsAuthIdentity( [Out] out SafeSspiAuthDataHandle authData); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/NegotiationInfoClass.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/NegotiationInfoClass.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/NegotiationInfoClass.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/NegotiationInfoClass.cs index f5f7ab1b07..133c935174 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/NegotiationInfoClass.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/NegotiationInfoClass.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -59,3 +61,5 @@ internal NegotiationInfoClass(SafeHandle safeHandle, int negotiationState) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIAuthType.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIAuthType.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIAuthType.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIAuthType.cs index cdb3819605..4a86701ffd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIAuthType.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIAuthType.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Net.Security; using System.Runtime.InteropServices; using Microsoft.Data; @@ -199,3 +201,5 @@ public int ApplyControlToken(ref SafeDeleteContext refContext, SecurityBuffer[] } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIInterface.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIInterface.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIInterface.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIInterface.cs index 655dcec07a..22e9a3c93d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIInterface.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIInterface.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Net.Security; using System.Runtime.InteropServices; @@ -30,3 +32,5 @@ internal interface SSPIInterface int ApplyControlToken(ref SafeDeleteContext refContext, SecurityBuffer[] inputBuffers); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPISecureChannelType.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPISecureChannelType.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPISecureChannelType.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPISecureChannelType.cs index 4152a89a7d..e6c213d241 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPISecureChannelType.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPISecureChannelType.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Net.Security; using System.Runtime.InteropServices; using Microsoft.Data; @@ -155,3 +157,5 @@ public int ApplyControlToken(ref SafeDeleteContext refContext, SecurityBuffer[] } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIWrapper.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIWrapper.cs index f8231f9069..1ad4a18c45 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SSPIWrapper.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.ComponentModel; using System.Globalization; using System.Net.Security; @@ -404,8 +406,7 @@ public static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SSP public static object QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute) { - int errorCode; - return QueryContextAttributes(secModule, securityContext, contextAttribute, out errorCode); + return QueryContextAttributes(secModule, securityContext, contextAttribute, out _); } public static object QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute, out int errorCode) @@ -595,3 +596,5 @@ public static string ErrorDescription(int errorCode) } } // class SSPIWrapper } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SafeDeleteContext.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SafeDeleteContext.cs similarity index 92% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SafeDeleteContext.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SafeDeleteContext.cs index cc9f80164f..7701689286 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SafeDeleteContext.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SafeDeleteContext.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; +#if !NET8_0_OR_GREATER -using System.Diagnostics; using System.Runtime.InteropServices; -using System.Security.Authentication.ExtendedProtection; namespace System.Net.Security { @@ -53,3 +51,5 @@ public override string ToString() #endif } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Bindings.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Bindings.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Bindings.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Bindings.cs index eb31544de1..f5bbb448eb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Bindings.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Bindings.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -14,3 +16,5 @@ internal struct SecPkgContext_Bindings internal IntPtr Bindings; } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs index 4dc03b53a6..a5c71068eb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_NegotiationInfoW.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -14,3 +16,5 @@ internal struct SecPkgContext_NegotiationInfoW internal uint NegotiationState; } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Sizes.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Sizes.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Sizes.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Sizes.cs index 48cdd54d2a..17fce36c6d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_Sizes.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_Sizes.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -40,3 +41,5 @@ internal unsafe SecPkgContext_Sizes(byte[] memory) public static readonly int SizeOf = Marshal.SizeOf(); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs index 519b607da7..98ec1a1d60 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecPkgContext_StreamSizes.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -42,3 +43,5 @@ internal unsafe SecPkgContext_StreamSizes(byte[] memory) public static readonly int SizeOf = Marshal.SizeOf(); } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfo.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfo.cs similarity index 94% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfo.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfo.cs index 3ec3c7fda6..73e9c8635c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfo.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfo.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; namespace System.Net @@ -18,3 +20,5 @@ internal struct SecurityPackageInfo internal IntPtr Comment; } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfoClass.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfoClass.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfoClass.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfoClass.cs index 74fca62e89..433904171e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecurityPackageInfoClass.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecurityPackageInfoClass.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Globalization; using System.Runtime.InteropServices; @@ -76,3 +78,5 @@ public override string ToString() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecuritySafeHandles.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecuritySafeHandles.cs index f78b10697d..ccebeecf0a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Interop/Windows/sspicli/SecuritySafeHandles.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; +#if !NET8_0_OR_GREATER using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.Security.Authentication.ExtendedProtection; +using Microsoft.Win32.SafeHandles; namespace System.Net.Security { @@ -213,7 +214,6 @@ public static unsafe int AcquireDefaultCredential( NetEventSource.Enter(null, package, intent); int errorCode = -1; - long timeStamp; outCredential = new SafeFreeCredential_SECURITY(); @@ -226,7 +226,7 @@ public static unsafe int AcquireDefaultCredential( null, null, ref outCredential._handle, - out timeStamp); + out _); #if TRACE_VERBOSE if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"{nameof(Interop.SspiCli.AcquireCredentialsHandleW)} returns 0x{errorCode:x}, handle = {outCredential}"); @@ -247,7 +247,6 @@ public static unsafe int AcquireCredentialsHandle( out SafeFreeCredentials outCredential) { int errorCode = -1; - long timeStamp; outCredential = new SafeFreeCredential_SECURITY(); errorCode = Interop.SspiCli.AcquireCredentialsHandleW( @@ -259,7 +258,7 @@ public static unsafe int AcquireCredentialsHandle( null, null, ref outCredential._handle, - out timeStamp); + out _); if (errorCode != 0) { @@ -279,7 +278,6 @@ public static unsafe int AcquireCredentialsHandle( NetEventSource.Enter(null, package, intent, authdata); int errorCode = -1; - long timeStamp; // If there is a certificate, wrap it into an array. @@ -304,7 +302,7 @@ public static unsafe int AcquireCredentialsHandle( null, null, ref outCredential._handle, - out timeStamp); + out _); } finally { @@ -631,8 +629,6 @@ private static unsafe int MustRunInitializeSecurityContext( Interop.SspiCli.CredHandle credentialHandle = inCredentials._handle; - long timeStamp; - errorCode = Interop.SspiCli.InitializeSecurityContextW( ref credentialHandle, inContextPtr, @@ -645,7 +641,7 @@ private static unsafe int MustRunInitializeSecurityContext( ref outContext._handle, ref outputBuffer, ref attributes, - out timeStamp); + out _); } finally { @@ -918,7 +914,6 @@ private static unsafe int MustRunAcceptSecurityContext_SECURITY( outContext.DangerousAddRef(ref ignore); Interop.SspiCli.CredHandle credentialHandle = inCredentials._handle; - long timeStamp; errorCode = Interop.SspiCli.AcceptSecurityContext( ref credentialHandle, @@ -929,7 +924,7 @@ private static unsafe int MustRunAcceptSecurityContext_SECURITY( ref outContext._handle, ref outputBuffer, ref outFlags, - out timeStamp); + out _); } finally { @@ -1279,3 +1274,5 @@ protected override bool ReleaseHandle() } } } + +#endif // !NET8_OR_GREATER diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Data/ProviderBase/DbConnectionInternal.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Data/ProviderBase/DbConnectionInternal.cs index 516aa9b7a9..fd5e3e2848 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Data/ProviderBase/DbConnectionInternal.cs @@ -63,7 +63,7 @@ internal bool CanBePooled { get { - return (!_connectionIsDoomed && !_cannotBePooled && !_owningObject.TryGetTarget(out DbConnection _)); + return (!_connectionIsDoomed && !_cannotBePooled && !_owningObject.TryGetTarget(out _)); } } @@ -102,7 +102,7 @@ internal bool IsEmancipated // of the pool and it's owning object is no longer around to // return it. - return (_pooledCount < 1) && !_owningObject.TryGetTarget(out DbConnection _); + return (_pooledCount < 1) && !_owningObject.TryGetTarget(out _); } } @@ -178,10 +178,10 @@ public ConnectionState State internal void AddWeakReference(object value, int tag) { - if (null == _referenceCollection) + if (_referenceCollection == null) { _referenceCollection = CreateReferenceCollection(); - if (null == _referenceCollection) + if (_referenceCollection == null) { throw ADP.InternalError(ADP.InternalErrorCode.CreateReferenceCollectionReturnedNull); } @@ -300,7 +300,7 @@ internal void MakePooledConnection(DbConnectionPool connectionPool) internal void NotifyWeakReference(int message) { DbReferenceCollection referenceCollection = ReferenceCollection; - if (null != referenceCollection) + if (referenceCollection != null) { referenceCollection.Notify(message); } @@ -349,7 +349,7 @@ protected bool TryOpenConnectionInternal(DbConnection outerConnection, DbConnect connectionFactory.SetInnerConnectionTo(outerConnection, this); throw; } - if (null == openConnection) + if (openConnection == null) { connectionFactory.SetInnerConnectionTo(outerConnection, this); throw ADP.InternalConnectionError(ADP.ConnectionError.GetConnectionReturnsNull); @@ -409,7 +409,7 @@ internal void PostPop(DbConnection newOwner) // IMPORTANT NOTE: You must have taken a lock on the object before // you call this method to prevent race conditions with Clear and // ReclaimEmancipatedObjects. - if (_owningObject.TryGetTarget(out DbConnection _)) + if (_owningObject.TryGetTarget(out _)) { throw ADP.InternalError(ADP.InternalErrorCode.PooledObjectHasOwner); // pooled connection already has an owner! } @@ -418,7 +418,7 @@ internal void PostPop(DbConnection newOwner) SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Preparing to pop from pool, owning connection {1}, pooledCount={2}", ObjectID, 0, _pooledCount); //3 // The following tests are retail assertions of things we can't allow to happen. - if (null != Pool) + if (Pool != null) { if (0 != _pooledCount) { @@ -434,7 +434,7 @@ internal void PostPop(DbConnection newOwner) internal void RemoveWeakReference(object value) { DbReferenceCollection referenceCollection = ReferenceCollection; - if (null != referenceCollection) + if (referenceCollection != null) { referenceCollection.Remove(value); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Win32/SafeHandles/GssSafeHandles.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Win32/SafeHandles/GssSafeHandles.cs index 6921ef6aba..6a5a8b17c8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Win32/SafeHandles/GssSafeHandles.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -135,3 +137,5 @@ protected override bool ReleaseHandle() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Collections/Generic/BidirectionalDictionary.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Collections/Generic/BidirectionalDictionary.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Collections/Generic/BidirectionalDictionary.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Collections/Generic/BidirectionalDictionary.cs index 32c4463433..2bf8459e1b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Collections/Generic/BidirectionalDictionary.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Collections/Generic/BidirectionalDictionary.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics; namespace System.Collections.Generic @@ -59,3 +61,5 @@ IEnumerator IEnumerable.GetEnumerator() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/System/IO/PathInternal.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/IO/PathInternal.Windows.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/System/IO/PathInternal.Windows.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/IO/PathInternal.Windows.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Unix.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Unix.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Unix.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Unix.cs index 599bd4ab7d..148e0bb76d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Unix.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Unix.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#if !NET8_0_OR_GREATER namespace System.Net { @@ -84,3 +84,5 @@ internal static Interop.NetSecurityNative.GssFlags GetInteropFromContextFlagsPal } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Windows.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Windows.cs index 5ed6e347d8..036f24d4ed 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsAdapterPal.Windows.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#if !NET8_0_OR_GREATER namespace System.Net { @@ -75,3 +75,5 @@ internal static Interop.SspiCli.ContextFlags GetInteropFromContextFlagsPal(Conte } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsPal.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsPal.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsPal.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsPal.cs index d4df40b597..f0df3bd677 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/ContextFlagsPal.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/ContextFlagsPal.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#if !NET8_0_OR_GREATER namespace System.Net { @@ -33,3 +33,5 @@ internal enum ContextFlagsPal UnverifiedTargetName = 0x20000000, } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs similarity index 96% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs index 1949341de2..a9d0965324 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleMinusOneIsInvalid.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if DEBUG && !NET8_0_OR_GREATER + using Microsoft.Win32.SafeHandles; namespace System.Net { -#if DEBUG // // This is a helper class for debugging GC-ed handles that we define. // As a general rule normal code path should always destroy handles explicitly @@ -38,5 +39,6 @@ private void Trace() NetEventSource.Info(this, _trace); } } -#endif // DEBUG } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs similarity index 95% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs index c28a7107b1..fcb485d568 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugCriticalHandleZeroOrMinusOneIsInvalid.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if DEBUG && !NET8_0_OR_GREATER + using Microsoft.Win32.SafeHandles; namespace System.Net { -#if DEBUG // // This is a helper class for debugging GC-ed handles that we define. // As a general rule normal code path should always destroy handles explicitly @@ -38,5 +39,6 @@ private void Trace() NetEventSource.Info(this, _trace); } } -#endif // DEBUG } + +#endif // !NET8_0_OR_GREATER diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugSafeHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugSafeHandle.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugSafeHandle.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugSafeHandle.cs index b0646f92e9..55d5bd8a6f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/DebugSafeHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/DebugSafeHandle.cs @@ -2,17 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; +#if DEBUG && !NET8_0_OR_GREATER using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using Microsoft.Win32.SafeHandles; namespace System.Net { -#if DEBUG // // This is a helper class for debugging GC-ed handles that we define. // As a general rule normal code path should always destroy handles explicitly @@ -47,5 +47,6 @@ private void Trace() NetEventSource.Info(this, _trace); } } -#endif // DEBUG } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/InternalException.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/InternalException.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/InternalException.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/InternalException.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/DebugThreadTracking.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/DebugThreadTracking.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/DebugThreadTracking.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/DebugThreadTracking.cs index 78d8d48ac6..cd66ff2287 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/DebugThreadTracking.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/DebugThreadTracking.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Collections.Generic; namespace System.Net @@ -162,3 +164,5 @@ internal enum ThreadKinds ThreadPool = CompletionPort | Worker, // Like Thread.CurrentThread.IsThreadPoolThread } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/NetEventSource.Common.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/NetEventSource.Common.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/NetEventSource.Common.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/NetEventSource.Common.cs index 5b908a3b8e..1e56818132 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Logging/NetEventSource.Common.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Logging/NetEventSource.Common.cs @@ -13,7 +13,7 @@ using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if net462 +#if NETFRAMEWORK using System.Security; #endif @@ -45,7 +45,7 @@ namespace System.Net // method that takes an object and optionally provides a string representation of it, in case a particular library wants to customize further. /// Provides logging facilities for System.Net libraries. -#if net462 +#if NETFRAMEWORK [SecuritySafeCritical] #endif internal sealed partial class NetEventSource : EventSource diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/NegotiationInfoClass.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/NegotiationInfoClass.cs similarity index 94% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/NegotiationInfoClass.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/NegotiationInfoClass.cs index 560098ef4c..d931c7c70d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/NegotiationInfoClass.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/NegotiationInfoClass.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + namespace System.Net { // This class is used to determine if NTLM or @@ -14,3 +16,5 @@ internal partial class NegotiationInfoClass internal const string Basic = "Basic"; } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Unix.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Unix.cs index 70c1a74377..f670a086cf 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Unix.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.ComponentModel; using System.Diagnostics; using Microsoft.Win32.SafeHandles; @@ -246,3 +248,5 @@ internal static SafeFreeCredentials AcquireCredentialsHandle(string package, boo } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Windows.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Windows.cs index fe56d8ed91..2ce87ac951 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NegotiateStreamPal.Windows.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Globalization; using System.ComponentModel; using Microsoft.Data; @@ -215,3 +217,5 @@ internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buff } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.Windows.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.Windows.cs index f229b6845a..e28cc18296 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.Windows.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics.Tracing; using System.Net.Security; @@ -88,3 +90,5 @@ public void SecurityContextInputBuffers(string context, int inputBuffersSize, in } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.cs similarity index 88% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.cs index b003ce8b7e..e785fe016d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/NetEventSource.Security.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/NetEventSource.Security.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics.Tracing; -using System.Globalization; -using System.Net.Security; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; namespace System.Net { @@ -34,3 +32,5 @@ public void SspiPackageNotFound(string packageName) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBuffer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBuffer.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBuffer.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBuffer.cs index b507449f1e..54c060a6e1 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBuffer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBuffer.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; using System.Security.Authentication.ExtendedProtection; @@ -61,3 +62,5 @@ public SecurityBuffer(ChannelBinding binding) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBufferType.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBufferType.cs similarity index 96% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBufferType.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBufferType.cs index 51174938a1..ca29feac84 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityBufferType.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityBufferType.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + namespace System.Net.Security { // sspi.h @@ -26,3 +28,5 @@ internal enum SecurityBufferType SECBUFFER_READONLY_WITH_CHECKSUM = 0x10000000 } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityContextTokenHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityContextTokenHandle.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityContextTokenHandle.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityContextTokenHandle.cs index 00e5b3ac60..3d146e5bcc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/SecurityContextTokenHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/SecurityContextTokenHandle.cs @@ -2,9 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; +#if !NET8_0_OR_GREATER using System.Threading; +using Microsoft.Win32.SafeHandles; namespace System.Net.Security { @@ -39,3 +40,5 @@ protected override bool ReleaseHandle() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteContext.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteContext.cs similarity index 97% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteContext.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteContext.cs index c3c75790b9..16636afd29 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteContext.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteContext.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics; using System.Runtime.InteropServices; @@ -44,3 +46,5 @@ protected override bool ReleaseHandle() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteNegoContext.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteNegoContext.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteNegoContext.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteNegoContext.cs index b98e9ac80b..53fe8e5ad9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeDeleteNegoContext.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeDeleteNegoContext.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics; using Microsoft.Win32.SafeHandles; @@ -75,3 +77,5 @@ protected override void Dispose(bool disposing) } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeCredentials.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeCredentials.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeCredentials.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeCredentials.cs index 51d6869a8d..254d9d127a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeCredentials.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeCredentials.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; @@ -71,3 +73,5 @@ protected override bool ReleaseHandle() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeNegoCredentials.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeNegoCredentials.cs index 217c787619..19ad2e2451 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/Security/Unix/SafeFreeNegoCredentials.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/Security/Unix/SafeFreeNegoCredentials.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Diagnostics; using Microsoft.Win32.SafeHandles; @@ -84,3 +86,5 @@ protected override bool ReleaseHandle() } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusAdapterPal.Windows.cs similarity index 99% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusAdapterPal.Windows.cs index b7ce1e6b1e..c3b13d549f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusAdapterPal.Windows.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -101,3 +103,5 @@ internal static Interop.SECURITY_STATUS GetInteropFromSecurityStatusPal(Security } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusPal.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusPal.cs similarity index 98% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusPal.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusPal.cs index 54b380e74f..5bbe78bd00 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/Net/SecurityStatusPal.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Net/SecurityStatusPal.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + namespace System.Net { internal readonly struct SecurityStatusPal @@ -71,3 +73,5 @@ internal enum SecurityStatusPalErrorCode ApplicationProtocolMismatch } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/NotImplemented.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/NotImplemented.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/System/NotImplemented.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/NotImplemented.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/System/Threading/Tasks/TaskToApm.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/System/Threading/Tasks/TaskToApm.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/System/Threading/Tasks/TaskToApm.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Common/System/Threading/Tasks/TaskToApm.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Interop.BOOL.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Interop.BOOL.cs deleted file mode 100644 index 9f4dab8935..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/CoreLib/Interop/Windows/Interop.BOOL.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -internal partial class Interop -{ - /// - /// Blittable version of Windows BOOL type. It is convenient in situations where - /// manual marshalling is required, or to avoid overhead of regular bool marshalling. - /// - /// - /// Some Windows APIs return arbitrary integer values although the return type is defined - /// as BOOL. It is best to never compare BOOL to TRUE. Always use bResult != BOOL.FALSE - /// or bResult == BOOL.FALSE . - /// - internal enum BOOL : int - { - FALSE = 0, - TRUE = 1, - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs deleted file mode 100644 index 44ae8a66ee..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -internal static partial class Interop -{ - // Initialization of libssl threading support is done in a static constructor. - // This enables a project simply to include this file, and any usage of any of - // the Ssl functions will trigger initialization of the threading support. - - internal static partial class Ssl - { - static Ssl() - { - SslInitializer.Initialize(); - } - } - - internal static class SslInitializer - { -#if !SYSNETSECURITY_NO_OPENSSL - static SslInitializer() - { - CryptoInitializer.Initialize(); - - //Call ssl specific initializer - Ssl.EnsureLibSslInitialized(); - if (Interop.Crypto.ErrPeekLastError() != 0) - { - // It is going to be wrapped in a type load exception but will have the error information - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } - } -#endif - - internal static void Initialize() - { - // No-op that exists to provide a hook for other static constructors - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetCurrentProcess_IntPtr.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetCurrentProcess_IntPtr.cs deleted file mode 100644 index 406e4b0017..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Interop/Windows/kernel32/Interop.GetCurrentProcess_IntPtr.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.InteropServices; - -internal partial class Interop -{ - internal partial class Kernel32 - { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern IntPtr GetCurrentProcess(); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs b/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs deleted file mode 100644 index df16ee4d23..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Common/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs +++ /dev/null @@ -1,477 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Data.Common; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Data.Common; -using System; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Data.ProviderBase -{ - internal abstract partial class DbConnectionFactory - { - private Dictionary _connectionPoolGroups; - private readonly List _poolsToRelease; - private readonly List _poolGroupsToRelease; - private readonly Timer _pruningTimer; - private const int PruningDueTime = 4 * 60 * 1000; // 4 minutes - private const int PruningPeriod = 30 * 1000; // thirty seconds - - private static int _objectTypeCount; // EventSource counter - internal int ObjectID { get; } = Interlocked.Increment(ref _objectTypeCount); - - // s_pendingOpenNonPooled is an array of tasks used to throttle creation of non-pooled connections to - // a maximum of Environment.ProcessorCount at a time. - private static uint s_pendingOpenNonPooledNext = 0; - private static Task[] s_pendingOpenNonPooled = new Task[Environment.ProcessorCount]; - private static Task s_completedTask; - - - protected DbConnectionFactory() - { - _connectionPoolGroups = new Dictionary(); - _poolsToRelease = new List(); - _poolGroupsToRelease = new List(); - _pruningTimer = CreatePruningTimer(); - } - - - abstract public DbProviderFactory ProviderFactory - { - get; - } - - - public void ClearAllPools() - { - using (TryEventScope.Create(" connectionPoolGroups = _connectionPoolGroups; - foreach (KeyValuePair entry in connectionPoolGroups) - { - DbConnectionPoolGroup poolGroup = entry.Value; - if (null != poolGroup) - { - poolGroup.Clear(); - } - } - } - } - - public void ClearPool(DbConnection connection) - { - ADP.CheckArgumentNull(connection, nameof(connection)); - using (TryEventScope.Create(" {0}", GetObjectId(connection))) - { - DbConnectionPoolGroup poolGroup = GetConnectionPoolGroup(connection); - if (null != poolGroup) - { - poolGroup.Clear(); - } - } - } - - public void ClearPool(DbConnectionPoolKey key) - { - Debug.Assert(key != null, "key cannot be null"); - ADP.CheckArgumentNull(key.ConnectionString, nameof(key) + "." + nameof(key.ConnectionString)); - using (TryEventScope.Create(" connectionString")) - { - Dictionary connectionPoolGroups = _connectionPoolGroups; - if (connectionPoolGroups.TryGetValue(key, out DbConnectionPoolGroup poolGroup)) - { - poolGroup.Clear(); - } - } - } - - internal virtual DbConnectionPoolProviderInfo CreateConnectionPoolProviderInfo(DbConnectionOptions connectionOptions) - { - return null; - } - - - internal DbConnectionInternal CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions) - { - Debug.Assert(null != owningConnection, "null owningConnection?"); - Debug.Assert(null != poolGroup, "null poolGroup?"); - - DbConnectionOptions connectionOptions = poolGroup.ConnectionOptions; - DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = poolGroup.ProviderInfo; - DbConnectionPoolKey poolKey = poolGroup.PoolKey; - - DbConnectionInternal newConnection = CreateConnection(connectionOptions, poolKey, poolGroupProviderInfo, null, owningConnection, userOptions); - if (null != newConnection) - { - SqlClientEventSource.Log.HardConnectRequest(); - newConnection.MakeNonPooledObject(owningConnection); - } - SqlClientEventSource.Log.TryTraceEvent(" {0}, Non-pooled database connection created.", ObjectID); - return newConnection; - } - - internal DbConnectionInternal CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) - { - Debug.Assert(null != pool, "null pool?"); - DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = pool.PoolGroup.ProviderInfo; - - DbConnectionInternal newConnection = CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningObject, userOptions); - if (null != newConnection) - { - SqlClientEventSource.Log.HardConnectRequest(); - newConnection.MakePooledConnection(pool); - } - SqlClientEventSource.Log.TryTraceEvent(" {0}, Pooled database connection created.", ObjectID); - return newConnection; - } - - virtual internal DbConnectionPoolGroupProviderInfo CreateConnectionPoolGroupProviderInfo(DbConnectionOptions connectionOptions) - { - return null; - } - - private Timer CreatePruningTimer() => - ADP.UnsafeCreateTimer( - new TimerCallback(PruneConnectionPoolGroups), - null, - PruningDueTime, - PruningPeriod); - - protected DbConnectionOptions FindConnectionOptions(DbConnectionPoolKey key) - { - Debug.Assert(key != null, "key cannot be null"); - if (!string.IsNullOrEmpty(key.ConnectionString)) - { - DbConnectionPoolGroup connectionPoolGroup; - Dictionary connectionPoolGroups = _connectionPoolGroups; - if (connectionPoolGroups.TryGetValue(key, out connectionPoolGroup)) - { - return connectionPoolGroup.ConnectionOptions; - } - } - return null; - } - - private static Task GetCompletedTask() - { - Debug.Assert(Monitor.IsEntered(s_pendingOpenNonPooled), $"Expected {nameof(s_pendingOpenNonPooled)} lock to be held."); - return s_completedTask ?? (s_completedTask = Task.FromResult(null)); - } - - private DbConnectionPool GetConnectionPool(DbConnection owningObject, DbConnectionPoolGroup connectionPoolGroup) - { - // if poolgroup is disabled, it will be replaced with a new entry - - Debug.Assert(null != owningObject, "null owningObject?"); - Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup?"); - - // It is possible that while the outer connection object has - // been sitting around in a closed and unused state in some long - // running app, the pruner may have come along and remove this - // the pool entry from the master list. If we were to use a - // pool entry in this state, we would create "unmanaged" pools, - // which would be bad. To avoid this problem, we automagically - // re-create the pool entry whenever it's disabled. - - // however, don't rebuild connectionOptions if no pooling is involved - let new connections do that work - if (connectionPoolGroup.IsDisabled && (null != connectionPoolGroup.PoolGroupOptions)) - { - SqlClientEventSource.Log.TryTraceEvent(" {0}, DisabledPoolGroup={1}", ObjectID, connectionPoolGroup?.ObjectID); - - // reusing existing pool option in case user originally used SetConnectionPoolOptions - DbConnectionPoolGroupOptions poolOptions = connectionPoolGroup.PoolGroupOptions; - - // get the string to hash on again - DbConnectionOptions connectionOptions = connectionPoolGroup.ConnectionOptions; - Debug.Assert(null != connectionOptions, "prevent expansion of connectionString"); - - connectionPoolGroup = GetConnectionPoolGroup(connectionPoolGroup.PoolKey, poolOptions, ref connectionOptions); - Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup?"); - SetConnectionPoolGroup(owningObject, connectionPoolGroup); - } - DbConnectionPool connectionPool = connectionPoolGroup.GetConnectionPool(this); - return connectionPool; - } - - internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, ref DbConnectionOptions userConnectionOptions) - { - if (string.IsNullOrEmpty(key.ConnectionString)) - { - return (DbConnectionPoolGroup)null; - } - - DbConnectionPoolGroup connectionPoolGroup; - Dictionary connectionPoolGroups = _connectionPoolGroups; - if (!connectionPoolGroups.TryGetValue(key, out connectionPoolGroup) || (connectionPoolGroup.IsDisabled && (null != connectionPoolGroup.PoolGroupOptions))) - { - // If we can't find an entry for the connection string in - // our collection of pool entries, then we need to create a - // new pool entry and add it to our collection. - - DbConnectionOptions connectionOptions = CreateConnectionOptions(key.ConnectionString, userConnectionOptions); - if (null == connectionOptions) - { - throw ADP.InternalConnectionError(ADP.ConnectionError.ConnectionOptionsMissing); - } - - if (null == userConnectionOptions) - { // we only allow one expansion on the connection string - - userConnectionOptions = connectionOptions; - string expandedConnectionString = connectionOptions.Expand(); - - // if the expanded string is same instance (default implementation), then use the already created options - if ((object)expandedConnectionString != (object)key.ConnectionString) - { - // CONSIDER: caching the original string to reduce future parsing - DbConnectionPoolKey newKey = (DbConnectionPoolKey)((ICloneable)key).Clone(); - newKey.ConnectionString = expandedConnectionString; - return GetConnectionPoolGroup(newKey, null, ref userConnectionOptions); - } - } - - // We don't support connection pooling on Win9x - if (null == poolOptions) - { - if (null != connectionPoolGroup) - { - // reusing existing pool option in case user originally used SetConnectionPoolOptions - poolOptions = connectionPoolGroup.PoolGroupOptions; - } - else - { - // Note: may return null for non-pooled connections - poolOptions = CreateConnectionPoolGroupOptions(connectionOptions); - } - } - - lock (this) - { - connectionPoolGroups = _connectionPoolGroups; - if (!connectionPoolGroups.TryGetValue(key, out connectionPoolGroup)) - { - DbConnectionPoolGroup newConnectionPoolGroup = new DbConnectionPoolGroup(connectionOptions, key, poolOptions); - newConnectionPoolGroup.ProviderInfo = CreateConnectionPoolGroupProviderInfo(connectionOptions); - - // build new dictionary with space for new connection string - Dictionary newConnectionPoolGroups = new Dictionary(1 + connectionPoolGroups.Count); - foreach (KeyValuePair entry in connectionPoolGroups) - { - newConnectionPoolGroups.Add(entry.Key, entry.Value); - } - - // lock prevents race condition with PruneConnectionPoolGroups - newConnectionPoolGroups.Add(key, newConnectionPoolGroup); - SqlClientEventSource.Log.EnterActiveConnectionPoolGroup(); - connectionPoolGroup = newConnectionPoolGroup; - _connectionPoolGroups = newConnectionPoolGroups; - } - else - { - Debug.Assert(!connectionPoolGroup.IsDisabled, "Disabled pool entry discovered"); - } - } - Debug.Assert(null != connectionPoolGroup, "how did we not create a pool entry?"); - Debug.Assert(null != userConnectionOptions, "how did we not have user connection options?"); - } - else if (null == userConnectionOptions) - { - userConnectionOptions = connectionPoolGroup.ConnectionOptions; - } - return connectionPoolGroup; - } - - - private void PruneConnectionPoolGroups(object state) - { - // when debugging this method, expect multiple threads at the same time - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}", ObjectID); - - // First, walk the pool release list and attempt to clear each - // pool, when the pool is finally empty, we dispose of it. If the - // pool isn't empty, it's because there are active connections or - // distributed transactions that need it. - lock (_poolsToRelease) - { - if (0 != _poolsToRelease.Count) - { - DbConnectionPool[] poolsToRelease = _poolsToRelease.ToArray(); - foreach (DbConnectionPool pool in poolsToRelease) - { - if (null != pool) - { - pool.Clear(); - - if (0 == pool.Count) - { - _poolsToRelease.Remove(pool); - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, ReleasePool={1}", ObjectID, pool.ObjectID); - SqlClientEventSource.Log.ExitInactiveConnectionPool(); - } - } - } - } - } - - // Next, walk the pool entry release list and dispose of each - // pool entry when it is finally empty. If the pool entry isn't - // empty, it's because there are active pools that need it. - lock (_poolGroupsToRelease) - { - if (0 != _poolGroupsToRelease.Count) - { - DbConnectionPoolGroup[] poolGroupsToRelease = _poolGroupsToRelease.ToArray(); - foreach (DbConnectionPoolGroup poolGroup in poolGroupsToRelease) - { - if (null != poolGroup) - { - int poolsLeft = poolGroup.Clear(); // may add entries to _poolsToRelease - - if (0 == poolsLeft) - { - _poolGroupsToRelease.Remove(poolGroup); - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, ReleasePoolGroup={1}", ObjectID, poolGroup.ObjectID); - SqlClientEventSource.Log.ExitInactiveConnectionPoolGroup(); - } - } - } - } - } - - // Finally, we walk through the collection of connection pool entries - // and prune each one. This will cause any empty pools to be put - // into the release list. - lock (this) - { - Dictionary connectionPoolGroups = _connectionPoolGroups; - Dictionary newConnectionPoolGroups = new Dictionary(connectionPoolGroups.Count); - - foreach (KeyValuePair entry in connectionPoolGroups) - { - if (null != entry.Value) - { - Debug.Assert(!entry.Value.IsDisabled, "Disabled pool entry discovered"); - - // entries start active and go idle during prune if all pools are gone - // move idle entries from last prune pass to a queue for pending release - // otherwise process entry which may move it from active to idle - if (entry.Value.Prune()) - { - // may add entries to _poolsToRelease - QueuePoolGroupForRelease(entry.Value); - } - else - { - newConnectionPoolGroups.Add(entry.Key, entry.Value); - } - } - } - _connectionPoolGroups = newConnectionPoolGroups; - } - } - - internal void QueuePoolForRelease(DbConnectionPool pool, bool clearing) - { - // Queue the pool up for release -- we'll clear it out and dispose - // of it as the last part of the pruning timer callback so we don't - // do it with the pool entry or the pool collection locked. - Debug.Assert(null != pool, "null pool?"); - - // set the pool to the shutdown state to force all active - // connections to be automatically disposed when they - // are returned to the pool - pool.Shutdown(); - - lock (_poolsToRelease) - { - if (clearing) - { - pool.Clear(); - } - _poolsToRelease.Add(pool); - } - SqlClientEventSource.Log.EnterInactiveConnectionPool(); - SqlClientEventSource.Log.ExitActiveConnectionPool(); - } - - internal void QueuePoolGroupForRelease(DbConnectionPoolGroup poolGroup) - { - Debug.Assert(null != poolGroup, "null poolGroup?"); - SqlClientEventSource.Log.TryTraceEvent(" {0}, poolGroup={1}", ObjectID, poolGroup.ObjectID); - - lock (_poolGroupsToRelease) - { - _poolGroupsToRelease.Add(poolGroup); - } - SqlClientEventSource.Log.EnterInactiveConnectionPoolGroup(); - SqlClientEventSource.Log.ExitActiveConnectionPoolGroup(); - } - - virtual protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) - { - return CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningConnection); - } - - internal DbMetaDataFactory GetMetaDataFactory(DbConnectionPoolGroup connectionPoolGroup, DbConnectionInternal internalConnection) - { - Debug.Assert(connectionPoolGroup != null, "connectionPoolGroup may not be null."); - - // get the matadatafactory from the pool entry. If it does not already have one - // create one and save it on the pool entry - DbMetaDataFactory metaDataFactory = connectionPoolGroup.MetaDataFactory; - - // consider serializing this so we don't construct multiple metadata factories - // if two threads happen to hit this at the same time. One will be GC'd - if (metaDataFactory == null) - { - bool allowCache = false; - metaDataFactory = CreateMetaDataFactory(internalConnection, out allowCache); - if (allowCache) - { - connectionPoolGroup.MetaDataFactory = metaDataFactory; - } - } - return metaDataFactory; - } - - protected virtual DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory) - { - // providers that support GetSchema must override this with a method that creates a meta data - // factory appropriate for them. - cacheMetaDataFactory = false; - throw ADP.NotSupported(); - } - - abstract protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection); - - abstract protected DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous); - - abstract protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions options); - - abstract internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection); - - abstract internal DbConnectionInternal GetInnerConnection(DbConnection connection); - - abstract protected int GetObjectId(DbConnection conne); - - abstract internal void PermissionDemand(DbConnection outerConnection); - - abstract internal void SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup); - - abstract internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to); - - abstract internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from); - - abstract internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to); - - virtual internal void Unload() - { - _pruningTimer.Dispose(); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs index c8591a8c11..8ba17db53d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs @@ -315,7 +315,7 @@ private static extern uint SNIOpenWrapper( [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] private static extern unsafe uint SNISecGenClientContextWrapper( [In] SNIHandle pConn, - [In, Out] byte[] pIn, + [In, Out] byte* pIn, uint cbIn, [In, Out] byte[] pOut, [In] ref uint pcbOut, @@ -471,18 +471,18 @@ internal static unsafe void SNIPacketSetData(SNIPacket packet, byte[] data, int } } - internal static unsafe uint SNISecGenClientContext(SNIHandle pConnectionObject, byte[] inBuff, uint receivedLength, byte[] OutBuff, ref uint sendLength, byte[] serverUserName) + internal static unsafe uint SNISecGenClientContext(SNIHandle pConnectionObject, ReadOnlySpan inBuff, byte[] OutBuff, ref uint sendLength, byte[] serverUserName) { fixed (byte* pin_serverUserName = &serverUserName[0]) + fixed (byte* pInBuff = inBuff) { - bool local_fDone; return SNISecGenClientContextWrapper( pConnectionObject, - inBuff, - receivedLength, + pInBuff, + (uint)inBuff.Length, OutBuff, ref sendLength, - out local_fDone, + out _, pin_serverUserName, (uint)serverUserName.Length, null, @@ -505,10 +505,10 @@ internal static uint SNIWritePacket(SNIHandle pConn, SNIPacket packet, bool sync private static void MarshalConsumerInfo(ConsumerInfo consumerInfo, ref Sni_Consumer_Info native_consumerInfo) { native_consumerInfo.DefaultUserDataLength = consumerInfo.defaultBufferSize; - native_consumerInfo.fnReadComp = null != consumerInfo.readDelegate + native_consumerInfo.fnReadComp = consumerInfo.readDelegate != null ? Marshal.GetFunctionPointerForDelegate(consumerInfo.readDelegate) : IntPtr.Zero; - native_consumerInfo.fnWriteComp = null != consumerInfo.writeDelegate + native_consumerInfo.fnWriteComp = consumerInfo.writeDelegate != null ? Marshal.GetFunctionPointerForDelegate(consumerInfo.writeDelegate) : IntPtr.Zero; native_consumerInfo.ConsumerKey = consumerInfo.key; diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 4059335f07..f956aa8594 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -1,8 +1,7 @@  Microsoft.Data.SqlClient - net7.0;net6.0;netstandard2.0;netstandard2.1 - netstandard2.1 + net8.0;net6.0 Microsoft.Data.SqlClient is not supported on this platform. $(OS) true @@ -10,7 +9,6 @@ false netcoreapp - netstandard Debug;Release; AnyCPU;x64;x86 $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName)\netcore\ @@ -20,604 +18,624 @@ Core $(BaseProduct) true $(NoWarn);IL2026;IL2057;IL2072;IL2075 + + + + + true + $(SigningKeyPath) + $(SigningKeyPath) + + + $(SigningKeyPath) - portable - true + $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFramework)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) - + + + + + - + Microsoft\Data\Common\ActivityCorrelator.cs - + Microsoft\Data\Common\AdapterUtil.cs - + + Microsoft\Data\Common\BitConverterCompatible.cs + + Microsoft\Data\Common\DbConnectionOptions.Common.cs - + Microsoft\Data\Common\DbConnectionPoolKey.cs - + Microsoft\Data\Common\DbConnectionStringCommon.cs - + Microsoft\Data\Common\MultipartIdentifier.cs - + Microsoft\Data\Common\NameValuePair.cs - + Microsoft\Data\DataException.cs - + Microsoft\Data\OperationAbortedException.cs - + + Microsoft\Data\ProviderBase\DbConnectionClosed.cs + + + Microsoft\Data\ProviderBase\DbConnectionFactory.cs + + + Microsoft\Data\ProviderBase\DbConnectionPool.cs + + Microsoft\Data\ProviderBase\DbConnectionPoolAuthenticationContext.cs - + Microsoft\Data\ProviderBase\DbConnectionPoolAuthenticationContextKey.cs - + Microsoft\Data\ProviderBase\DbConnectionPoolGroup.cs - + Microsoft\Data\ProviderBase\DbConnectionPoolGroupProviderInfo.cs - + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs + + Microsoft\Data\ProviderBase\DbConnectionPoolOptions.cs - + Microsoft\Data\ProviderBase\DbConnectionPoolProviderInfo.cs - + Microsoft\Data\ProviderBase\DbMetaDataFactory.cs - + + Common\Microsoft\Data\ProviderBase\DbReferenceCollection.cs + + Microsoft\Data\ProviderBase\FieldNameLookup.cs - + Microsoft\Data\ProviderBase\TimeoutTimer.cs - + Microsoft\Data\Sql\SqlDataSourceEnumerator.cs - + Microsoft\Data\Sql\SqlDataSourceEnumeratorManagedHelper.cs - + Microsoft\Data\Sql\SqlDataSourceEnumeratorUtil.cs - + Microsoft\Data\Sql\SqlNotificationRequest.cs - + + Microsoft\Data\SqlClient\AAsyncCallContext.cs + + Microsoft\Data\SqlClient\ActiveDirectoryAuthenticationProvider.cs - + Microsoft\Data\SqlClient\ActiveDirectoryAuthenticationTimeoutRetryHelper.cs - + + Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs + + + Microsoft\Data\SqlClient\AlwaysEncryptedHelperClasses.cs + + + Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.cs + + Microsoft\Data\SqlClient\ApplicationIntent.cs - + Microsoft\Data\SqlClient\AssemblyRef.cs - + + Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs + + Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs - + Microsoft\Data\SqlClient\DataClassification\SensitivityClassification.cs - + Microsoft\Data\SqlClient\DisposableTemporaryOnStack.cs - + Microsoft\Data\SqlClient\EnclaveDelegate.cs - + + Microsoft\Data\SqlClient\EnclaveDelegate.Crypto.cs + + Microsoft\Data\SqlClient\EnclavePackage.cs - + + Microsoft\Data\SqlClient\EnclaveProviderBase.cs + + + Microsoft\Data\SqlClient\EnclaveSessionCache.cs + + Microsoft\Data\SqlClient\LocalAppContextSwitches.cs - + + Microsoft\Data\SqlClient\NoneAttestationEnclaveProvider.cs + + Microsoft\Data\SqlClient\OnChangedEventHandler.cs - + Microsoft\Data\SqlClient\ParameterPeekAheadValue.cs - + Microsoft\Data\SqlClient\PoolBlockingPeriod.cs - + Microsoft\Data\SqlClient\Reliability\AppConfigManager.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryingEventArgs.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryIntervalBaseEnumerator.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryLogic.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryLogicBase.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryLogicBaseProvider.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryLogicProvider.cs - + Microsoft\Data\SqlClient\Reliability\SqlConfigurableRetryFactory.cs - + Microsoft\Data\SqlClient\Reliability\SqlConfigurableRetryLogicLoader.cs - + Microsoft\Data\SqlClient\Reliability\SqlConfigurableRetryLogicManager.cs - + Microsoft\Data\SqlClient\Reliability\SqlRetryIntervalEnumerators.cs - + Microsoft\Data\SqlClient\RowsCopiedEventArgs.cs - + Microsoft\Data\SqlClient\RowsCopiedEventHandler.cs - - Microsoft\Data\SqlClient\SqlSequentialTextReader.cs - - + Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs - + Microsoft\Data\SqlClient\Server\ITypedGetters.cs - + Microsoft\Data\SqlClient\Server\ITypedGettersV3.cs - + Microsoft\Data\SqlClient\Server\ITypedSetters.cs - + Microsoft\Data\SqlClient\Server\ITypedSettersV3.cs - + Microsoft\Data\SqlClient\Server\MemoryRecordBuffer.cs - + Microsoft\Data\SqlClient\Server\MetadataUtilsSmi.cs - + Microsoft\Data\SqlClient\Server\SmiEventSink.cs - + Microsoft\Data\SqlClient\Server\SmiEventSink_Default.Common.cs - + Microsoft\Data\SqlClient\Server\SmiGettersStream.cs - + Microsoft\Data\SqlClient\Server\SmiMetaData.cs - + Microsoft\Data\SqlClient\Server\SmiMetaDataProperty.cs - + Microsoft\Data\SqlClient\Server\SmiRecordBuffer.cs - + Microsoft\Data\SqlClient\Server\SmiSettersStream.cs - + Microsoft\Data\SqlClient\Server\SmiTypedGetterSetter.cs - + Microsoft\Data\SqlClient\Server\SmiXetterAccessMap.Common.cs - + Microsoft\Data\SqlClient\Server\SmiXetterTypeCode.cs - + Microsoft\Data\SqlClient\Server\SqlDataRecord.cs - + Microsoft\Data\SqlClient\Server\SqlDataRecord.netcore.cs - + Microsoft\Data\SqlClient\Server\SqlMetaData.cs - + Microsoft\Data\SqlClient\Server\SqlNormalizer.cs - + Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs - - Microsoft\Data\SqlClient\SqlTransaction.Common.cs + + Microsoft\Data\SqlClient\Server\SqlSer.cs - + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs - + Microsoft\Data\SqlClient\SignatureVerificationCache.cs - + Microsoft\Data\SqlClient\SortOrder.cs - + Microsoft\Data\SqlClient\SqlAeadAes256CbcHmac256Algorithm.cs - + Microsoft\Data\SqlClient\SqlAeadAes256CbcHmac256EncryptionKey.cs - + Microsoft\Data\SqlClient\SqlAeadAes256CbcHmac256Factory.cs - + Microsoft\Data\SqlClient\SqlAuthenticationParameters.cs - + Microsoft\Data\SqlClient\SqlAuthenticationProvider.cs - - Microsoft\Data\SqlClient\SqlBuffer.cs + + Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.cs - + Microsoft\Data\SqlClient\SqlAuthenticationToken.cs - + + Microsoft\Data\SqlClient\SqlBatch.cs + + + Microsoft\Data\SqlClient\SqlBatchCommand.cs + + + Microsoft\Data\SqlClient\SqlBatchCommand.Net8OrGreater.cs + + + Microsoft\Data\SqlClient\SqlBatchCommandCollection.cs + + + Microsoft\Data\SqlClient\SqlBuffer.cs + + Microsoft\Data\SqlClient\SqlBulkCopyColumnMapping.cs - + Microsoft\Data\SqlClient\SqlBulkCopyColumnMappingCollection.cs - + Microsoft\Data\SqlClient\SqlBulkCopyColumnOrderHint.cs - + Microsoft\Data\SqlClient\SqlBulkCopyColumnOrderHintCollection.cs - + Microsoft\Data\SqlClient\SqlBulkCopyOptions.cs - + Microsoft\Data\SqlClient\SqlCachedBuffer.cs - + Microsoft\Data\SqlClient\SqlClientEncryptionAlgorithm.cs - + Microsoft\Data\SqlClient\SqlClientEncryptionAlgorithmFactory.cs - + Microsoft\Data\SqlClient\SqlClientEncryptionAlgorithmFactoryList.cs - + Microsoft\Data\SqlClient\SqlClientEncryptionType.cs - + Microsoft\Data\SqlClient\SqlClientEventSource.cs - + + Microsoft\Data\SqlClient\SqlClientFactory.cs + + Microsoft\Data\SqlClient\SqlClientLogger.cs - + Microsoft\Data\SqlClient\SqlClientMetaDataCollectionNames.cs - + Microsoft\Data\SqlClient\SqlClientSymmetricKey.cs - + Microsoft\Data\SqlClient\SqlCollation.cs - - Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs - + Microsoft\Data\SqlClient\SqlCommandBuilder.cs - + + Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlCommandSet.cs - + Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs - + Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs - + Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs - + Microsoft\Data\SqlClient\SqlConnectionPoolKey.cs - + Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs - + Microsoft\Data\SqlClient\SqlConnectionString.cs - + Microsoft\Data\SqlClient\SqlConnectionStringBuilder.cs - + Microsoft\Data\SqlClient\SqlConnectionTimeoutErrorInternal.cs - + Microsoft\Data\SqlClient\SqlCredential.cs - + Microsoft\Data\SqlClient\SqlDataAdapter.cs - + Microsoft\Data\SqlClient\SqlDependency.cs - + Microsoft\Data\SqlClient\SqlDependencyListener.cs - + Microsoft\Data\SqlClient\SqlDependencyUtils.cs - + Microsoft\Data\SqlClient\SqlDependencyUtils.AppDomain.cs - + + Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs + + + Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs + + Microsoft\Data\SqlClient\SqlEnclaveSession.cs - + Microsoft\Data\SqlClient\SqlEnums.cs - + Microsoft\Data\SqlClient\SqlEnvChange.cs - + Microsoft\Data\SqlClient\SqlError.cs - + Microsoft\Data\SqlClient\SqlErrorCollection.cs - + Microsoft\Data\SqlClient\SqlException.cs - + Microsoft\Data\SqlClient\SQLFallbackDNSCache.cs - + Microsoft\Data\SqlClient\SqlInfoMessageEvent.cs - + Microsoft\Data\SqlClient\SqlInfoMessageEventHandler.cs - + Microsoft\Data\SqlClient\SqlInternalConnection.cs - + Microsoft\Data\SqlClient\SqlInternalTransaction.cs - + Microsoft\Data\SqlClient\SqlMetadataFactory.cs - + Microsoft\Data\SqlClient\SqlNotificationEventArgs.cs - + Microsoft\Data\SqlClient\SqlNotificationInfo.cs - + Microsoft\Data\SqlClient\SqlNotificationSource.cs - + Microsoft\Data\SqlClient\SqlNotificationType.cs - + Microsoft\Data\SqlClient\SqlObjectPool.cs - + Microsoft\Data\SqlClient\SqlParameter.cs - + Microsoft\Data\SqlClient\SqlParameterCollection.cs - + Microsoft\Data\SqlClient\SqlQueryMetadataCache.cs - + Microsoft\Data\SqlClient\SqlReferenceCollection.cs - + Microsoft\Data\SqlClient\SqlRowUpdatedEvent.cs - + Microsoft\Data\SqlClient\SqlRowUpdatedEventHandler.cs - + Microsoft\Data\SqlClient\SqlRowUpdatingEvent.cs - + Microsoft\Data\SqlClient\SqlRowUpdatingEventHandler.cs - + Microsoft\Data\SqlClient\SqlSecurityUtility.cs - + Microsoft\Data\SqlClient\SqlSequentialStream.cs - - Microsoft\Data\SqlClient\Server\SqlSer.cs + + Microsoft\Data\SqlClient\SqlSequentialTextReader.cs - + Microsoft\Data\SqlClient\SqlStatistics.cs - + + Microsoft\Data\SqlClient\SqlStream.cs + + Microsoft\Data\SqlClient\SqlSymmetricKeyCache.cs - + Microsoft\Data\SqlClient\SqlUdtInfo.cs - + Microsoft\Data\SqlClient\SqlUtil.cs - + + Microsoft\Data\SqlClient\SqlTransaction.Common.cs + + + Microsoft\Data\SqlClient\SSPI\ManagedSSPIContextProvider.cs + + + Microsoft\Data\SqlClient\SSPI\NegotiateSSPIContextProvider.cs + + + Microsoft\Data\SqlClient\SSPI\SSPIContextProvider.cs + + Microsoft\Data\SqlClient\TdsEnums.cs - + Microsoft\Data\SqlClient\TdsParameterSetter.cs - + + Microsoft\Data\SqlClient\TdsParser.cs + + + Microsoft\Data\SqlClient\TdsParserHelperClasses.cs + + Microsoft\Data\SqlClient\TdsParserStateObject.cs - + Microsoft\Data\SqlClient\TdsParserStaticMethods.cs - + Microsoft\Data\SqlClient\TdsRecordBufferSetter.cs - + Microsoft\Data\SqlClient\TdsParserSessionPool.cs - + Microsoft\Data\SqlClient\TdsValueSetter.cs - + + Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs + + + Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs + + Microsoft\Data\SQLTypes\SQLResource.cs - + Microsoft\Data\SqlTypes\SqlTypeWorkarounds.cs - - Microsoft\Data\SqlClient\SqlStream.cs + + Microsoft\Data\SqlTypes\SqlJson.cs - + Resources\ResCategoryAttribute.cs - + Resources\ResDescriptionAttribute.cs - + Common\System\Diagnostics\CodeAnalysis.cs - - - - - - - Microsoft\Data\SqlClient\EnclaveDelegate.NotSupported.cs - - - Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NotSupported.cs - - - - - - - - - - - - Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs - - - Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs - - - Microsoft\Data\SqlClient\EnclaveDelegate.Crypto.cs - - - Microsoft\Data\SqlClient\EnclaveProviderBase.cs - - - Microsoft\Data\SqlClient\EnclaveSessionCache.cs - - - Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs - - - Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs - - - Microsoft\Data\SqlClient\NoneAttestationEnclaveProvider.cs - - - Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs - - - - - - - - - - - - - Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs - - - - - - - Resources\StringsHelper.cs - - - Resources\Strings.Designer.cs - True - True - Strings.resx - - - Resources\Strings.resx - Microsoft.Data.SqlClient.Resources.Strings.resources - ResXFileCodeGenerator - Strings.Designer.cs - System - - - Resources\%(RecursiveDir)%(Filename)%(Extension) - - - - - Common\CoreLib\System\Threading\Tasks\TaskToApm.cs - - - Common\Microsoft\Data\ProviderBase\DbConnectionClosed.cs - - - Common\Microsoft\Data\ProviderBase\DbConnectionFactory.cs - - - Common\Microsoft\Data\ProviderBase\DbConnectionInternal.cs - - - Common\Microsoft\Data\ProviderBase\DbReferenceCollection.cs - - + + Microsoft\Data\SqlDbTypeExtensions.cs + + + + + + + + + + + + + + + - - - - - - + @@ -627,16 +645,18 @@ + - + + - + - - + + @@ -644,351 +664,213 @@ + - + - - - - + + - - Microsoft\Data\Common\AdapterUtil.Windows.cs - - - Microsoft\Data\Sql\SqlDataSourceEnumeratorNativeHelper.cs - - - Microsoft\Data\Sql\SqlDataSourceEnumerator.Windows.cs - - - - - - Microsoft\Data\SqlClient\TdsParserSafeHandles.Windows.cs - - - - - - Microsoft\Data\Common\AdapterUtil.Unix.cs - - - - - - - - - - - - - Common\CoreLib\Interop\Windows\kernel32\Interop.FileTypes.cs - - - Common\CoreLib\Interop\Windows\kernel32\Interop.GetFileType_SafeHandle.cs - - - Common\CoreLib\Interop\Windows\kernel32\Interop.SetThreadErrorMode.cs + + Common\Interop\Windows\Kernel32\Interop.GetFileType_SafeHandle.cs - - Common\CoreLib\System\IO\PathInternal.Windows.cs - - + Common\Interop\Windows\Interop.Errors.cs - + + Common\Interop\Windows\Interop.Libraries.cs + + Common\Interop\Windows\Interop.UNICODE_STRING.cs - + Common\Interop\Windows\Kernel32\Interop.CTL_CODE.cs - + Common\Interop\Windows\Kernel32\Interop.DeviceIoControl.cs - + + Common\Interop\Windows\Kernel32\Interop.FileTypes.cs + + Common\Interop\Windows\Kernel32\Interop.IoControlCodeAccess.cs - + Common\Interop\Windows\Kernel32\Interop.IoControlTransferType.cs - + + Common\Interop\Windows\Kernel32\Interop.SetThreadErrorMode.cs + + Common\Interop\Windows\NtDll\Interop.FILE_FULL_EA_INFORMATION.cs - + Common\Interop\Windows\NtDll\Interop.IO_STATUS_BLOCK.cs - + Common\Interop\Windows\NtDll\Interop.NtCreateFile.cs - + Common\Interop\Windows\NtDll\Interop.RtlNtStatusToDosError.cs - - - - - - - - - - - - - - - - - - - - - - Common\Interop\Windows\kernel32\Interop.LoadLibraryEx.cs + + Microsoft\Data\Common\AdapterUtil.Windows.cs - - - - - - - - - - Common\CoreLib\Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Windows.cs - - Common\Interop\Windows\kernel32\Interop.FreeLibrary.cs + + Microsoft\Data\Sql\SqlDataSourceEnumeratorNativeHelper.cs - - Common\Interop\Windows\kernel32\Interop.GetProcAddress.cs + + Microsoft\Data\Sql\SqlDataSourceEnumerator.Windows.cs - - - - - - Common\Interop\Windows\Interop.Libraries.cs + + Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.Windows.cs - - - - - Common\System\Net\InternalException.cs + + Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.Windows.cs - - Common\System\Net\Logging\NetEventSource.Common.cs + + Microsoft\Data\SqlClient\SSPI\NativeSSPIContextProvider.cs + + Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.Windows.cs + + + Microsoft\Data\SqlClient\TdsParserSafeHandles.Windows.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + Microsoft\Data\Common\AdapterUtil.Unix.cs + + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Unix.cs + + + + + + + + + + + + + - + - + + + + + - - - - Common\CoreLib\Interop\Windows\Kernel32\Interop.CloseHandle.cs - - - Common\Interop\Windows\Crypt32\Interop.certificates.cs - - - Common\Interop\Windows\Crypt32\Interop.certificates_types.cs - - - Common\Interop\Windows\SChannel\Interop.SecPkgContext_ApplicationProtocol.cs - - - Common\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs - - - Common\Interop\Windows\SChannel\SecPkgContext_ConnectionInfo.cs - - - Common\System\Collections\Generic\BidirectionalDictionary.cs - - - Common\System\Net\ContextFlagsAdapterPal.Windows.cs - - - Common\System\Net\DebugCriticalHandleZeroOrMinusOneIsInvalid.cs - - - Common\System\Net\Security\SecurityContextTokenHandle.cs - - - Common\System\Net\SecurityStatusAdapterPal.Windows.cs - - - Common\System\Net\Security\NegotiateStreamPal.Windows.cs - - - Common\System\Net\Security\NetEventSource.Security.cs - - - Common\System\Net\Security\NetEventSource.Security.Windows.cs - - - Common\Interop\Windows\sspicli\GlobalSSPI.cs - - - Common\Interop\Windows\sspicli\Interop.SSPI.cs - - - Common\Interop\Windows\sspicli\NegotiationInfoClass.cs - - - Common\Interop\Windows\sspicli\SafeDeleteContext.cs - - - Common\Interop\Windows\sspicli\SecPkgContext_Bindings.cs - - - Common\Interop\Windows\sspicli\SecPkgContext_NegotiationInfoW.cs - - - Common\Interop\Windows\sspicli\SecPkgContext_Sizes.cs - - - Common\Interop\Windows\sspicli\SecPkgContext_StreamSizes.cs - - - Common\Interop\Windows\sspicli\SecurityPackageInfo.cs - - - Common\Interop\Windows\sspicli\SecurityPackageInfoClass.cs - - - Common\Interop\Windows\sspicli\SecuritySafeHandles.cs - - - Common\Interop\Windows\sspicli\SSPIAuthType.cs - - - Common\Interop\Windows\sspicli\SSPIInterface.cs - - - Common\Interop\Windows\sspicli\SSPISecureChannelType.cs - - - Common\Interop\Windows\sspicli\SSPIWrapper.cs - - - - - - Common\System\Net\ContextFlagsPal.cs - - - Common\System\Net\DebugCriticalHandleMinusOneIsInvalid.cs - - - Common\System\Net\DebugSafeHandle.cs - - - Common\System\Net\Logging\DebugThreadTracking.cs - - - Common\System\Net\NegotiationInfoClass.cs - - - Common\System\Net\Security\SecurityBuffer.cs - - - Common\System\Net\Security\SecurityBufferType.cs - - - Common\System\Net\SecurityStatusPal.cs - - - - - - - Common\Interop\Unix\Interop.Libraries.cs - - - Common\Interop\Unix\System.Net.Security.Native\Interop.GssApiException.cs - - - Common\Interop\Unix\System.Net.Security.Native\Interop.GssBuffer.cs - - - Common\Interop\Unix\System.Net.Security.Native\Interop.NetSecurityNative.cs - - - Common\Microsoft\Win32\SafeHandles\GssSafeHandles.cs - - - Common\System\Net\Security\Unix\SafeDeleteContext.cs - - - Common\System\Net\Security\Unix\SafeDeleteNegoContext.cs - - - Common\System\Net\Security\Unix\SafeFreeCredentials.cs - - - Common\System\Net\Security\Unix\SafeFreeNegoCredentials.cs - - - Common\System\Net\ContextFlagsAdapterPal.Unix.cs + + + + + Resources\StringsHelper.cs - - Common\System\Net\Security\NegotiateStreamPal.Unix.cs + + Resources\Strings.Designer.cs + True + True + Strings.resx - - - - - - + + Resources\Strings.resx + Microsoft.Data.SqlClient.Resources.Strings.resources + ResXFileCodeGenerator + Strings.Designer.cs + System + + + Resources\%(RecursiveDir)%(Filename)%(Extension) + Microsoft.Data.SqlClient.Resources.%(Filename).resources + Microsoft.Data.SqlClient.SqlMetaData.xml - - + + + - - - - + + + - - - - - - - - + diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs index 35440e9e11..759696d471 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs @@ -15,7 +15,7 @@ internal string ExpandAttachDbFileName(string replacementValue) int copyPosition = 0; StringBuilder builder = new(_usersConnectionString.Length); - for (NameValuePair current = _keyChain; null != current; current = current.Next) + for (NameValuePair current = _keyChain; current != null; current = current.Next) { if (string.Equals(current.Name, DbConnectionStringKeywords.AttachDBFilename, StringComparison.InvariantCultureIgnoreCase)) { @@ -38,12 +38,12 @@ internal string ExpandAttachDbFileName(string replacementValue) internal static string ExpandDataDirectory(string keyword, string value) { string fullPath = null; - if ((null != value) && value.StartsWith(DataDirectory, StringComparison.OrdinalIgnoreCase)) + if (value != null && value.StartsWith(DataDirectory, StringComparison.OrdinalIgnoreCase)) { // find the replacement path object rootFolderObject = AppDomain.CurrentDomain.GetData("DataDirectory"); var rootFolderPath = (rootFolderObject as string); - if ((null != rootFolderObject) && (null == rootFolderPath)) + if (rootFolderObject != null && rootFolderPath == null) { throw ADP.InvalidDataDirectory(); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs deleted file mode 100644 index 89663d2f90..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Transactions; -using Microsoft.Data.Common; - -namespace Microsoft.Data.ProviderBase -{ - internal abstract partial class DbConnectionClosed : DbConnectionInternal - { - protected override void Activate(Transaction transaction) => throw ADP.ClosedConnectionError(); - - public override void EnlistTransaction(Transaction transaction) => throw ADP.ClosedConnectionError(); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs deleted file mode 100644 index 1a2e809147..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs +++ /dev/null @@ -1,220 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Data; -using System.Data.Common; -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using System.Transactions; -using Microsoft.Data.Common; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Data.ProviderBase -{ - internal abstract partial class DbConnectionFactory - { - private static readonly Action, object> s_tryGetConnectionCompletedContinuation = TryGetConnectionCompletedContinuation; - - internal bool TryGetConnection(DbConnection owningConnection, TaskCompletionSource retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, out DbConnectionInternal connection) - { - Debug.Assert(null != owningConnection, "null owningConnection?"); - - DbConnectionPoolGroup poolGroup; - DbConnectionPool connectionPool; - connection = null; - - // Work around race condition with clearing the pool between GetConnectionPool obtaining pool - // and GetConnection on the pool checking the pool state. Clearing the pool in this window - // will switch the pool into the ShuttingDown state, and GetConnection will return null. - // There is probably a better solution involving locking the pool/group, but that entails a major - // re-design of the connection pooling synchronization, so is postponed for now. - - // Use retriesLeft to prevent CPU spikes with incremental sleep - // start with one msec, double the time every retry - // max time is: 1 + 2 + 4 + ... + 2^(retries-1) == 2^retries -1 == 1023ms (for 10 retries) - int retriesLeft = 10; - int timeBetweenRetriesMilliseconds = 1; - - do - { - poolGroup = GetConnectionPoolGroup(owningConnection); - // Doing this on the callers thread is important because it looks up the WindowsIdentity from the thread. - connectionPool = GetConnectionPool(owningConnection, poolGroup); - if (null == connectionPool) - { - // If GetConnectionPool returns null, we can be certain that - // this connection should not be pooled via DbConnectionPool - // or have a disabled pool entry. - poolGroup = GetConnectionPoolGroup(owningConnection); // previous entry have been disabled - - if (retry != null) - { - Task newTask; - CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - lock (s_pendingOpenNonPooled) - { - // look for an available task slot (completed or empty) - int idx; - for (idx = 0; idx < s_pendingOpenNonPooled.Length; idx++) - { - Task task = s_pendingOpenNonPooled[idx]; - if (task == null) - { - s_pendingOpenNonPooled[idx] = GetCompletedTask(); - break; - } - else if (task.IsCompleted) - { - break; - } - } - - // if didn't find one, pick the next one in round-robin fashion - if (idx == s_pendingOpenNonPooled.Length) - { - idx = (int)(s_pendingOpenNonPooledNext % s_pendingOpenNonPooled.Length); - unchecked - { - s_pendingOpenNonPooledNext++; - } - } - - // now that we have an antecedent task, schedule our work when it is completed. - // If it is a new slot or a completed task, this continuation will start right away. - newTask = CreateReplaceConnectionContinuation(s_pendingOpenNonPooled[idx], owningConnection, retry, userOptions, oldConnection, poolGroup, cancellationTokenSource); - - // Place this new task in the slot so any future work will be queued behind it - s_pendingOpenNonPooled[idx] = newTask; - } - - // Set up the timeout (if needed) - if (owningConnection.ConnectionTimeout > 0) - { - int connectionTimeoutMilliseconds = owningConnection.ConnectionTimeout * 1000; - cancellationTokenSource.CancelAfter(connectionTimeoutMilliseconds); - } - - // once the task is done, propagate the final results to the original caller - newTask.ContinueWith( - continuationAction: s_tryGetConnectionCompletedContinuation, - state: Tuple.Create(cancellationTokenSource, retry), - scheduler: TaskScheduler.Default - ); - - return false; - } - - connection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); - SqlClientEventSource.Log.EnterNonPooledConnection(); - } - else - { - if (((SqlClient.SqlConnection)owningConnection).ForceNewConnection) - { - Debug.Assert(!(oldConnection is DbConnectionClosed), "Force new connection, but there is no old connection"); - connection = connectionPool.ReplaceConnection(owningConnection, userOptions, oldConnection); - } - else - { - if (!connectionPool.TryGetConnection(owningConnection, retry, userOptions, out connection)) - { - return false; - } - } - - if (connection == null) - { - // connection creation failed on semaphore waiting or if max pool reached - if (connectionPool.IsRunning) - { - SqlClientEventSource.Log.TryTraceEvent(" {0}, GetConnection failed because a pool timeout occurred.", ObjectID); - // If GetConnection failed while the pool is running, the pool timeout occurred. - throw ADP.PooledOpenTimeout(); - } - else - { - // We've hit the race condition, where the pool was shut down after we got it from the group. - // Yield time slice to allow shut down activities to complete and a new, running pool to be instantiated - // before retrying. - System.Threading.Thread.Sleep(timeBetweenRetriesMilliseconds); - timeBetweenRetriesMilliseconds *= 2; // double the wait time for next iteration - } - } - } - } while (connection == null && retriesLeft-- > 0); - - if (connection == null) - { - SqlClientEventSource.Log.TryTraceEvent(" {0}, GetConnection failed because a pool timeout occurred and all retries were exhausted.", ObjectID); - // exhausted all retries or timed out - give up - throw ADP.PooledOpenTimeout(); - } - - return true; - } - - private Task CreateReplaceConnectionContinuation(Task task, DbConnection owningConnection, TaskCompletionSource retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionPoolGroup poolGroup, CancellationTokenSource cancellationTokenSource) - { - return task.ContinueWith( - (_) => - { - Transaction originalTransaction = ADP.GetCurrentTransaction(); - try - { - ADP.SetCurrentTransaction(retry.Task.AsyncState as Transaction); - var newConnection = CreateNonPooledConnection(owningConnection, poolGroup, userOptions); - if ((oldConnection != null) && (oldConnection.State == ConnectionState.Open)) - { - oldConnection.PrepareForReplaceConnection(); - oldConnection.Dispose(); - } - return newConnection; - } - finally - { - ADP.SetCurrentTransaction(originalTransaction); - } - }, - cancellationTokenSource.Token, - TaskContinuationOptions.LongRunning, - TaskScheduler.Default - ); - } - - private static void TryGetConnectionCompletedContinuation(Task task, object state) - { - Tuple> parameters = (Tuple>)state; - CancellationTokenSource source = parameters.Item1; - source.Dispose(); - - TaskCompletionSource retryCompletionSource = parameters.Item2; - - if (task.IsCanceled) - { - retryCompletionSource.TrySetException(ADP.ExceptionWithStackTrace(ADP.NonPooledOpenTimeout())); - } - else if (task.IsFaulted) - { - retryCompletionSource.TrySetException(task.Exception.InnerException); - } - else - { - if (!retryCompletionSource.TrySetResult(task.Result)) - { - // The outer TaskCompletionSource was already completed - // Which means that we don't know if someone has messed with the outer connection in the middle of creation - // So the best thing to do now is to destroy the newly created connection - task.Result.DoomThisConnection(); - task.Result.Dispose(); - } - else - { - SqlClientEventSource.Log.EnterNonPooledConnection(); - } - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs index 8fc8df24e0..6458d11f48 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs @@ -16,6 +16,7 @@ internal abstract partial class DbConnectionInternal { private static int _objectTypeCount; internal readonly int _objectID = Interlocked.Increment(ref _objectTypeCount); + private TransactionCompletedEventHandler _transactionCompletedEventHandler = null; private bool _isInStasis; @@ -36,8 +37,8 @@ protected internal Transaction EnlistedTransaction set { Transaction currentEnlistedTransaction = _enlistedTransaction; - if (((null == currentEnlistedTransaction) && (null != value)) - || ((null != currentEnlistedTransaction) && !currentEnlistedTransaction.Equals(value))) + if ((currentEnlistedTransaction == null && value != null) + || (currentEnlistedTransaction != null && !currentEnlistedTransaction.Equals(value))) { // WebData 20000024 // Pay attention to the order here: @@ -52,7 +53,7 @@ protected internal Transaction EnlistedTransaction Transaction previousTransactionClone = null; try { - if (null != value) + if (value != null) { valueClone = value.Clone(); } @@ -87,12 +88,12 @@ protected internal Transaction EnlistedTransaction // we really need to dispose our clones; they may have // native resources and GC may not happen soon enough. // VSDevDiv 479564: don't dispose if still holding reference in _enlistedTransaction - if (null != previousTransactionClone && + if (previousTransactionClone != null && !object.ReferenceEquals(previousTransactionClone, _enlistedTransaction)) { previousTransactionClone.Dispose(); } - if (null != valueClone && !object.ReferenceEquals(valueClone, _enlistedTransaction)) + if (valueClone != null && !object.ReferenceEquals(valueClone, _enlistedTransaction)) { valueClone.Dispose(); } @@ -103,7 +104,7 @@ protected internal Transaction EnlistedTransaction // against multiple concurrent calls to enlist, which really // isn't supported anyway. - if (null != value) + if (value != null) { SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Transaction {1}, Enlisting.", ObjectID, value.GetHashCode()); TransactionOutcomeEnlist(value); @@ -250,7 +251,7 @@ internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFac // if the DbConnectionInternal derived class needs to close the connection it should // delegate to the DbConnection if one exists or directly call dispose // DbConnection owningObject = (DbConnection)Owner; - // if (null != owningObject) { + // if (owningObject != null) { // owningObject.Close(); // force the closed state on the outer object. // } // else { @@ -260,8 +261,8 @@ internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFac //////////////////////////////////////////////////////////////// // DON'T MESS WITH THIS CODE UNLESS YOU KNOW WHAT YOU'RE DOING! //////////////////////////////////////////////////////////////// - Debug.Assert(null != owningObject, "null owningObject"); - Debug.Assert(null != connectionFactory, "null connectionFactory"); + Debug.Assert(owningObject != null, "null owningObject"); + Debug.Assert(connectionFactory != null, "null connectionFactory"); SqlClientEventSource.Log.TryPoolerTraceEvent(" {0} Closing.", ObjectID); // if an exception occurs after the state change but before the try block @@ -287,7 +288,7 @@ internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFac // The singleton closed classes won't have owners and // connection pools, and we won't want to put them back // into the pool. - if (null != connectionPool) + if (connectionPool != null) { connectionPool.PutObject(this, owningObject); // PutObject calls Deactivate for us... // NOTE: Before we leave the PutObject call, another @@ -353,13 +354,13 @@ virtual internal void DelegatedTransactionEnded() DbConnectionPool pool = Pool; - if (null == pool) + if (pool == null) { throw ADP.InternalError(ADP.InternalErrorCode.PooledObjectWithoutPool); // pooled connection does not have a pool } pool.PutObjectFromTransactedPool(this); } - else if (-1 == _pooledCount && !_owningObject.TryGetTarget(out DbConnection _)) + else if (-1 == _pooledCount && !_owningObject.TryGetTarget(out _)) { // When _pooledCount is -1 and the owning object no longer exists, // it indicates a closed (or leaked), non-pooled connection so @@ -437,15 +438,19 @@ internal void DetachTransaction(Transaction transaction, bool isExplicitlyReleas // potentially a multi-threaded event, so lock the connection to make sure we don't enlist in a new // transaction between compare and assignment. No need to short circuit outside of lock, since failed comparisons should // be the exception, not the rule. - lock (this) + // locking on anything other than the transaction object would lead to a thread deadlock with sys.Transaction.TransactionCompleted event. + lock (transaction) { // Detach if detach-on-end behavior, or if outer connection was closed - DbConnection owner = (DbConnection)Owner; - if (isExplicitlyReleasing || UnbindOnTransactionCompletion || null == owner) + DbConnection owner = Owner; + if (isExplicitlyReleasing || UnbindOnTransactionCompletion || owner is null) { Transaction currentEnlistedTransaction = _enlistedTransaction; if (currentEnlistedTransaction != null && transaction.Equals(currentEnlistedTransaction)) { + // We need to remove the transaction completed event handler to cease listening for the transaction to end. + currentEnlistedTransaction.TransactionCompleted -= _transactionCompletedEventHandler; + EnlistedTransaction = null; if (IsTxRootWaitingForTxEnd) @@ -463,7 +468,7 @@ internal void CleanupConnectionOnTransactionCompletion(Transaction transaction) DetachTransaction(transaction, false); DbConnectionPool pool = Pool; - if (null != pool) + if (pool != null) { pool.TransactionEnded(transaction, this); } @@ -479,7 +484,8 @@ void TransactionCompletedEvent(object sender, TransactionEventArgs e) private void TransactionOutcomeEnlist(Transaction transaction) { - transaction.TransactionCompleted += new TransactionCompletedEventHandler(TransactionCompletedEvent); + _transactionCompletedEventHandler ??= new TransactionCompletedEventHandler(TransactionCompletedEvent); + transaction.TransactionCompleted += _transactionCompletedEventHandler; } internal void SetInStasis() diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs deleted file mode 100644 index c85d042b2a..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using Microsoft.Data.Common; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Data.ProviderBase -{ - sealed internal partial class DbConnectionPool - { - private bool IsBlockingPeriodEnabled() - { - var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString; - if (poolGroupConnectionOptions == null) - { - return true; - } - var policy = poolGroupConnectionOptions.PoolBlockingPeriod; - - switch (policy) - { - case PoolBlockingPeriod.Auto: - { - return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource); - } - case PoolBlockingPeriod.AlwaysBlock: - { - return true; //Enabled - } - case PoolBlockingPeriod.NeverBlock: - { - return false; //Disabled - } - default: - { - //we should never get into this path. - Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement."); - return true; - } - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.uap.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.uap.cs deleted file mode 100644 index 9ed10f0fcc..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/LocalDBAPI.uap.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Data -{ - internal static partial class LocalDBAPI - { - private static IntPtr LoadProcAddress() => - throw new PlatformNotSupportedException(Strings.LocalDBNotSupported); // No Registry support on UAP - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/LocalDB.uap.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/LocalDB.uap.cs deleted file mode 100644 index e764375802..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/LocalDB.uap.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.SqlClient.SNI -{ - internal class LocalDB - { - internal static string GetLocalDBConnectionString(string localDbInstance) - { - throw new PlatformNotSupportedException(Strings.LocalDBNotSupported); // No Registry support on UAP - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs index b93ba0749c..62d2291993 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Buffers.Binary; using System.Diagnostics; using System.Net; using System.Net.Security; @@ -59,10 +60,11 @@ public void Read(byte[] bytes) { SMID = bytes[0]; flags = bytes[1]; - sessionId = BitConverter.ToUInt16(bytes, 2); - length = BitConverter.ToUInt32(bytes, 4) - SNISMUXHeader.HEADER_LENGTH; - sequenceNumber = BitConverter.ToUInt32(bytes, 8); - highwater = BitConverter.ToUInt32(bytes, 12); + Span span = bytes.AsSpan(); + sessionId = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(2)); + length = BinaryPrimitives.ReadUInt32LittleEndian(span.Slice(4)) - SNISMUXHeader.HEADER_LENGTH; + sequenceNumber = BinaryPrimitives.ReadUInt32LittleEndian(span.Slice(8)); + highwater = BinaryPrimitives.ReadUInt32LittleEndian(span.Slice(12)); } public void Write(Span bytes) @@ -136,221 +138,175 @@ internal class SNICommon internal const int LocalDBBadRuntime = 57; /// - /// We only validate Server name in Certificate to match with "targetServerName". + /// We either validate that the provided 'validationCert' matches the 'serverCert', or we validate that the server name in the 'serverCert' matches 'targetServerName'. /// Certificate validation and chain trust validations are done by SSLStream class [System.Net.Security.SecureChannel.VerifyRemoteCertificate method] /// This method is called as a result of callback for SSL Stream Certificate validation. /// + /// Connection ID/GUID for tracing /// Server that client is expecting to connect to - /// X.509 certificate + /// Optional hostname to use for server certificate validation + /// X.509 certificate from the server + /// Path to an X.509 certificate file from the application to compare with the serverCert /// Policy errors /// True if certificate is valid - internal static bool ValidateSslServerCertificate(string targetServerName, X509Certificate cert, SslPolicyErrors policyErrors) + internal static bool ValidateSslServerCertificate(Guid connectionId, string targetServerName, string hostNameInCertificate, X509Certificate serverCert, string validationCertFileName, SslPolicyErrors policyErrors) { - using (TrySNIEventScope.Create("SNICommon.ValidateSslServerCertificate | SNI | SCOPE | INFO | Entering Scope {0} ")) + using (TrySNIEventScope.Create(nameof(SNICommon))) { if (policyErrors == SslPolicyErrors.None) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "targetServerName {0}, SSL Server certificate not validated as PolicyErrors set to None.", args0: targetServerName); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "Connection Id {0}, targetServerName {1}, SSL Server certificate not validated as PolicyErrors set to None.", args0: connectionId, args1: targetServerName); return true; } - // If we get to this point then there is a ssl policy flag. - StringBuilder messageBuilder = new(); - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)) + string serverNameToValidate; + X509Certificate validationCertificate = null; + if (!string.IsNullOrEmpty(hostNameInCertificate)) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, SslPolicyError {1}, SSL Policy certificate chain has errors.", args0: targetServerName, args1: policyErrors); - - // get the chain status from the certificate - X509Certificate2 cert2 = cert as X509Certificate2; - X509Chain chain = new(); - chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; - StringBuilder chainStatusInformation = new(); - bool chainIsValid = chain.Build(cert2); - Debug.Assert(!chainIsValid, "RemoteCertificateChainError flag is detected, but certificate chain is valid."); - if (!chainIsValid) - { - foreach (X509ChainStatus chainStatus in chain.ChainStatus) - { - chainStatusInformation.Append($"{chainStatus.StatusInformation}, [Status: {chainStatus.Status}]"); - chainStatusInformation.AppendLine(); - } - } - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, SslPolicyError {1}, SSL Policy certificate chain has errors. ChainStatus {2}", args0: targetServerName, args1: policyErrors, args2: chainStatusInformation); - messageBuilder.AppendFormat(Strings.SQL_RemoteCertificateChainErrors, chainStatusInformation); - messageBuilder.AppendLine(); + serverNameToValidate = hostNameInCertificate; } - - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable)) + else { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, SSL Policy invalidated certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNotAvailable); + serverNameToValidate = targetServerName; } - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) + if (!string.IsNullOrEmpty(validationCertFileName)) { -#if NET7_0_OR_GREATER - X509Certificate2 cert2 = cert as X509Certificate2; - if (!cert2.MatchesHostname(targetServerName)) + try { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, Target Server name or HNIC does not match the Subject/SAN in Certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + validationCertificate = new X509Certificate(validationCertFileName); } -#else - // To Do: include certificate SAN (Subject Alternative Name) check. - string certServerName = cert.Subject.Substring(cert.Subject.IndexOf('=') + 1); - - // Verify that target server name matches subject in the certificate - if (targetServerName.Length > certServerName.Length) + catch (Exception e) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, Target Server name is of greater length than Subject in Certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + // if this fails, then fall back to the HostNameInCertificate or TargetServer validation. + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Exception occurred loading specified ServerCertificate: {1}, treating it as if ServerCertificate has not been specified.", args0: connectionId, args1: e.Message); } - else if (targetServerName.Length == certServerName.Length) + } + + if (validationCertificate != null) + { + if (serverCert.GetRawCertData().AsSpan().SequenceEqual(validationCertificate.GetRawCertData().AsSpan())) { - // Both strings have the same length, so targetServerName must be a FQDN - if (!targetServerName.Equals(certServerName, StringComparison.OrdinalIgnoreCase)) - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); - } + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "Connection Id {0}, ServerCertificate matches the certificate provided by the server. Certificate validation passed.", args0: connectionId); + return true; } else { - if (string.Compare(targetServerName, 0, certServerName, 0, targetServerName.Length, StringComparison.OrdinalIgnoreCase) != 0) - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); - } - - // Server name matches cert name for its whole length, so ensure that the - // character following the server name is a '.'. This will avoid - // having server name "ab" match "abc.corp.company.com" - // (Names have different lengths, so the target server can't be a FQDN.) - if (certServerName[targetServerName.Length] != '.') - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); - } + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "Connection Id {0}, ServerCertificate doesn't match the certificate provided by the server. Certificate validation failed.", args0: connectionId); + throw ADP.SSLCertificateAuthenticationException(Strings.SQL_RemoteCertificateDoesNotMatchServerCertificate); } #endif } if (messageBuilder.Length > 0) { - throw ADP.SSLCertificateAuthenticationException(messageBuilder.ToString()); - } - - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, " Remote certificate with subject: {0}, validated successfully.", args0: cert.Subject); - return true; - } - } - - /// - /// We validate the provided certificate provided by the client with the one from the server to see if it matches. - /// Certificate validation and chain trust validations are done by SSLStream class [System.Net.Security.SecureChannel.VerifyRemoteCertificate method] - /// This method is called as a result of callback for SSL Stream Certificate validation. - /// - /// X.509 certificate provided by the client - /// X.509 certificate provided by the server - /// Policy errors - /// True if certificate is valid - internal static bool ValidateSslServerCertificate(X509Certificate clientCert, X509Certificate serverCert, SslPolicyErrors policyErrors) - { - using (TrySNIEventScope.Create("SNICommon.ValidateSslServerCertificate | SNI | SCOPE | INFO | Entering Scope {0} ")) - { - if (policyErrors == SslPolicyErrors.None) - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "serverCert {0}, SSL Server certificate not validated as PolicyErrors set to None.", args0: clientCert.Subject); - return true; - } - - StringBuilder messageBuilder = new(); - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable)) - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "serverCert {0}, SSL Server certificate not validated as PolicyErrors set to RemoteCertificateNotAvailable.", args0: clientCert.Subject); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNotAvailable); - } + // If we get to this point then there is a ssl policy flag. + StringBuilder messageBuilder = new(); + if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable)) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, targetServerName {1}, SSL Server certificate not validated as PolicyErrors set to RemoteCertificateNotAvailable.", args0: connectionId, args1: targetServerName); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNotAvailable); + } - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)) - { - // get the chain status from the server certificate - X509Certificate2 cert2 = serverCert as X509Certificate2; - X509Chain chain = new(); - chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; - StringBuilder chainStatusInformation = new(); - bool chainIsValid = chain.Build(cert2); - Debug.Assert(!chainIsValid, "RemoteCertificateChainError flag is detected, but certificate chain is valid."); - if (!chainIsValid) + if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)) { - foreach (X509ChainStatus chainStatus in chain.ChainStatus) + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, targetServerName {0}, SslPolicyError {1}, SSL Policy certificate chain has errors.", args0: connectionId, args1: targetServerName, args2: policyErrors); + + // get the chain status from the certificate + X509Certificate2 cert2 = serverCert as X509Certificate2; + X509Chain chain = new(); + chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; + StringBuilder chainStatusInformation = new(); + bool chainIsValid = chain.Build(cert2); + Debug.Assert(!chainIsValid, "RemoteCertificateChainError flag is detected, but certificate chain is valid."); + if (!chainIsValid) { - chainStatusInformation.Append($"{chainStatus.StatusInformation}, [Status: {chainStatus.Status}]"); - chainStatusInformation.AppendLine(); + foreach (X509ChainStatus chainStatus in chain.ChainStatus) + { + chainStatusInformation.Append($"{chainStatus.StatusInformation}, [Status: {chainStatus.Status}]"); + chainStatusInformation.AppendLine(); + } } + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, targetServerName {1}, SslPolicyError {2}, SSL Policy certificate chain has errors. ChainStatus {3}", args0: connectionId, args1: targetServerName, args2: policyErrors, args3: chainStatusInformation); + messageBuilder.AppendFormat(Strings.SQL_RemoteCertificateChainErrors, chainStatusInformation); + messageBuilder.AppendLine(); } - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "certificate subject from server is {0}, and does not match with the certificate provided client.", args0: cert2.SubjectName.Name); - messageBuilder.AppendFormat(Strings.SQL_RemoteCertificateChainErrors, chainStatusInformation); - messageBuilder.AppendLine(); - } - - if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) - { -#if NET7_0_OR_GREATER - X509Certificate2 s_cert = serverCert as X509Certificate2; - X509Certificate2 c_cert = clientCert as X509Certificate2; - if (!s_cert.MatchesHostname(c_cert.SubjectName.Name)) + if (policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "certificate from server does not match with the certificate provided client.", args0: s_cert.Subject); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); - } +#if NET8_0_OR_GREATER + X509Certificate2 cert2 = serverCert as X509Certificate2; + if (!cert2.MatchesHostname(serverNameToValidate)) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, serverNameToValidate {1}, Target Server name or HNIC does not match the Subject/SAN in Certificate.", args0: connectionId, args1: serverNameToValidate); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + } #else - // Verify that subject name matches - if (serverCert.Subject != clientCert.Subject) - { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "certificate subject from server is {0}, and does not match with the certificate provided client.", args0: serverCert.Subject); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + // To Do: include certificate SAN (Subject Alternative Name) check. + string certServerName = serverCert.Subject.Substring(serverCert.Subject.IndexOf('=') + 1); + + // Verify that target server name matches subject in the certificate + if (serverNameToValidate.Length > certServerName.Length) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, serverNameToValidate {1}, Target Server name is of greater length than Subject in Certificate.", args0: connectionId, args1: serverNameToValidate); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + } + else if (serverNameToValidate.Length == certServerName.Length) + { + // Both strings have the same length, so serverNameToValidate must be a FQDN + if (!serverNameToValidate.Equals(certServerName, StringComparison.OrdinalIgnoreCase)) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, serverNameToValidate {1}, Target Server name does not match Subject in Certificate.", args0: connectionId, args1: serverNameToValidate); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + } + } + else + { + if (string.Compare(serverNameToValidate, 0, certServerName, 0, serverNameToValidate.Length, StringComparison.OrdinalIgnoreCase) != 0) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, serverNameToValidate {1}, Target Server name does not match Subject in Certificate.", args0: connectionId, args1: serverNameToValidate); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + } + + // Server name matches cert name for its whole length, so ensure that the + // character following the server name is a '.'. This will avoid + // having server name "ab" match "abc.corp.company.com" + // (Names have different lengths, so the target server can't be a FQDN.) + if (certServerName[serverNameToValidate.Length] != '.') + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "Connection Id {0}, serverNameToValidate {1}, Target Server name does not match Subject in Certificate.", args0: connectionId, args1: serverNameToValidate); + messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + } + } +#endif } - if (!serverCert.Equals(clientCert)) + if (messageBuilder.Length > 0) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.ERR, "certificate from server does not match with the certificate provided client.", args0: serverCert.Subject); - messageBuilder.AppendLine(Strings.SQL_RemoteCertificateNameMismatch); + throw ADP.SSLCertificateAuthenticationException(messageBuilder.ToString()); } -#endif - } - - if (messageBuilder.Length > 0) - { - throw ADP.SSLCertificateAuthenticationException(messageBuilder.ToString()); } - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "certificate subject {0}, Client certificate validated successfully.", args0: clientCert.Subject); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "Connection Id {0}, certificate with subject: {1}, validated successfully.", args0: connectionId, args1: serverCert.Subject); return true; } } internal static IPAddress[] GetDnsIpAddresses(string serverName, TimeoutTimer timeout) { - using (TrySNIEventScope.Create(nameof(GetDnsIpAddresses))) + IPAddress[] ipAddresses = GetDnsIpAddresses(serverName); + + // We cannot timeout accurately in sync code above, so throw TimeoutException if we've now exceeded the timeout. + if (timeout.IsExpired) { - int remainingTimeout = timeout.MillisecondsRemainingInt; - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, - "Getting DNS host entries for serverName {0} within {1} milliseconds.", - args0: serverName, - args1: remainingTimeout); - using CancellationTokenSource cts = new CancellationTokenSource(remainingTimeout); - // using this overload to support netstandard - Task task = Dns.GetHostAddressesAsync(serverName); - task.ConfigureAwait(false); - task.Wait(cts.Token); - return task.Result; + throw new TimeoutException(); } + return ipAddresses; } internal static IPAddress[] GetDnsIpAddresses(string serverName) { - using (TrySNIEventScope.Create(nameof(GetDnsIpAddresses))) + using (TrySNIEventScope.Create(nameof(SNICommon))) { SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNICommon), EventType.INFO, "Getting DNS host entries for serverName {0}.", args0: serverName); return Dns.GetHostAddresses(serverName); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs index 354ce3eff5..515686f6a3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs @@ -19,7 +19,6 @@ internal abstract class SNIHandle { protected static readonly SslProtocols s_supportedProtocols = SslProtocols.None; -#if !NETSTANDARD2_0 protected static readonly List s_tdsProtocols = new List(1) { new(TdsEnums.TDS8_Protocol) }; protected static async Task AuthenticateAsClientAsync(SslStream sslStream, string serverNameIndication, X509CertificateCollection certificate, CancellationToken token) @@ -32,15 +31,10 @@ protected static async Task AuthenticateAsClientAsync(SslStream sslStream, strin }; await sslStream.AuthenticateAsClientAsync(sslClientOptions, token); } -#endif protected static void AuthenticateAsClient(SslStream sslStream, string serverNameIndication, X509CertificateCollection certificate) { -#if !NETSTANDARD2_0 AuthenticateAsClientAsync(sslStream, serverNameIndication, certificate, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); -#else - throw new NotSupportedException(Strings.SQL_TDS8_NotSupported_Netstandard2_0); -#endif } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs index 8246ce3d6f..b7f682f6d5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs @@ -94,7 +94,7 @@ public SNIMarsHandle(SNIMarsConnection connection, ushort sessionId, object call /// SMUX header flags private void SendControlPacket(SNISMUXFlags flags) { - using (TrySNIEventScope.Create("SNIMarsHandle.SendControlPacket | SNI | INFO | SCOPE | Entering Scope {0}")) + using (TrySNIEventScope.Create(nameof(SNIMarsHandle))) { SNIPacket packet = RentPacket(headerSize: SNISMUXHeader.HEADER_LENGTH, dataSize: 0); #if DEBUG @@ -195,7 +195,7 @@ public override uint Send(SNIPacket packet) private uint InternalSendAsync(SNIPacket packet) { Debug.Assert(packet.ReservedHeaderSize == SNISMUXHeader.HEADER_LENGTH, "mars handle attempting to send muxed packet without smux reservation in InternalSendAsync"); - using (TrySNIEventScope.Create("SNIMarsHandle.InternalSendAsync | SNI | INFO | SCOPE | Entering Scope {0}")) + using (TrySNIEventScope.Create(nameof(SNIMarsHandle))) { lock (this) { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs index 2c3c2aeaf3..8f8af57f58 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs @@ -24,6 +24,8 @@ internal sealed class SNINpHandle : SNIPhysicalHandle private readonly string _targetServer; private readonly object _sendSync; + private readonly string _hostNameInCertificate; + private readonly string _serverCertificateFilename; private readonly bool _tlsFirst; private Stream _stream; private NamedPipeClientStream _pipeStream; @@ -38,7 +40,7 @@ internal sealed class SNINpHandle : SNIPhysicalHandle private int _bufferSize = TdsEnums.DEFAULT_LOGIN_PACKET_SIZE; private readonly Guid _connectionId = Guid.NewGuid(); - public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, bool tlsFirst) + public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, bool tlsFirst, string hostNameInCertificate, string serverCertificateFilename) { using (TrySNIEventScope.Create(nameof(SNINpHandle))) { @@ -47,6 +49,8 @@ public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, boo _sendSync = new object(); _targetServer = serverName; _tlsFirst = tlsFirst; + _hostNameInCertificate = hostNameInCertificate; + _serverCertificateFilename = serverCertificateFilename; try { _pipeStream = new NamedPipeClientStream( @@ -68,7 +72,7 @@ public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, boo { int timeoutMilliseconds = timeout.MillisecondsRemainingInt; SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, - "Connection Id {0}, Setting server name = {1}, pipe name = {2}. Connecting within the {3} sepecified milliseconds.", + "Connection Id {0}, Setting server name = {1}, pipe name = {2}. Connecting within the {3} specified milliseconds.", args0: _connectionId, args1: serverName, args2: pipeName, @@ -369,14 +373,14 @@ public override void DisableSsl() /// Validate server certificate /// /// Sender object - /// X.509 certificate + /// X.509 certificate /// X.509 chain /// Policy errors /// true if valid - private bool ValidateServerCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors) + private bool ValidateServerCertificate(object sender, X509Certificate serverCertificate, X509Chain chain, SslPolicyErrors policyErrors) { using (TrySNIEventScope.Create(nameof(SNINpHandle))) - { + { if (!_validateCert) { SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Certificate validation not requested.", args0: ConnectionId); @@ -384,8 +388,8 @@ private bool ValidateServerCertificate(object sender, X509Certificate cert, X509 } SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Proceeding to SSL certificate validation.", args0: ConnectionId); - return SNICommon.ValidateSslServerCertificate(_targetServer, cert, policyErrors); - } + return SNICommon.ValidateSslServerCertificate(_connectionId, _targetServer, _hostNameInCertificate, serverCertificate, _serverCertificateFilename, policyErrors); + } } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs index d83682021b..fd542e542f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs @@ -92,7 +92,7 @@ public SNIPacket() public int DataLeft => (_dataLength - _dataOffset); /// - /// Indicates that the packet should be sent out of band bypassing the normal send-recieve lock + /// Indicates that the packet should be sent out of band bypassing the normal send-receive lock /// public bool IsOutOfBand { get; set; } @@ -181,7 +181,7 @@ public void AppendData(byte[] data, int size) } /// - /// Read data from the packet into the buffer at dataOffset for zize and then remove that data from the packet + /// Read data from the packet into the buffer at dataOffset for size and then remove that data from the packet /// /// Buffer /// Data offset to write data at diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs index e249d9182c..6961cd3288 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Buffers; using System.Diagnostics; using System.IO; using System.Net; @@ -25,7 +26,7 @@ internal class SNIProxy private static readonly SNIProxy s_singleton = new SNIProxy(); internal static SNIProxy Instance => s_singleton; -#if !NET7_0_OR_GREATER +#if !NET8_0_OR_GREATER /// /// Generate SSPI context /// @@ -34,7 +35,21 @@ internal class SNIProxy /// Send buffer /// Service Principal Name buffer /// SNI error code - internal static void GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, byte[] receivedBuff, ref byte[] sendBuff, byte[][] serverName) + internal static void GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, ReadOnlyMemory receivedBuff, ref byte[] sendBuff, byte[][] serverName) + { + // TODO: this should use ReadOnlyMemory all the way through + byte[] array = null; + + if (!receivedBuff.IsEmpty) + { + array = new byte[receivedBuff.Length]; + receivedBuff.CopyTo(array); + } + + GenSspiClientContext(sspiClientContextStatus, array, ref sendBuff, serverName); + } + + private static void GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, byte[] receivedBuff, ref byte[] sendBuff, byte[][] serverName) { SafeDeleteContext securityContext = sspiClientContextStatus.SecurityContext; ContextFlagsPal contextFlags = sspiClientContextStatus.ContextFlags; @@ -182,19 +197,19 @@ internal static SNIHandle CreateConnectionHandle( } SNIHandle sniHandle = null; - switch (details._connectionProtocol) + switch (details.ResolvedProtocol) { case DataSource.Protocol.Admin: case DataSource.Protocol.None: // default to using tcp if no protocol is provided case DataSource.Protocol.TCP: sniHandle = CreateTcpHandle(details, timeout, parallel, ipPreference, cachedFQDN, ref pendingDNSInfo, tlsFirst, hostNameInCertificate, serverCertificateFilename); - break; + break; case DataSource.Protocol.NP: - sniHandle = CreateNpHandle(details, timeout, parallel, tlsFirst); + sniHandle = CreateNpHandle(details, timeout, parallel, tlsFirst, hostNameInCertificate, serverCertificateFilename); break; default: - Debug.Fail($"Unexpected connection protocol: {details._connectionProtocol}"); + Debug.Fail($"Unexpected connection protocol: {details.ResolvedProtocol}"); break; } @@ -230,11 +245,11 @@ private static byte[][] GetSqlServerSPNs(DataSource dataSource, string serverSPN } else if (!string.IsNullOrWhiteSpace(dataSource.InstanceName)) { - postfix = dataSource.InstanceName; + postfix = dataSource.ResolvedProtocol == DataSource.Protocol.TCP ? dataSource.ResolvedPort.ToString() : dataSource.InstanceName; } SqlClientEventSource.Log.TryTraceEvent("SNIProxy.GetSqlServerSPN | Info | ServerName {0}, InstanceName {1}, Port {2}, postfix {3}", dataSource?.ServerName, dataSource?.InstanceName, dataSource?.Port, postfix); - return GetSqlServerSPNs(hostName, postfix, dataSource._connectionProtocol); + return GetSqlServerSPNs(hostName, postfix, dataSource.ResolvedProtocol); } private static byte[][] GetSqlServerSPNs(string hostNameOrAddress, string portOrInstanceName, DataSource.Protocol protocol) @@ -312,12 +327,12 @@ private static SNITCPHandle CreateTcpHandle( } int port = -1; - bool isAdminConnection = details._connectionProtocol == DataSource.Protocol.Admin; + bool isAdminConnection = details.ResolvedProtocol == DataSource.Protocol.Admin; if (details.IsSsrpRequired) { try { - port = isAdminConnection ? + details.ResolvedPort = port = isAdminConnection ? SSRP.GetDacPortByInstanceName(hostName, details.InstanceName, timeout, parallel, ipPreference) : SSRP.GetPortByInstanceName(hostName, details.InstanceName, timeout, parallel, ipPreference); } @@ -347,8 +362,10 @@ private static SNITCPHandle CreateTcpHandle( /// Timer expiration /// Should MultiSubnetFailover be used. Only returns an error for named pipes. /// + /// Host name in certificate + /// Used for the path to the Server Certificate /// SNINpHandle - private static SNINpHandle CreateNpHandle(DataSource details, TimeoutTimer timeout, bool parallel, bool tlsFirst) + private static SNINpHandle CreateNpHandle(DataSource details, TimeoutTimer timeout, bool parallel, bool tlsFirst, string hostNameInCertificate, string serverCertificateFilename) { if (parallel) { @@ -356,7 +373,7 @@ private static SNINpHandle CreateNpHandle(DataSource details, TimeoutTimer timeo SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, Strings.SNI_ERROR_49); return null; } - return new SNINpHandle(details.PipeHostName, details.PipeName, timeout, tlsFirst); + return new SNINpHandle(details.PipeHostName, details.PipeName, timeout, tlsFirst, hostNameInCertificate, serverCertificateFilename); } /// @@ -418,11 +435,11 @@ internal class DataSource private const string LocalDbHost_NP = @"np:\\.\pipe\LOCALDB#"; private const string NamedPipeInstanceNameHeader = "mssql$"; private const string DefaultPipeName = "sql\\query"; + private const string InstancePrefix = "MSSQL$"; + private const string PathSeparator = "\\"; internal enum Protocol { TCP, NP, None, Admin }; - internal Protocol _connectionProtocol = Protocol.None; - /// /// Provides the HostName of the server to connect to for TCP protocol. /// This information is also used for finding the SPN of SqlServer @@ -434,6 +451,11 @@ internal enum Protocol { TCP, NP, None, Admin }; /// internal int Port { get; private set; } = -1; + /// + /// The port resolved by SSRP when InstanceName is specified + /// + internal int ResolvedPort { get; set; } = -1; + /// /// Provides the inferred Instance Name from Server Data Source /// @@ -449,6 +471,12 @@ internal enum Protocol { TCP, NP, None, Admin }; /// internal string PipeHostName { get; private set; } + /// + /// Gets or sets the protocol that was resolved from the connection string. If this is + /// , the protocol could not reliably be determined. + /// + internal Protocol ResolvedProtocol { get; private set; } + private string _workingDataSource; private string _dataSourceAfterTrimmingProtocol; @@ -465,16 +493,16 @@ private DataSource(string dataSource) PopulateProtocol(); - _dataSourceAfterTrimmingProtocol = (firstIndexOfColon > -1) && _connectionProtocol != Protocol.None + _dataSourceAfterTrimmingProtocol = (firstIndexOfColon > -1) && ResolvedProtocol != Protocol.None ? _workingDataSource.Substring(firstIndexOfColon + 1).Trim() : _workingDataSource; if (_dataSourceAfterTrimmingProtocol.Contains(Slash)) // Pipe paths only allow back slashes { - if (_connectionProtocol == Protocol.None) + if (ResolvedProtocol == Protocol.None) ReportSNIError(SNIProviders.INVALID_PROV); - else if (_connectionProtocol == Protocol.NP) + else if (ResolvedProtocol == Protocol.NP) ReportSNIError(SNIProviders.NP_PROV); - else if (_connectionProtocol == Protocol.TCP) + else if (ResolvedProtocol == Protocol.TCP) ReportSNIError(SNIProviders.TCP_PROV); } } @@ -485,7 +513,7 @@ private void PopulateProtocol() if (splitByColon.Length <= 1) { - _connectionProtocol = Protocol.None; + ResolvedProtocol = Protocol.None; } else { @@ -493,17 +521,17 @@ private void PopulateProtocol() switch (splitByColon[0].Trim()) { case TdsEnums.TCP: - _connectionProtocol = Protocol.TCP; + ResolvedProtocol = Protocol.TCP; break; case TdsEnums.NP: - _connectionProtocol = Protocol.NP; + ResolvedProtocol = Protocol.NP; break; case TdsEnums.ADMIN: - _connectionProtocol = Protocol.Admin; + ResolvedProtocol = Protocol.Admin; break; default: // None of the supported protocols were found. This may be a IPv6 address - _connectionProtocol = Protocol.None; + ResolvedProtocol = Protocol.None; break; } } @@ -587,7 +615,7 @@ private void InferLocalServerName() // If Server name is empty or localhost, then use "localhost" if (string.IsNullOrEmpty(ServerName) || IsLocalHost(ServerName) || (Environment.MachineName.Equals(ServerName, StringComparison.CurrentCultureIgnoreCase) && - _connectionProtocol == Protocol.Admin)) + ResolvedProtocol == Protocol.Admin)) { // For DAC use "localhost" instead of the server name. ServerName = DefaultHostName; @@ -619,11 +647,11 @@ private bool InferConnectionDetails() } // For Tcp and Only Tcp are parameters allowed. - if (_connectionProtocol == Protocol.None) + if (ResolvedProtocol == Protocol.None) { - _connectionProtocol = Protocol.TCP; + ResolvedProtocol = Protocol.TCP; } - else if (_connectionProtocol != Protocol.TCP) + else if (ResolvedProtocol != Protocol.TCP) { // Parameter has been specified for non-TCP protocol. This is not allowed. ReportSNIError(SNIProviders.INVALID_PROV); @@ -681,14 +709,37 @@ private void ReportSNIError(SNIProviders provider) private bool InferNamedPipesInformation() { // If we have a datasource beginning with a pipe or we have already determined that the protocol is Named Pipe - if (_dataSourceAfterTrimmingProtocol.StartsWith(PipeBeginning, StringComparison.Ordinal) || _connectionProtocol == Protocol.NP) + if (_dataSourceAfterTrimmingProtocol.StartsWith(PipeBeginning, StringComparison.Ordinal) || ResolvedProtocol == Protocol.NP) { - // If the data source is "np:servername" + // If the data source starts with "np:servername" if (!_dataSourceAfterTrimmingProtocol.Contains(PipeBeginning)) { - PipeHostName = ServerName = _dataSourceAfterTrimmingProtocol; + // Assuming that user did not change default NamedPipe name, if the datasource is in the format servername\instance, + // separate servername and instance and prepend instance with MSSQL$ and append default pipe path + // https://learn.microsoft.com/en-us/sql/tools/configuration-manager/named-pipes-properties?view=sql-server-ver16 + if (_dataSourceAfterTrimmingProtocol.Contains(PathSeparator) && ResolvedProtocol == Protocol.NP) + { + string[] tokensByBackSlash = _dataSourceAfterTrimmingProtocol.Split(BackSlashCharacter); + if (tokensByBackSlash.Length == 2) + { + // NamedPipeClientStream object will create the network path using PipeHostName and PipeName + // and can be seen in its _normalizedPipePath variable in the format \\servername\pipe\MSSQL$\sql\query + PipeHostName = ServerName = tokensByBackSlash[0]; + PipeName = $"{InstancePrefix}{tokensByBackSlash[1]}{PathSeparator}{DefaultPipeName}"; + } + else + { + ReportSNIError(SNIProviders.NP_PROV); + return false; + } + } + else + { + PipeHostName = ServerName = _dataSourceAfterTrimmingProtocol; + PipeName = SNINpHandle.DefaultPipePath; + } + InferLocalServerName(); - PipeName = SNINpHandle.DefaultPipePath; return true; } @@ -753,11 +804,11 @@ private bool InferNamedPipesInformation() } // DataSource is something like "\\pipename" - if (_connectionProtocol == Protocol.None) + if (ResolvedProtocol == Protocol.None) { - _connectionProtocol = Protocol.NP; + ResolvedProtocol = Protocol.NP; } - else if (_connectionProtocol != Protocol.NP) + else if (ResolvedProtocol != Protocol.NP) { // In case the path began with a "\\" and protocol was not Named Pipes ReportSNIError(SNIProviders.NP_PROV); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs index d12e91ad62..5632e8ebfe 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs @@ -426,33 +426,16 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout, bool isConnected; try // catching SocketException with SocketErrorCode == WouldBlock to run Socket.Select { - if (isInfiniteTimeout) + socket.Connect(ipAddress, port); + if (!isInfiniteTimeout) { - socket.Connect(ipAddress, port); - } - else - { - if (timeout.IsExpired) - { - return null; - } - // Socket.Connect does not support infinite timeouts, so we use Task to simulate it - Task socketConnectTask = new Task(() => socket.Connect(ipAddress, port)); - socketConnectTask.ConfigureAwait(false); - socketConnectTask.Start(); - int remainingTimeout = timeout.MillisecondsRemainingInt; - if (!socketConnectTask.Wait(remainingTimeout)) - { - throw ADP.TimeoutException($"The socket couldn't connect during the expected {remainingTimeout} remaining time."); - } throw SQL.SocketDidNotThrow(); } isConnected = true; } - catch (AggregateException aggregateException) when (!isInfiniteTimeout - && aggregateException.InnerException is SocketException socketException - && socketException.SocketErrorCode == SocketError.WouldBlock) + catch (SocketException socketException) when (!isInfiniteTimeout && + socketException.SocketErrorCode == SocketError.WouldBlock) { // https://github.com/dotnet/SqlClient/issues/826#issuecomment-736224118 // Socket.Select is used because it supports timeouts, while Socket.Connect does not @@ -509,11 +492,11 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout, return socket; } } - catch (AggregateException aggregateException) when (aggregateException.InnerException is SocketException socketException) + catch (SocketException e) { - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.ERR, "THIS EXCEPTION IS BEING SWALLOWED: {0}", args0: socketException?.Message); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.ERR, "THIS EXCEPTION IS BEING SWALLOWED: {0}", args0: e?.Message); SqlClientEventSource.Log.TryAdvancedTraceEvent( - $"{nameof(SNITCPHandle)}.{nameof(Connect)}{EventType.ERR}THIS EXCEPTION IS BEING SWALLOWED: {socketException}"); + $"{nameof(SNITCPHandle)}.{nameof(Connect)}{EventType.ERR}THIS EXCEPTION IS BEING SWALLOWED: {e}"); } finally { @@ -644,7 +627,6 @@ public override uint EnableSsl(uint options) } else { - // TODO: Resolve whether to send _serverNameIndication or _targetServer. _serverNameIndication currently results in error. Why? _sslStream.AuthenticateAsClient(_targetServer, null, s_supportedProtocols, false); } if (_sslOverTdsStream is not null) @@ -698,33 +680,8 @@ private bool ValidateServerCertificate(object sender, X509Certificate serverCert return true; } - string serverNameToValidate; - if (!string.IsNullOrEmpty(_hostNameInCertificate)) - { - serverNameToValidate = _hostNameInCertificate; - } - else - { - serverNameToValidate = _targetServer; - } - - if (!string.IsNullOrEmpty(_serverCertificateFilename)) - { - X509Certificate clientCertificate = null; - try - { - clientCertificate = new X509Certificate(_serverCertificateFilename); - return SNICommon.ValidateSslServerCertificate(clientCertificate, serverCertificate, policyErrors); - } - catch (Exception e) - { - // if this fails, then fall back to the HostNameInCertificate or TargetServer validation. - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, IOException occurred: {1}", args0: _connectionId, args1: e.Message); - } - } - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Certificate will be validated for Target Server name", args0: _connectionId); - return SNICommon.ValidateSslServerCertificate(serverNameToValidate, serverCertificate, policyErrors); + return SNICommon.ValidateSslServerCertificate(_connectionId, _targetServer, _hostNameInCertificate, serverCertificate, _serverCertificateFilename, policyErrors); } /// @@ -747,7 +704,7 @@ public override uint Send(SNIPacket packet) try { // is the packet is marked out out-of-band (attention packets only) it must be - // sent immediately even if a send of recieve operation is already in progress + // sent immediately even if a send or receive operation is already in progress // because out of band packets are used to cancel ongoing operations // so try to take the lock if possible but continue even if it can't be taken if (packet.IsOutOfBand) @@ -1008,7 +965,7 @@ public override void KillConnection() internal static void SetKeepAliveValues(ref Socket socket) { -#if NETCOREAPP +#if NET6_0_OR_GREATER socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 1); socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 30); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SSRP.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SSRP.cs index 3cad605caa..085551c16e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SSRP.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SSRP.cs @@ -18,8 +18,8 @@ internal sealed class SSRP { private const char SemicolonSeparator = ';'; private const int SqlServerBrowserPort = 1434; //port SQL Server Browser - private const int RecieveMAXTimeoutsForCLNT_BCAST_EX = 15000; //Default max time for response wait - private const int RecieveTimeoutsForCLNT_BCAST_EX = 1000; //subsequent wait time for response after intial wait + private const int ReceiveMAXTimeoutsForCLNT_BCAST_EX = 15000; //Default max time for response wait + private const int ReceiveTimeoutsForCLNT_BCAST_EX = 1000; //subsequent wait time for response after intial wait private const int ServerResponseHeaderSizeForCLNT_BCAST_EX = 3;//(SVR_RESP + RESP_SIZE) https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/2e1560c9-5097-4023-9f5e-72b9ff1ec3b1 private const int ValidResponseSizeForCLNT_BCAST_EX = 4096; //valid reponse size should be less than 4096 private const int FirstTimeoutForCLNT_BCAST_EX = 5000;//wait for first response for 5 seconds @@ -383,11 +383,11 @@ private static SsrpResult SendUDPRequest(IPEndPoint endPoint, byte[] requestPack } /// - /// Sends request to server, and recieves response from server (SQLBrowser) on port 1434 by UDP + /// Sends request to server, and receives response from server (SQLBrowser) on port 1434 by UDP /// Request (https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/a3035afa-c268-4699-b8fd-4f351e5c8e9e) /// Response (https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/2e1560c9-5097-4023-9f5e-72b9ff1ec3b1) /// - /// string constaning list of SVR_RESP(just RESP_DATA) + /// string containing list of SVR_RESP(just RESP_DATA) internal static string SendBroadcastUDPRequest() { StringBuilder response = new StringBuilder(); @@ -407,9 +407,9 @@ internal static string SendBroadcastUDPRequest() sw.Start(); try { - while ((receiveTask = clientListener.ReceiveAsync()).Wait(currentTimeOut) && sw.ElapsedMilliseconds <= RecieveMAXTimeoutsForCLNT_BCAST_EX && receiveTask != null) + while ((receiveTask = clientListener.ReceiveAsync()).Wait(currentTimeOut) && sw.ElapsedMilliseconds <= ReceiveMAXTimeoutsForCLNT_BCAST_EX && receiveTask != null) { - currentTimeOut = RecieveTimeoutsForCLNT_BCAST_EX; + currentTimeOut = ReceiveTimeoutsForCLNT_BCAST_EX; SqlClientEventSource.Log.TrySNITraceEvent(nameof(SSRP), EventType.INFO, "Received instnace info from UDP Client."); if (receiveTask.Result.Buffer.Length < ValidResponseSizeForCLNT_BCAST_EX) //discard invalid response { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.NetStandard.cs deleted file mode 100644 index 60bb597974..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.NetStandard.cs +++ /dev/null @@ -1,223 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Buffers; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Data.SqlClient.SNI -{ - internal sealed partial class SslOverTdsStream : Stream - { - public override int Read(byte[] buffer, int offset, int count) - { - using (TrySNIEventScope.Create(nameof(SslOverTdsStream))) - { - if (!_encapsulate) - { - return _stream.Read(buffer, offset, count); - } - - if (_packetBytes > 0) - { - // there are queued bytes from a previous packet available - // work out how many of the remaining bytes we can consume - int wantedCount = Math.Min(count, _packetBytes); - int readCount = _stream.Read(buffer, offset, wantedCount); - if (readCount == 0) - { - // 0 means the connection was closed, tell the caller - return 0; - } - _packetBytes -= readCount; - return readCount; - } - else - { - byte[] headerBytes = ArrayPool.Shared.Rent(TdsEnums.HEADER_LEN); - Array.Clear(headerBytes, 0, headerBytes.Length); - - // fetch the packet header to determine how long the packet is - int headerBytesRead = 0; - do - { - int headerBytesReadIteration = _stream.Read(headerBytes, headerBytesRead, (TdsEnums.HEADER_LEN - headerBytesRead)); - if (headerBytesReadIteration == 0) - { - // 0 means the connection was closed, cleanup the rented array and then tell the caller - ArrayPool.Shared.Return(headerBytes, clearArray: true); - return 0; - } - headerBytesRead += headerBytesReadIteration; - } while (headerBytesRead < TdsEnums.HEADER_LEN); - - // read the packet data size from the header and store it in case it is needed for a subsequent call - _packetBytes = ((headerBytes[TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8) | headerBytes[TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - TdsEnums.HEADER_LEN; - - ArrayPool.Shared.Return(headerBytes, clearArray: true); - - // read as much from the packet as the caller can accept - int packetBytesRead = _stream.Read(buffer, offset, Math.Min(count, _packetBytes)); - _packetBytes -= packetBytesRead; - return packetBytesRead; - } - } - } - - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - using (TrySNIEventScope.Create(nameof(SslOverTdsStream))) - { - if (!_encapsulate) - { - return await _stream.ReadAsync(buffer, offset, count, cancellationToken); - } - - if (_packetBytes > 0) - { - // there are queued bytes from a previous packet available - // work out how many of the remaining bytes we can consume - int wantedCount = Math.Min(count, _packetBytes); - int readCount = await _stream.ReadAsync(buffer, offset, wantedCount, cancellationToken); - if (readCount == 0) - { - // 0 means the connection was closed, tell the caller - return 0; - } - _packetBytes -= readCount; - return readCount; - } - else - { - byte[] headerBytes = ArrayPool.Shared.Rent(TdsEnums.HEADER_LEN); - Array.Clear(headerBytes, 0, headerBytes.Length); - - // fetch the packet header to determine how long the packet is - int headerBytesRead = 0; - do - { - int headerBytesReadIteration = await _stream.ReadAsync(headerBytes, headerBytesRead, (TdsEnums.HEADER_LEN - headerBytesRead), cancellationToken); - if (headerBytesReadIteration == 0) - { - // 0 means the connection was closed, cleanup the rented array and then tell the caller - ArrayPool.Shared.Return(headerBytes, clearArray: true); - return 0; - } - headerBytesRead += headerBytesReadIteration; - } while (headerBytesRead < TdsEnums.HEADER_LEN); - - // read the packet data size from the header and store it in case it is needed for a subsequent call - _packetBytes = ((headerBytes[TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8) | headerBytes[TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - TdsEnums.HEADER_LEN; - - ArrayPool.Shared.Return(headerBytes, clearArray: true); - - // read as much from the packet as the caller can accept - int packetBytesRead = await _stream.ReadAsync(buffer, offset, Math.Min(count, _packetBytes), cancellationToken); - _packetBytes -= packetBytesRead; - return packetBytesRead; - } - } - } - - public override void Write(byte[] buffer, int offset, int count) - { - using (TrySNIEventScope.Create(nameof(SslOverTdsStream))) - { - // During the SSL negotiation phase, SSL is tunnelled over TDS packet type 0x12. After - // negotiation, the underlying socket only sees SSL frames. - if (!_encapsulate) - { - _stream.Write(buffer, offset, count); - _stream.Flush(); - return; - } - - int remainingBytes = count; - int dataOffset = offset; - byte[] packetBuffer = null; - while (remainingBytes > 0) - { - int dataLength = Math.Min(PACKET_SIZE_WITHOUT_HEADER, remainingBytes); - int packetLength = TdsEnums.HEADER_LEN + dataLength; - remainingBytes -= dataLength; - - if (packetBuffer == null) - { - packetBuffer = ArrayPool.Shared.Rent(packetLength); - } - else if (packetBuffer.Length < packetLength) - { - ArrayPool.Shared.Return(packetBuffer, clearArray: true); - packetBuffer = ArrayPool.Shared.Rent(packetLength); - } - - SetupPreLoginPacketHeader(packetBuffer, dataLength, remainingBytes); - - Array.Copy(buffer, dataOffset, packetBuffer, TdsEnums.HEADER_LEN, dataLength); - - _stream.Write(packetBuffer, 0, packetLength); - _stream.Flush(); - - dataOffset += dataLength; - } - if (packetBuffer != null) - { - ArrayPool.Shared.Return(packetBuffer, clearArray: true); - } - } - } - - public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - using (TrySNIEventScope.Create(nameof(SslOverTdsStream))) - { - if (!_encapsulate) - { - await _stream.WriteAsync(buffer, offset, count).ConfigureAwait(false); - Task flushTask = _stream.FlushAsync(); - if (flushTask.Status == TaskStatus.RanToCompletion) - { - await flushTask.ConfigureAwait(false); - } - return; - } - - int remainingBytes = count; - int dataOffset = offset; - byte[] packetBuffer = null; - while (remainingBytes > 0) - { - int dataLength = Math.Min(PACKET_SIZE_WITHOUT_HEADER, remainingBytes); - int packetLength = TdsEnums.HEADER_LEN + dataLength; - remainingBytes -= dataLength; - - if (packetBuffer == null) - { - packetBuffer = ArrayPool.Shared.Rent(packetLength); - } - else if (packetBuffer.Length < packetLength) - { - ArrayPool.Shared.Return(packetBuffer, clearArray: true); - packetBuffer = ArrayPool.Shared.Rent(packetLength); - } - - SetupPreLoginPacketHeader(packetBuffer, dataLength, remainingBytes); - - Array.Copy(buffer, dataOffset, packetBuffer, TdsEnums.HEADER_LEN, dataLength); - - await _stream.WriteAsync(packetBuffer, 0, packetLength, cancellationToken).ConfigureAwait(false); - await _stream.FlushAsync().ConfigureAwait(false); - - dataOffset += dataLength; - } - if (packetBuffer != null) - { - ArrayPool.Shared.Return(packetBuffer, clearArray: true); - } - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.cs index e95c5a6cf9..e0f48a28d3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SslOverTdsStream.cs @@ -99,7 +99,7 @@ public override long Position public override bool CanWrite => _stream.CanWrite; /// - /// Check if stream can be seeked + /// Check if stream can seek /// public override bool CanSeek => false; diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SspiClientContextStatus.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SspiClientContextStatus.cs index b557bfa0be..d9aabab16b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SspiClientContextStatus.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SspiClientContextStatus.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if !NET8_0_OR_GREATER + using System.Net; using System.Net.Security; @@ -28,3 +30,5 @@ public ContextFlagsPal ContextFlags } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs deleted file mode 100644 index 094114f357..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs +++ /dev/null @@ -1,195 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Configuration; - -namespace Microsoft.Data.SqlClient -{ - internal partial class SqlAuthenticationProviderManager - { - private readonly SqlAuthenticationInitializer _initializer; - - static SqlAuthenticationProviderManager() - { - SqlAuthenticationProviderConfigurationSection configurationSection = null; - - try - { - // New configuration section "SqlClientAuthenticationProviders" for Microsoft.Data.SqlClient accepted to avoid conflicts with older one. - configurationSection = FetchConfigurationSection(SqlClientAuthenticationProviderConfigurationSection.Name); - if (null == configurationSection) - { - // If configuration section is not yet found, try with old Configuration Section name for backwards compatibility - configurationSection = FetchConfigurationSection(SqlAuthenticationProviderConfigurationSection.Name); - } - } - catch (ConfigurationErrorsException e) - { - // Don't throw an error for invalid config files - SqlClientEventSource.Log.TryTraceEvent("static SqlAuthenticationProviderManager: Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e); - } - - Instance = new SqlAuthenticationProviderManager(configurationSection); - SetDefaultAuthProviders(Instance); - } - - /// - /// Constructor. - /// - public SqlAuthenticationProviderManager(SqlAuthenticationProviderConfigurationSection configSection = null) - { - var methodName = "Ctor"; - _providers = new ConcurrentDictionary(); - var authenticationsWithAppSpecifiedProvider = new HashSet(); - _authenticationsWithAppSpecifiedProvider = authenticationsWithAppSpecifiedProvider; - - if (configSection == null) - { - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "Neither SqlClientAuthenticationProviders nor SqlAuthenticationProviders configuration section found."); - return; - } - - if (!string.IsNullOrEmpty(configSection.ApplicationClientId)) - { - _applicationClientId = configSection.ApplicationClientId; - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "Received user-defined Application Client Id"); - } - else - { - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "No user-defined Application Client Id found."); - } - - // Create user-defined auth initializer, if any. - if (!string.IsNullOrEmpty(configSection.InitializerType)) - { - try - { - var initializerType = Type.GetType(configSection.InitializerType, true); - _initializer = (SqlAuthenticationInitializer)Activator.CreateInstance(initializerType); - _initializer.Initialize(); - } - catch (Exception e) - { - throw SQL.CannotCreateSqlAuthInitializer(configSection.InitializerType, e); - } - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "Created user-defined SqlAuthenticationInitializer."); - } - else - { - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "No user-defined SqlAuthenticationInitializer found."); - } - - // add user-defined providers, if any. - if (configSection.Providers != null && configSection.Providers.Count > 0) - { - foreach (ProviderSettings providerSettings in configSection.Providers) - { - SqlAuthenticationMethod authentication = AuthenticationEnumFromString(providerSettings.Name); - SqlAuthenticationProvider provider; - try - { - var providerType = Type.GetType(providerSettings.Type, true); - provider = (SqlAuthenticationProvider)Activator.CreateInstance(providerType); - } - catch (Exception e) - { - throw SQL.CannotCreateAuthProvider(authentication.ToString(), providerSettings.Type, e); - } - if (!provider.IsSupported(authentication)) - { - throw SQL.UnsupportedAuthenticationByProvider(authentication.ToString(), providerSettings.Type); - } - - _providers[authentication] = provider; - authenticationsWithAppSpecifiedProvider.Add(authentication); - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, string.Format("Added user-defined auth provider: {0} for authentication {1}.", providerSettings?.Type, authentication)); - } - } - else - { - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, "No user-defined auth providers."); - } - } - - private static T FetchConfigurationSection(string name) - { - Type t = typeof(T); - object section = ConfigurationManager.GetSection(name); - if (null != section) - { - if (section is ConfigurationSection configSection && configSection.GetType() == t) - { - return (T)section; - } - else - { - SqlClientEventSource.Log.TraceEvent("Found a custom {0} configuration but it is not of type {1}.", name, t.FullName); - } - } - return default; - } - - private static SqlAuthenticationMethod AuthenticationEnumFromString(string authentication) - { - switch (authentication.ToLowerInvariant()) - { - case ActiveDirectoryIntegrated: - return SqlAuthenticationMethod.ActiveDirectoryIntegrated; - case ActiveDirectoryPassword: - return SqlAuthenticationMethod.ActiveDirectoryPassword; - case ActiveDirectoryInteractive: - return SqlAuthenticationMethod.ActiveDirectoryInteractive; - case ActiveDirectoryServicePrincipal: - return SqlAuthenticationMethod.ActiveDirectoryServicePrincipal; - case ActiveDirectoryDeviceCodeFlow: - return SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow; - case ActiveDirectoryManagedIdentity: - return SqlAuthenticationMethod.ActiveDirectoryManagedIdentity; - case ActiveDirectoryMSI: - return SqlAuthenticationMethod.ActiveDirectoryMSI; - case ActiveDirectoryDefault: - return SqlAuthenticationMethod.ActiveDirectoryDefault; - default: - throw SQL.UnsupportedAuthentication(authentication); - } - } - - /// - /// The configuration section definition for reading app.config. - /// - internal class SqlAuthenticationProviderConfigurationSection : ConfigurationSection - { - public const string Name = "SqlAuthenticationProviders"; - - /// - /// User-defined auth providers. - /// - [ConfigurationProperty("providers")] - public ProviderSettingsCollection Providers => (ProviderSettingsCollection)this["providers"]; - - /// - /// User-defined initializer. - /// - [ConfigurationProperty("initializerType")] - public string InitializerType => this["initializerType"] as string; - - /// - /// Application Client Id - /// - [ConfigurationProperty("applicationClientId", IsRequired = false)] - public string ApplicationClientId => this["applicationClientId"] as string; - } - - /// - /// The configuration section definition for reading app.config. - /// - internal class SqlClientAuthenticationProviderConfigurationSection : SqlAuthenticationProviderConfigurationSection - { - public new const string Name = "SqlClientAuthenticationProviders"; - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs deleted file mode 100644 index 01a84342f8..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.SqlClient -{ - internal partial class SqlAuthenticationProviderManager - { - static SqlAuthenticationProviderManager() - { - Instance = new SqlAuthenticationProviderManager(); - SetDefaultAuthProviders(Instance); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs deleted file mode 100644 index 401fc23466..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace Microsoft.Data.SqlClient -{ - /// - /// Authentication provider manager. - /// - internal partial class SqlAuthenticationProviderManager - { - private const string ActiveDirectoryPassword = "active directory password"; - private const string ActiveDirectoryIntegrated = "active directory integrated"; - private const string ActiveDirectoryInteractive = "active directory interactive"; - private const string ActiveDirectoryServicePrincipal = "active directory service principal"; - private const string ActiveDirectoryDeviceCodeFlow = "active directory device code flow"; - private const string ActiveDirectoryManagedIdentity = "active directory managed identity"; - private const string ActiveDirectoryMSI = "active directory msi"; - private const string ActiveDirectoryDefault = "active directory default"; - - private readonly IReadOnlyCollection _authenticationsWithAppSpecifiedProvider; - private readonly ConcurrentDictionary _providers; - private readonly SqlClientLogger _sqlAuthLogger = new SqlClientLogger(); - private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId; - - public static readonly SqlAuthenticationProviderManager Instance; - - /// - /// Sets default supported Active Directory Authentication providers by the driver - /// on the SqlAuthenticationProviderManager instance. - /// - private static void SetDefaultAuthProviders(SqlAuthenticationProviderManager instance) - { - if (instance != null) - { - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(instance._applicationClientId); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); - instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDefault, activeDirectoryAuthProvider); - } - } - /// - /// Constructor. - /// - public SqlAuthenticationProviderManager() - { - _providers = new ConcurrentDictionary(); - _authenticationsWithAppSpecifiedProvider = new HashSet(); - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), "Ctor", "No SqlAuthProviders configuration section found."); - } - - /// - /// Get an authentication provider by method. - /// - /// Authentication method. - /// Authentication provider or null if not found. - public SqlAuthenticationProvider GetProvider(SqlAuthenticationMethod authenticationMethod) - { - SqlAuthenticationProvider value; - return _providers.TryGetValue(authenticationMethod, out value) ? value : null; - } - - /// - /// Set an authentication provider by method. - /// - /// Authentication method. - /// Authentication provider. - /// True if succeeded, false otherwise, e.g., the existing provider disallows overriding. - public bool SetProvider(SqlAuthenticationMethod authenticationMethod, SqlAuthenticationProvider provider) - { - if (!provider.IsSupported(authenticationMethod)) - { - throw SQL.UnsupportedAuthenticationByProvider(authenticationMethod.ToString(), provider.GetType().Name); - } - var methodName = "SetProvider"; - if (_authenticationsWithAppSpecifiedProvider.Count > 0) - { - foreach (SqlAuthenticationMethod candidateMethod in _authenticationsWithAppSpecifiedProvider) - { - if (candidateMethod == authenticationMethod) - { - _sqlAuthLogger.LogError(nameof(SqlAuthenticationProviderManager), methodName, $"Failed to add provider {GetProviderType(provider)} because a user-defined provider with type {GetProviderType(_providers[authenticationMethod])} already existed for authentication {authenticationMethod}."); - break; - } - } - } - _providers.AddOrUpdate(authenticationMethod, provider, (key, oldProvider) => - { - if (oldProvider != null) - { - oldProvider.BeforeUnload(authenticationMethod); - } - if (provider != null) - { - provider.BeforeLoad(authenticationMethod); - } - _sqlAuthLogger.LogInfo(nameof(SqlAuthenticationProviderManager), methodName, $"Added auth provider {GetProviderType(provider)}, overriding existed provider {GetProviderType(oldProvider)} for authentication {authenticationMethod}."); - return provider; - }); - return true; - } - - private static string GetProviderType(SqlAuthenticationProvider provider) - { - if (provider == null) - return "null"; - return provider.GetType().FullName; - } - } - - /// - public abstract class SqlAuthenticationInitializer - { - /// - public abstract void Initialize(); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs index 273394395a..93bf6e119f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs @@ -385,7 +385,7 @@ internal SqlStatistics Statistics { get { - if (null != _connection) + if (_connection != null) { if (_connection.StatisticsEnabled) { @@ -540,7 +540,7 @@ private string AnalyzeTargetAndCreateUpdateBulkCommand(BulkCopySimpleResultSet i isInTransaction = _connection.HasLocalTransaction; // Throw if there is a transaction but no flag is set - if (isInTransaction && null == _externalTransaction && null == _internalTransaction && (_connection.Parser != null && _connection.Parser.CurrentTransaction != null && _connection.Parser.CurrentTransaction.IsLocal)) + if (isInTransaction && _externalTransaction == null && _internalTransaction == null && (_connection.Parser != null && _connection.Parser.CurrentTransaction != null && _connection.Parser.CurrentTransaction.IsLocal)) { throw SQL.BulkLoadExistingTransaction(); } @@ -683,7 +683,7 @@ private string AnalyzeTargetAndCreateUpdateBulkCommand(BulkCopySimpleResultSet i { updateBulkCommandText.Append(" COLLATE " + collation_name.Value); // Compare collations only if the collation value was set on the metadata - if (null != _sqlDataReaderRowSource && metadata.collation != null) + if (_sqlDataReaderRowSource != null && metadata.collation != null) { // On SqlDataReader we can verify the sourcecolumn collation! int sourceColumnId = _localColumnMappings[assocId]._internalSourceColumnOrdinal; @@ -847,7 +847,7 @@ private void Dispose(bool disposing) try { Debug.Assert(_internalTransaction == null, "Internal transaction exists during dispose"); - if (null != _internalTransaction) + if (_internalTransaction != null) { _internalTransaction.Rollback(); _internalTransaction.Dispose(); @@ -922,7 +922,7 @@ private object GetValueFromSourceRow(int destRowIndex, out bool isSqlType, out b } } // SqlDataReader-specific logic - else if (null != _sqlDataReaderRowSource) + else if (_sqlDataReaderRowSource != null) { if (_currentRowMetadata[destRowIndex].IsSqlType) { @@ -1281,7 +1281,7 @@ private SourceColumnMetadata GetColumnMetadata(int ordinal) private void CreateOrValidateConnection(string method) { - if (null == _connection) + if (_connection == null) { throw ADP.ConnectionRequired(method); } @@ -1297,7 +1297,7 @@ private void CreateOrValidateConnection(string method) // If we have a transaction, check to ensure that the active // connection property matches the connection associated with // the transaction. - if (null != _externalTransaction && _connection != _externalTransaction.Connection) + if (_externalTransaction != null && _connection != _externalTransaction.Connection) { throw ADP.TransactionConnectionMismatch(); } @@ -1340,7 +1340,7 @@ private void RunParserReliably(BulkCopySimpleResultSet bulkCopyHandler = null) private void CommitTransaction() { - if (null != _internalTransaction) + if (_internalTransaction != null) { SqlInternalConnectionTds internalConnection = _connection.GetOpenTdsConnection(); internalConnection.ThreadHasParserLockForClose = true; // In case of error, let the connection know that we have the lock @@ -1640,14 +1640,12 @@ public void WriteToServer(DbDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _dbDataReaderRowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; - - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1673,12 +1671,11 @@ public void WriteToServer(IDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1707,13 +1704,12 @@ public void WriteToServer(DataTable table, DataRowState rowState) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1746,16 +1742,14 @@ public void WriteToServer(DataRow[] rows) try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); DataTable table = rows[0].Table; - Debug.Assert(null != table, "How can we have rows without a table?"); + Debug.Assert(table != null, "How can we have rows without a table?"); _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1787,7 +1781,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); if (rows.Length == 0) { return cancellationToken.IsCancellationRequested ? @@ -1796,11 +1790,10 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok } DataTable table = rows[0].Table; - Debug.Assert(null != table, "How can we have rows without a table?"); + Debug.Assert(table != null, "How can we have rows without a table?"); _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); _isAsyncBulkCopy = true; @@ -1834,10 +1827,10 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; _dbDataReaderRowSource = reader; - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1871,10 +1864,10 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1914,9 +1907,9 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; - _sqlDataReaderRowSource = null; _dataTableSource = table; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); @@ -3093,5 +3086,17 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken) } return resultTask; } + + private void ResetWriteToServerGlobalVariables() + { + _dataTableSource = null; + _dbDataReaderRowSource = null; + _isAsyncBulkCopy = false; + _rowEnumerator = null; + _rowSource = null; + _rowSourceType = ValueSourceType.Unspecified; + _sqlDataReaderRowSource = null; + _sqlDataReaderRowSource = null; + } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnostic.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnostic.cs new file mode 100644 index 0000000000..51a2f8f0ba --- /dev/null +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnostic.cs @@ -0,0 +1,970 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; + +namespace Microsoft.Data.SqlClient.Diagnostics +{ + /// + public sealed class SqlClientCommandBefore : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandBefore"; + + internal SqlClientCommandBefore(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + TransactionId = transactionId; + Command = command; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid? ConnectionId { get; } + /// + public long? TransactionId { get; } + /// + public SqlCommand Command { get; } + + /// + public int Count => 3 + 3; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(TransactionId), TransactionId), + 5 => new KeyValuePair(nameof(Command), Command), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientCommandAfter : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteCommandAfter"; + + internal SqlClientCommandAfter(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command, IDictionary statistics) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + TransactionId = transactionId; + Command = command; + Statistics = statistics; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid? ConnectionId { get; } + /// + public long? TransactionId { get; } + /// + public SqlCommand Command { get; } + /// + public IDictionary Statistics { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(TransactionId), TransactionId), + 5 => new KeyValuePair(nameof(Command), Command), + 6 => new KeyValuePair(nameof(Statistics), Statistics), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientCommandError : IReadOnlyList> + { + /// + + public const string Name = "Microsoft.Data.SqlClient.WriteCommandError"; + + internal SqlClientCommandError(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command, Exception exception) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + TransactionId = transactionId; + Command = command; + Exception = exception; + } + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid? ConnectionId { get; } + /// + public long? TransactionId { get; } + /// + public SqlCommand Command { get; } + /// + public Exception Exception { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(TransactionId), TransactionId), + 5 => new KeyValuePair(nameof(Command), Command), + 6 => new KeyValuePair(nameof(Exception), Exception), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionOpenBefore : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenBefore"; + + internal SqlClientConnectionOpenBefore(Guid operationId, string operation, long timestamp, SqlConnection connection, string clientVersion) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + Connection = connection; + ClientVersion = clientVersion; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public SqlConnection Connection { get; } + /// + public string ClientVersion { get; } + + /// + public int Count => 3 + 2; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(Connection), Connection), + 4 => new KeyValuePair(nameof(ClientVersion), ClientVersion), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionOpenAfter : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenAfter"; + + internal SqlClientConnectionOpenAfter(Guid operationId, string operation, long timestamp, Guid connectionId, SqlConnection connection, string clientVersion, IDictionary statistics) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + Connection = connection; + ClientVersion = clientVersion; + Statistics = statistics; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid ConnectionId { get; } + /// + public SqlConnection Connection { get; } + /// + public string ClientVersion { get; } + /// + public IDictionary Statistics { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(ClientVersion), ClientVersion), + 6 => new KeyValuePair(nameof(Statistics), Statistics), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionOpenError : IReadOnlyList> + { + /// + + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionOpenError"; + + internal SqlClientConnectionOpenError(Guid operationId, string operation, long timestamp, Guid connectionId, SqlConnection connection, string clientVersion, Exception exception) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + Connection = connection; + ClientVersion = clientVersion; + Exception = exception; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + + /// + public Guid ConnectionId { get; } + /// + public SqlConnection Connection { get; } + /// + public string ClientVersion { get; } + /// + public Exception Exception { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(ClientVersion), ClientVersion), + 6 => new KeyValuePair(nameof(Exception), Exception), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionCloseBefore : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseBefore"; + + internal SqlClientConnectionCloseBefore(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + Connection = connection; + Statistics = statistics; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid? ConnectionId { get; } + /// + public SqlConnection Connection { get; } + /// + public IDictionary Statistics { get; } + + /// + public int Count => 3 + 3; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(Statistics), Statistics), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionCloseAfter : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseAfter"; + + internal SqlClientConnectionCloseAfter(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + Connection = connection; + Statistics = statistics; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public Guid? ConnectionId { get; } + /// + public SqlConnection Connection { get; } + /// + public IDictionary Statistics { get; } + + /// + public int Count => 3 + 3; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(Statistics), Statistics), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientConnectionCloseError : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseError"; + + internal SqlClientConnectionCloseError(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics, Exception ex) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + ConnectionId = connectionId; + Connection = connection; + Statistics = statistics; + Exception = ex; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + + /// + public Guid? ConnectionId { get; } + /// + public SqlConnection Connection { get; } + /// + public IDictionary Statistics { get; } + + /// + public Exception Exception { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(ConnectionId), ConnectionId), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(Statistics), Statistics), + 6 => new KeyValuePair(nameof(Exception), Exception), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionCommitBefore : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitBefore"; + + internal SqlClientTransactionCommitBefore(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + + /// + public int Count => 3 + 3; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionCommitAfter : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitAfter"; + + internal SqlClientTransactionCommitAfter(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + + /// + public int Count => 3 + 3; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionCommitError : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionCommitError"; + + internal SqlClientTransactionCommitError(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId, Exception ex) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + Exception = ex; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + /// + public Exception Exception { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + 6 => new KeyValuePair(nameof(Exception), Exception), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionRollbackBefore : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackBefore"; + + internal SqlClientTransactionRollbackBefore(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId, string transactionName) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + TransactionName = transactionName; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + /// + public string TransactionName { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + 6 => new KeyValuePair(nameof(TransactionName), TransactionName), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionRollbackAfter : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackAfter"; + + internal SqlClientTransactionRollbackAfter(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId, string transactionName) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + TransactionName = transactionName; + } + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + /// + public string TransactionName { get; } + + /// + public int Count => 3 + 4; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + 6 => new KeyValuePair(nameof(TransactionName), TransactionName), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } + + /// + public sealed class SqlClientTransactionRollbackError : IReadOnlyList> + { + /// + public const string Name = "Microsoft.Data.SqlClient.WriteTransactionRollbackError"; + + internal SqlClientTransactionRollbackError(Guid operationId, string operation, long timestamp, IsolationLevel isolationLevel, SqlConnection connection, long? transactionId, string transactionName, Exception ex) + { + OperationId = operationId; + Operation = operation; + Timestamp = timestamp; + IsolationLevel = isolationLevel; + Connection = connection; + TransactionId = transactionId; + TransactionName = transactionName; + Exception = ex; + } + + + /// + public Guid OperationId { get; } + /// + public string Operation { get; } + /// + public long Timestamp { get; } + /// + public IsolationLevel IsolationLevel { get; } + /// + public SqlConnection Connection { get; } + /// + public long? TransactionId { get; } + /// + public string TransactionName { get; } + /// + public Exception Exception { get; } + + /// + public int Count => 3 + 5; + + /// + public KeyValuePair this[int index] + { + get => index switch + { + 0 => new KeyValuePair(nameof(OperationId), OperationId), + 1 => new KeyValuePair(nameof(Operation), Operation), + 2 => new KeyValuePair(nameof(Timestamp), Timestamp), + 3 => new KeyValuePair(nameof(IsolationLevel), IsolationLevel), + 4 => new KeyValuePair(nameof(Connection), Connection), + 5 => new KeyValuePair(nameof(TransactionId), TransactionId), + 6 => new KeyValuePair(nameof(TransactionName), TransactionName), + 7 => new KeyValuePair(nameof(Exception), Exception), + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + public IEnumerator> GetEnumerator() + { + int count = Count; + for (int index = 0; index < count; index++) + { + yield return this[index]; + } + } + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnosticListenerExtensions.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnosticListenerExtensions.cs index 1d955b8c47..9f63cbaba8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnosticListenerExtensions.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientDiagnosticListenerExtensions.cs @@ -3,9 +3,12 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections; +using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Runtime.CompilerServices; +using Microsoft.Data.SqlClient.Diagnostics; namespace Microsoft.Data.SqlClient { @@ -16,168 +19,155 @@ internal static class SqlClientDiagnosticListenerExtensions { public const string DiagnosticListenerName = "SqlClientDiagnosticListener"; - private const string SqlClientPrefix = "Microsoft.Data.SqlClient."; - - public const string SqlBeforeExecuteCommand = SqlClientPrefix + nameof(WriteCommandBefore); - public const string SqlAfterExecuteCommand = SqlClientPrefix + nameof(WriteCommandAfter); - public const string SqlErrorExecuteCommand = SqlClientPrefix + nameof(WriteCommandError); - - public const string SqlBeforeOpenConnection = SqlClientPrefix + nameof(WriteConnectionOpenBefore); - public const string SqlAfterOpenConnection = SqlClientPrefix + nameof(WriteConnectionOpenAfter); - public const string SqlErrorOpenConnection = SqlClientPrefix + nameof(WriteConnectionOpenError); - - public const string SqlBeforeCloseConnection = SqlClientPrefix + nameof(WriteConnectionCloseBefore); - public const string SqlAfterCloseConnection = SqlClientPrefix + nameof(WriteConnectionCloseAfter); - public const string SqlErrorCloseConnection = SqlClientPrefix + nameof(WriteConnectionCloseError); - - public const string SqlBeforeCommitTransaction = SqlClientPrefix + nameof(WriteTransactionCommitBefore); - public const string SqlAfterCommitTransaction = SqlClientPrefix + nameof(WriteTransactionCommitAfter); - public const string SqlErrorCommitTransaction = SqlClientPrefix + nameof(WriteTransactionCommitError); - - public const string SqlBeforeRollbackTransaction = SqlClientPrefix + nameof(WriteTransactionRollbackBefore); - public const string SqlAfterRollbackTransaction = SqlClientPrefix + nameof(WriteTransactionRollbackAfter); - public const string SqlErrorRollbackTransaction = SqlClientPrefix + nameof(WriteTransactionRollbackError); - public static Guid WriteCommandBefore(this SqlDiagnosticListener @this, SqlCommand sqlCommand, SqlTransaction transaction, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlBeforeExecuteCommand)) + if (@this.IsEnabled(SqlClientCommandBefore.Name)) { Guid operationId = Guid.NewGuid(); @this.Write( - SqlBeforeExecuteCommand, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlCommand.Connection?.ClientConnectionId, - Command = sqlCommand, + SqlClientCommandBefore.Name, + new SqlClientCommandBefore( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlCommand.Connection?.ClientConnectionId, transaction?.InternalTransaction?.TransactionId, - Timestamp = Stopwatch.GetTimestamp() - }); + sqlCommand + ) + ); return operationId; } else + { return Guid.Empty; + } } public static void WriteCommandAfter(this SqlDiagnosticListener @this, Guid operationId, SqlCommand sqlCommand, SqlTransaction transaction, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlAfterExecuteCommand)) + if (@this.IsEnabled(SqlClientCommandAfter.Name)) { @this.Write( - SqlAfterExecuteCommand, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlCommand.Connection?.ClientConnectionId, - Command = sqlCommand, + SqlClientCommandAfter.Name, + new SqlClientCommandAfter( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlCommand.Connection?.ClientConnectionId, transaction?.InternalTransaction?.TransactionId, - Statistics = sqlCommand.Statistics?.GetDictionary(), - Timestamp = Stopwatch.GetTimestamp() - }); + sqlCommand, + sqlCommand.Statistics?.GetDictionary() + ) + ); } } public static void WriteCommandError(this SqlDiagnosticListener @this, Guid operationId, SqlCommand sqlCommand, SqlTransaction transaction, Exception ex, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlErrorExecuteCommand)) + if (@this.IsEnabled(SqlClientCommandError.Name)) { @this.Write( - SqlErrorExecuteCommand, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlCommand.Connection?.ClientConnectionId, - Command = sqlCommand, + SqlClientCommandError.Name, + new SqlClientCommandError + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlCommand.Connection?.ClientConnectionId, transaction?.InternalTransaction?.TransactionId, - Exception = ex, - Timestamp = Stopwatch.GetTimestamp() - }); + sqlCommand, + ex + ) + ); } } public static Guid WriteConnectionOpenBefore(this SqlDiagnosticListener @this, SqlConnection sqlConnection, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlBeforeOpenConnection)) + if (@this.IsEnabled(SqlClientConnectionOpenBefore.Name)) { Guid operationId = Guid.NewGuid(); @this.Write( - SqlBeforeOpenConnection, - new - { - OperationId = operationId, - Operation = operation, - Connection = sqlConnection, - ClientVersion = ThisAssembly.InformationalVersion, - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionOpenBefore.Name, + new SqlClientConnectionOpenBefore + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlConnection, + ThisAssembly.InformationalVersion + ) + ); return operationId; } else + { return Guid.Empty; + } } public static void WriteConnectionOpenAfter(this SqlDiagnosticListener @this, Guid operationId, SqlConnection sqlConnection, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlAfterOpenConnection)) + if (@this.IsEnabled(SqlClientConnectionOpenAfter.Name)) { @this.Write( - SqlAfterOpenConnection, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlConnection.ClientConnectionId, - Connection = sqlConnection, - ClientVersion = ThisAssembly.InformationalVersion, - Statistics = sqlConnection.Statistics?.GetDictionary(), - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionOpenAfter.Name, + new SqlClientConnectionOpenAfter + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlConnection.ClientConnectionId, + sqlConnection, + ThisAssembly.InformationalVersion, + sqlConnection.Statistics?.GetDictionary() + ) + ); } } public static void WriteConnectionOpenError(this SqlDiagnosticListener @this, Guid operationId, SqlConnection sqlConnection, Exception ex, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlErrorOpenConnection)) + if (@this.IsEnabled(SqlClientConnectionOpenError.Name)) { @this.Write( - SqlErrorOpenConnection, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlConnection.ClientConnectionId, - Connection = sqlConnection, - ClientVersion = ThisAssembly.InformationalVersion, - Exception = ex, - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionOpenError.Name, + new SqlClientConnectionOpenError + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlConnection.ClientConnectionId, + sqlConnection, + ThisAssembly.InformationalVersion, + ex + ) + ); } } public static Guid WriteConnectionCloseBefore(this SqlDiagnosticListener @this, SqlConnection sqlConnection, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlBeforeCloseConnection)) + if (@this.IsEnabled(SqlClientConnectionCloseBefore.Name)) { Guid operationId = Guid.NewGuid(); @this.Write( - SqlBeforeCloseConnection, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = sqlConnection.ClientConnectionId, - Connection = sqlConnection, - Statistics = sqlConnection.Statistics?.GetDictionary(), - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionCloseBefore.Name, + new SqlClientConnectionCloseBefore + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + sqlConnection.ClientConnectionId, + sqlConnection, + sqlConnection.Statistics?.GetDictionary() + ) + ); return operationId; } @@ -187,163 +177,175 @@ public static Guid WriteConnectionCloseBefore(this SqlDiagnosticListener @this, public static void WriteConnectionCloseAfter(this SqlDiagnosticListener @this, Guid operationId, Guid clientConnectionId, SqlConnection sqlConnection, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlAfterCloseConnection)) + if (@this.IsEnabled(SqlClientConnectionCloseAfter.Name)) { @this.Write( - SqlAfterCloseConnection, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = clientConnectionId, - Connection = sqlConnection, - Statistics = sqlConnection.Statistics?.GetDictionary(), - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionCloseAfter.Name, + new SqlClientConnectionCloseAfter + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + clientConnectionId, + sqlConnection, + sqlConnection.Statistics?.GetDictionary() + ) + ); } } public static void WriteConnectionCloseError(this SqlDiagnosticListener @this, Guid operationId, Guid clientConnectionId, SqlConnection sqlConnection, Exception ex, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlErrorCloseConnection)) + if (@this.IsEnabled(SqlClientConnectionCloseError.Name)) { @this.Write( - SqlErrorCloseConnection, - new - { - OperationId = operationId, - Operation = operation, - ConnectionId = clientConnectionId, - Connection = sqlConnection, - Statistics = sqlConnection.Statistics?.GetDictionary(), - Exception = ex, - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientConnectionCloseError.Name, + new SqlClientConnectionCloseError + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + clientConnectionId, + sqlConnection, + sqlConnection.Statistics?.GetDictionary(), + ex + ) + ); } } public static Guid WriteTransactionCommitBefore(this SqlDiagnosticListener @this, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlBeforeCommitTransaction)) + if (@this.IsEnabled(SqlClientTransactionCommitBefore.Name)) { Guid operationId = Guid.NewGuid(); @this.Write( - SqlBeforeCommitTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, - transaction?.TransactionId, - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientTransactionCommitBefore.Name, + new SqlClientTransactionCommitBefore + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, + transaction?.TransactionId + ) + ); return operationId; } else + { return Guid.Empty; + } } public static void WriteTransactionCommitAfter(this SqlDiagnosticListener @this, Guid operationId, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlAfterCommitTransaction)) + if (@this.IsEnabled(SqlClientTransactionCommitAfter.Name)) { @this.Write( - SqlAfterCommitTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, - transaction?.TransactionId, - Timestamp = Stopwatch.GetTimestamp() - }); + SqlClientTransactionCommitAfter.Name, + new SqlClientTransactionCommitAfter + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, + transaction?.TransactionId + ) + ); } } public static void WriteTransactionCommitError(this SqlDiagnosticListener @this, Guid operationId, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, Exception ex, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlErrorCommitTransaction)) + if (@this.IsEnabled(SqlClientTransactionCommitError.Name)) { @this.Write( - SqlErrorCommitTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, + SqlClientTransactionCommitError.Name, + new SqlClientTransactionCommitError + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, transaction?.TransactionId, - Exception = ex, - Timestamp = Stopwatch.GetTimestamp() - }); + ex + ) + ); } } public static Guid WriteTransactionRollbackBefore(this SqlDiagnosticListener @this, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, string transactionName = null, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlBeforeRollbackTransaction)) + if (@this.IsEnabled(SqlClientTransactionRollbackBefore.Name)) { Guid operationId = Guid.NewGuid(); @this.Write( - SqlBeforeRollbackTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, + SqlClientTransactionRollbackBefore.Name, + new SqlClientTransactionRollbackBefore + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, transaction?.TransactionId, - TransactionName = transactionName, - Timestamp = Stopwatch.GetTimestamp() - }); + transactionName + ) + ); return operationId; } else + { return Guid.Empty; + } } public static void WriteTransactionRollbackAfter(this SqlDiagnosticListener @this, Guid operationId, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, string transactionName = null, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlAfterRollbackTransaction)) + if (@this.IsEnabled(SqlClientTransactionRollbackAfter.Name)) { @this.Write( - SqlAfterRollbackTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, + SqlClientTransactionRollbackAfter.Name, + new SqlClientTransactionRollbackAfter + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, transaction?.TransactionId, - TransactionName = transactionName, - Timestamp = Stopwatch.GetTimestamp() - }); + transactionName + ) + ); } } public static void WriteTransactionRollbackError(this SqlDiagnosticListener @this, Guid operationId, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, Exception ex, string transactionName = null, [CallerMemberName] string operation = "") { - if (@this.IsEnabled(SqlErrorRollbackTransaction)) + if (@this.IsEnabled(SqlClientTransactionRollbackError.Name)) { @this.Write( - SqlErrorRollbackTransaction, - new - { - OperationId = operationId, - Operation = operation, - IsolationLevel = isolationLevel, - Connection = connection, + SqlClientTransactionRollbackError.Name, + new SqlClientTransactionRollbackError + ( + operationId, + operation, + Stopwatch.GetTimestamp(), + isolationLevel, + connection, transaction?.TransactionId, - TransactionName = transactionName, - Exception = ex, - Timestamp = Stopwatch.GetTimestamp() - }); + transactionName, + ex + ) + ); } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientFactory.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientFactory.cs deleted file mode 100644 index 2dd3261fe6..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientFactory.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Data.Common; - -namespace Microsoft.Data.SqlClient -{ - /// - public sealed partial class SqlClientFactory : DbProviderFactory - { - /// - public static readonly SqlClientFactory Instance = new SqlClientFactory(); - - private SqlClientFactory() - { - } - - /// - public override DbCommand CreateCommand() - { - return new SqlCommand(); - } - - /// - public override DbCommandBuilder CreateCommandBuilder() - { - return new SqlCommandBuilder(); - } - - /// - public override DbConnection CreateConnection() - { - return new SqlConnection(); - } - - /// - public override DbConnectionStringBuilder CreateConnectionStringBuilder() - { - return new SqlConnectionStringBuilder(); - } - - /// - public override DbDataAdapter CreateDataAdapter() - { - return new SqlDataAdapter(); - } - - /// - public override DbParameter CreateParameter() - { - return new SqlParameter(); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs deleted file mode 100644 index fd81db557d..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Security.Cryptography; - -namespace Microsoft.Data.SqlClient -{ - /// - /// The base class that defines the interface for enclave providers for Always Encrypted. An enclave is a protected region of memory inside SQL Server, used for computations on encrypted columns. An enclave provider encapsulates the client-side implementation details of the enclave attestation protocol as well as the logic for creating and caching enclave sessions. - /// - internal abstract partial class SqlColumnEncryptionEnclaveProvider - { - /// Performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. - /// The information the provider uses to attest the enclave and generate a symmetric key for the session. The format of this information is specific to the enclave attestation protocol. - /// A Diffie-Hellman algorithm object encapsulating a client-side key pair. - /// The set of parameters required for enclave session. - /// The set of extra data needed for attesting the enclave. - /// The length of the extra data needed for attesting the enclave. - /// The requested enclave session or null if the provider does not implement session caching. - /// A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. - internal abstract void CreateEnclaveSession(byte[] enclaveAttestationInfo, ECDiffieHellman clientDiffieHellmanKey, EnclaveSessionParameters enclaveSessionParameters, byte[] customData, int customDataLength, - out SqlEnclaveSession sqlEnclaveSession, out long counter); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.cs deleted file mode 100644 index 9223702509..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.SqlClient -{ - /// - internal abstract partial class SqlColumnEncryptionEnclaveProvider - { - /// - internal abstract void GetEnclaveSession(EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, bool isRetry, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength); - - /// - internal abstract SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength); - - /// - internal abstract void InvalidateEnclaveSession(EnclaveSessionParameters enclaveSessionParameters, SqlEnclaveSession enclaveSession); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index 3e12b61a61..e64d81da40 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -19,6 +19,7 @@ using System.Xml; using Microsoft.Data.Common; using Microsoft.Data.Sql; +using Microsoft.Data.SqlClient.Diagnostics; using Microsoft.Data.SqlClient.Server; // NOTE: The current Microsoft.VSDesigner editor attributes are implemented for System.Data.SqlClient, and are not publicly available. @@ -71,7 +72,7 @@ internal sealed class ExecuteNonQueryAsyncCallContext : AAsyncCallContext TaskCompletionSource => _source; - public void Set(SqlCommand command, TaskCompletionSource source, CancellationTokenRegistration disposable, Guid operationID) + public void Set(SqlCommand command, TaskCompletionSource source, CancellationTokenRegistration disposable, Guid operationID) { base.Set(command, source, disposable); OperationID = operationID; @@ -249,9 +250,9 @@ internal bool IsColumnEncryptionEnabled } } - internal bool ShouldUseEnclaveBasedWorkflow => - (!string.IsNullOrWhiteSpace(_activeConnection.EnclaveAttestationUrl) || Connection.AttestationProtocol == SqlConnectionAttestationProtocol.None) && - IsColumnEncryptionEnabled; + internal bool ShouldUseEnclaveBasedWorkflow => + (!string.IsNullOrWhiteSpace(_activeConnection.EnclaveAttestationUrl) || Connection.AttestationProtocol == SqlConnectionAttestationProtocol.None) && + IsColumnEncryptionEnabled; /// /// Per-command custom providers. It can be provided by the user and can be set more than once. @@ -290,7 +291,7 @@ internal string CachedSetOptions } internal bool PendingAsyncOperation { - get { return (null != _cachedAsyncResult); } + get { return _cachedAsyncResult != null; } } internal string EndMethodName { @@ -391,9 +392,7 @@ private CachedAsyncState cachedAsyncState private bool _batchRPCMode; private List<_SqlRPC> _RPCList; - private _SqlRPC[] _SqlRPCBatchArray; private _SqlRPC[] _sqlRPCParameterEncryptionReqArray; - private List _parameterCollectionList; private int _currentlyExecutingBatch; private SqlRetryLogicBaseProvider _retryLogicProvider; @@ -497,7 +496,7 @@ private SqlCommand(SqlCommand from) : this() // Check to see if the currently set transaction has completed. If so, // null out our local reference. - if (null != _transaction && _transaction.Connection == null) + if (_transaction != null && _transaction.Connection == null) { _transaction = null; } @@ -595,10 +594,10 @@ internal SqlStatistics Statistics { get { - if (null != _activeConnection) + if (_activeConnection != null) { if (_activeConnection.StatisticsEnabled || - s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand)) + s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name)) { return _activeConnection.Statistics; } @@ -616,7 +615,7 @@ internal SqlStatistics Statistics get { // if the transaction object has been zombied, just return null - if ((null != _transaction) && (null == _transaction.Connection)) + if (_transaction != null && _transaction.Connection == null) { _transaction = null; } @@ -784,7 +783,7 @@ public override bool DesignTimeVisible { get { - if (null == _parameters) + if (_parameters == null) { // delay the creation of the SqlParameterCollection // until user actually uses the Parameters property @@ -850,7 +849,7 @@ internal void OnStatementCompleted(int recordCount) if (0 <= recordCount) { StatementCompletedEventHandler handler = _statementCompletedEventHandler; - if (null != handler) + if (handler != null) { try { @@ -894,7 +893,7 @@ public override void Prepare() || ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters)))) { - if (null != Statistics) + if (Statistics != null) { Statistics.SafeIncrement(ref Statistics._prepares); } @@ -912,7 +911,7 @@ public override void Prepare() GetStateObject(); // Loop through parameters ensuring that we do not have unspecified types, sizes, scales, or precisions - if (null != _parameters) + if (_parameters != null) { int count = _parameters.Count; for (int i = 0; i < count; ++i) @@ -959,8 +958,8 @@ private void InternalPrepare() } Debug.Assert(_execType != EXECTYPE.PREPARED, "Invalid attempt to Prepare already Prepared command!"); Debug.Assert(_activeConnection != null, "must have an open connection to Prepare"); - Debug.Assert(null != _stateObj, "TdsParserStateObject should not be null"); - Debug.Assert(null != _stateObj.Parser, "TdsParser class should not be null in Command.Execute!"); + Debug.Assert(_stateObj != null, "TdsParserStateObject should not be null"); + Debug.Assert(_stateObj.Parser != null, "TdsParser class should not be null in Command.Execute!"); Debug.Assert(_stateObj.Parser == _activeConnection.Parser, "stateobject parser not same as connection parser"); Debug.Assert(false == _inPrepare, "Already in Prepare cycle, this.inPrepare should be false!"); @@ -970,7 +969,7 @@ private void InternalPrepare() _preparedConnectionCloseCount = _activeConnection.CloseCount; _preparedConnectionReconnectCount = _activeConnection.ReconnectCount; - if (null != Statistics) + if (Statistics != null) { Statistics.SafeIncrement(ref Statistics._prepares); } @@ -1029,12 +1028,12 @@ public override void Cancel() // if we have pending data, but it is not a result of this command, then we don't cancel either. Note that // this model is implementable because we only allow one active command at any one time. This code // will have to change we allow multiple outstanding batches - if (null == _activeConnection) + if (_activeConnection == null) { return; } SqlInternalConnectionTds connection = (_activeConnection.InnerConnection as SqlInternalConnectionTds); - if (null == connection) + if (connection == null) { // Fail with out locking return; } @@ -1051,12 +1050,11 @@ public override void Cancel() } TdsParser parser = connection.Parser; - if (null == parser) + if (parser == null) { return; } - if (!_pendingCancel) { // Do nothing if already pending. // Before attempting actual cancel, set the _pendingCancel flag to false. @@ -1067,7 +1065,7 @@ public override void Cancel() _pendingCancel = true; TdsParserStateObject stateObj = _stateObj; - if (null != stateObj) + if (stateObj != null) { stateObj.Cancel(this); } @@ -1142,7 +1140,7 @@ public override object ExecuteScalar() RunExecuteReaderWithRetry(0, RunBehavior.ReturnImmediately, returnStream: true) : RunExecuteReader(0, RunBehavior.ReturnImmediately, returnStream: true, method: nameof(ExecuteScalar)); success = true; - return CompleteExecuteScalar(ds, false); + return CompleteExecuteScalar(ds, _batchRPCMode); } catch (Exception ex) { @@ -1161,26 +1159,22 @@ public override object ExecuteScalar() } } - private object CompleteExecuteScalar(SqlDataReader ds, bool returnSqlValue) + private object CompleteExecuteScalar(SqlDataReader ds, bool returnLastResult) { object retResult = null; try { - if (ds.Read()) + do { - if (ds.FieldCount > 0) + if (ds.Read()) { - if (returnSqlValue) - { - retResult = ds.GetSqlValue(0); - } - else + if (ds.FieldCount > 0) { retResult = ds.GetValue(0); } } - } + } while (returnLastResult && ds.NextResult()); } finally { @@ -1324,13 +1318,13 @@ private IAsyncResult BeginExecuteNonQueryInternal(CommandBehavior behavior, Asyn // In these cases finalize the call internally and trigger a retry when needed. if ( !TriggerInternalEndAndRetryIfNecessary( - behavior, - stateObject, - timeout, - usedCache, - inRetry, - asyncWrite, - globalCompletion, + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, localCompletion, endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => { @@ -1407,7 +1401,7 @@ private void VerifyEndExecuteState(Task completionTask, string endMethod, bool f { _stateObj.Parser.State = TdsParserState.Broken; // We failed to respond to attention, we have to quit! _stateObj.Parser.Connection.BreakConnection(); - _stateObj.Parser.ThrowExceptionAndWarning(_stateObj); + _stateObj.Parser.ThrowExceptionAndWarning(_stateObj, this); } else { @@ -1610,11 +1604,9 @@ private object InternalEndExecuteNonQuery(IAsyncResult asyncResult, bool isInter { try { - bool dataReady; Debug.Assert(_stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, - out dataReady); - if (!result) + TdsOperationStatus result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -1632,7 +1624,7 @@ private object InternalEndExecuteNonQuery(IAsyncResult asyncResult, bool isInter { // otherwise, use a full-fledged execute that can handle params and stored procs SqlDataReader reader = CompleteAsyncExecuteReader(isInternal); - if (null != reader) + if (reader != null) { reader.Close(); } @@ -1651,7 +1643,7 @@ private object InternalEndExecuteNonQuery(IAsyncResult asyncResult, bool isInter } } - Debug.Assert(null == _stateObj, "non-null state object in EndExecuteNonQuery"); + Debug.Assert(_stateObj == null, "non-null state object in EndExecuteNonQuery"); return _rowsAffected; } @@ -1659,7 +1651,7 @@ private Task InternalExecuteNonQuery(TaskCompletionSource completion, bo { SqlClientEventSource.Log.TryTraceEvent("SqlCommand.InternalExecuteNonQuery | INFO | ObjectId {0}, Client Connection Id {1}, AsyncCommandInProgress={2}", _activeConnection?.ObjectID, _activeConnection?.ClientConnectionId, _activeConnection?.AsyncCommandInProgress); - bool isAsync = (null != completion); + bool isAsync = completion != null; usedCache = false; SqlStatistics statistics = Statistics; @@ -1678,11 +1670,11 @@ private Task InternalExecuteNonQuery(TaskCompletionSource completion, bo // Always Encrypted generally operates only on parameterized queries. However enclave based Always encrypted also supports unparameterized queries // We skip this block for enclave based always encrypted so that we can make a call to SQL Server to get the encryption information - if (!ShouldUseEnclaveBasedWorkflow && !BatchRPCMode && (CommandType.Text == CommandType) && (0 == GetParameterCount(_parameters))) + if (!ShouldUseEnclaveBasedWorkflow && !_batchRPCMode && (CommandType.Text == CommandType) && (0 == GetParameterCount(_parameters))) { Debug.Assert(!sendToPipe, "Trying to send non-context command to pipe"); - if (null != statistics) + if (statistics != null) { if (!IsDirty && IsPrepared) { @@ -1707,7 +1699,7 @@ private Task InternalExecuteNonQuery(TaskCompletionSource completion, bo SqlClientEventSource.Log.TryTraceEvent("SqlCommand.InternalExecuteNonQuery | INFO | Object Id {0}, RPC execute method name {1}, isAsync {2}, inRetry {3}", ObjectID, methodName, isAsync, inRetry); SqlDataReader reader = RunExecuteReader(0, RunBehavior.UntilDone, false, completion, timeout, out task, out usedCache, asyncWrite, inRetry, methodName); - if (null != reader) + if (reader != null) { if (task != null) { @@ -1723,7 +1715,7 @@ private Task InternalExecuteNonQuery(TaskCompletionSource completion, bo } } - Debug.Assert(isAsync || null == _stateObj, "non-null state object in InternalExecuteNonQuery"); + Debug.Assert(isAsync || _stateObj == null, "non-null state object in InternalExecuteNonQuery"); return task; } @@ -1854,13 +1846,13 @@ private IAsyncResult BeginExecuteXmlReaderInternal(CommandBehavior behavior, Asy // In these cases finalize the call internally and trigger a retry when needed. if ( !TriggerInternalEndAndRetryIfNecessary( - behavior, - stateObject, - timeout, - usedCache, - inRetry, - asyncWrite, - globalCompletion, + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, localCompletion, endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => { @@ -2008,9 +2000,9 @@ private XmlReader CompleteXmlReader(SqlDataReader ds, bool isAsync = false) XmlReader xr = null; SmiExtendedMetaData[] md = ds.GetInternalSmiMetaData(); - bool isXmlCapable = (null != md && md.Length == 1 && (md[0].SqlDbType == SqlDbType.NText - || md[0].SqlDbType == SqlDbType.NVarChar - || md[0].SqlDbType == SqlDbType.Xml)); + bool isXmlCapable = (md != null && md.Length == 1 && (md[0].SqlDbType == SqlDbType.NText + || md[0].SqlDbType == SqlDbType.NVarChar + || md[0].SqlDbType == SqlDbType.Xml)); if (isXmlCapable) { @@ -2300,13 +2292,13 @@ private IAsyncResult BeginExecuteReaderInternal(CommandBehavior behavior, AsyncC // In these cases finalize the call internally and trigger a retry when needed. if ( !TriggerInternalEndAndRetryIfNecessary( - behavior, - stateObject, - timeout, - usedCache, - inRetry, - asyncWrite, - globalCompletion, + behavior, + stateObject, + timeout, + usedCache, + inRetry, + asyncWrite, + globalCompletion, localCompletion, endFunc: static (SqlCommand command, IAsyncResult asyncResult, bool isInternal, string endMethod) => { @@ -2448,7 +2440,7 @@ long firstAttemptStart if (!shouldRetry) { // If we cannot retry, Reset the async state to make sure we leave a clean state. - if (null != _cachedAsyncState) + if (_cachedAsyncState != null) { _cachedAsyncState.ResetAsyncState(); } @@ -2571,7 +2563,7 @@ private SqlDataReader InternalEndExecuteReader(IAsyncResult asyncResult, bool is CheckThrowSNIException(); SqlDataReader reader = CompleteAsyncExecuteReader(isInternal); - Debug.Assert(null == _stateObj, "non-null state object in InternalEndExecuteReader"); + Debug.Assert(_stateObj == null, "non-null state object in InternalEndExecuteReader"); return reader; } @@ -2903,7 +2895,81 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo // exception thrown by Dispose... source.SetException(e); } - }, + }, + TaskScheduler.Default + ); + } + _parentOperationStarted = false; + return source.Task; + }, TaskScheduler.Default).Unwrap(); + } + + internal Task ExecuteScalarBatchAsync(CancellationToken cancellationToken) + { + _parentOperationStarted = true; + Guid operationId = s_diagnosticListener.WriteCommandBefore(this, _transaction); + + return ExecuteReaderAsync(cancellationToken).ContinueWith((executeTask) => + { + TaskCompletionSource source = new TaskCompletionSource(); + if (executeTask.IsCanceled) + { + source.SetCanceled(); + } + else if (executeTask.IsFaulted) + { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, executeTask.Exception.InnerException); + source.SetException(executeTask.Exception.InnerException); + } + else + { + SqlDataReader reader = executeTask.Result; + ExecuteScalarUntilEndAsync(reader, cancellationToken).ContinueWith( + (readTask) => + { + try + { + if (readTask.IsCanceled) + { + reader.Dispose(); + source.SetCanceled(); + } + else if (readTask.IsFaulted) + { + reader.Dispose(); + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, readTask.Exception.InnerException); + source.SetException(readTask.Exception.InnerException); + } + else + { + Exception exception = null; + object result = null; + try + { + result = readTask.Result; + } + finally + { + reader.Dispose(); + } + if (exception != null) + { + s_diagnosticListener.WriteCommandError(operationId, this, _transaction, exception); + source.SetException(exception); + } + else + { + s_diagnosticListener.WriteCommandAfter(operationId, this, _transaction); + source.SetResult(result); + } + } + } + catch (Exception e) + { + // exception thrown by Dispose... + source.SetException(e); + } + }, TaskScheduler.Default ); } @@ -2912,6 +2978,20 @@ private Task InternalExecuteScalarAsync(CancellationToken cancellationTo }, TaskScheduler.Default).Unwrap(); } + private async Task ExecuteScalarUntilEndAsync(SqlDataReader reader, CancellationToken cancellationToken) + { + object retval = null; + do + { + if (await reader.ReadAsync(cancellationToken).ConfigureAwait(false) && reader.FieldCount > 0) + { + retval = reader.GetValue(0); // no async untyped value getter, this will work ok as long as the value is in the current packet + } + } + while (_batchRPCMode && !cancellationToken.IsCancellationRequested && await reader.NextResultAsync(cancellationToken).ConfigureAwait(false)); + return retval; + } + /// public Task ExecuteXmlReaderAsync() { @@ -3097,7 +3177,7 @@ internal List GetColumnEncryptionCustomKeyStoreProvidersNames() // with the function below, ideally we should have support from the server for this. private static string UnquoteProcedurePart(string part) { - if ((null != part) && (2 <= part.Length)) + if (part != null && (2 <= part.Length)) { if ('[' == part[0] && ']' == part[part.Length - 1]) { @@ -3117,7 +3197,7 @@ private static string UnquoteProcedureName(string name, out object groupNumber) groupNumber = null; // Out param - initialize value to no value. string sproc = name; - if (null != sproc) + if (sproc != null) { if (char.IsDigit(sproc[sproc.Length - 1])) { // If last char is a digit, parse. @@ -3216,7 +3296,7 @@ internal void DeriveParameters() // Use common parser for SqlClient and OleDb - parse into 4 parts - Server, Catalog, Schema, ProcedureName string[] parsedSProc = MultipartIdentifier.ParseMultipartIdentifier(CommandText, "[\"", "]\"", Strings.SQL_SqlCommandCommandText, false); - if (null == parsedSProc[3] || string.IsNullOrEmpty(parsedSProc[3])) + if (string.IsNullOrEmpty(parsedSProc[3])) { throw ADP.NoStoredProcedureExists(CommandText); } @@ -3281,7 +3361,7 @@ internal void DeriveParameters() paramsCmd.Parameters.Add(new SqlParameter("@procedure_name", SqlDbType.NVarChar, 255)); paramsCmd.Parameters[0].Value = UnquoteProcedureName(parsedSProc[3], out groupNumber); // ProcedureName is 4rd element in parsed array - if (null != groupNumber) + if (groupNumber != null) { SqlParameter param = paramsCmd.Parameters.Add(new SqlParameter("@group_number", SqlDbType.Int)); param.Value = groupNumber; @@ -3505,11 +3585,11 @@ private void CheckNotificationStateAndAutoEnlist() // There is a variance in order between Start(), SqlDependency(), and Execute. This is the // best way to solve that problem. - if (null != Notification) + if (Notification != null) { if (_sqlDep != null) { - if (null == _sqlDep.Options) + if (_sqlDep.Options == null) { // If null, SqlDependency was not created with options, so we need to obtain default options now. // GetDefaultOptions can and will throw under certain conditions. @@ -3597,11 +3677,12 @@ private Task RunExecuteNonQueryTds(string methodName, bool isAsync, int timeout, } else { - bool dataReady; Debug.Assert(_stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, out dataReady); - if (!result) - { throw SQL.SynchronousCallMayNotPend(); } + TdsOperationStatus result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } } catch (Exception e) @@ -3718,7 +3799,7 @@ private void PrepareTransparentEncryptionFinallyBlock(bool closeDataReader, if (closeDataReader) { // Close the data reader to reset the _stateObj - if (null != describeParameterEncryptionDataReader) + if (describeParameterEncryptionDataReader != null) { describeParameterEncryptionDataReader.Close(); } @@ -3759,7 +3840,7 @@ private void PrepareForTransparentEncryption(CommandBehavior cmdBehavior, bool r // If we are not in Batch RPC and not already retrying, attempt to fetch the cipher MD for each parameter from the cache. // If this succeeds then return immediately, otherwise just fall back to the full crypto MD discovery. - if (!BatchRPCMode && !inRetry && (this._parameters != null && this._parameters.Count > 0) && SqlQueryMetadataCache.GetInstance().GetQueryMetadataIfExists(this)) + if (!_batchRPCMode && !inRetry && (this._parameters != null && this._parameters.Count > 0) && SqlQueryMetadataCache.GetInstance().GetQueryMetadataIfExists(this)) { usedCache = true; return; @@ -3774,7 +3855,7 @@ private void PrepareForTransparentEncryption(CommandBehavior cmdBehavior, bool r // Flag to indicate if exception is caught during the execution, to govern clean up. bool exceptionCaught = false; - // Used in BatchRPCMode to maintain a map of describe parameter encryption RPC requests (Keys) and their corresponding original RPC requests (Values). + // Used in _batchRPCMode to maintain a map of describe parameter encryption RPC requests (Keys) and their corresponding original RPC requests (Values). ReadOnlyDictionary<_SqlRPC, _SqlRPC> describeParameterEncryptionRpcOriginalRpcMap = null; @@ -3797,16 +3878,16 @@ private void PrepareForTransparentEncryption(CommandBehavior cmdBehavior, bool r Debug.Assert(fetchInputParameterEncryptionInfoTask == null || isAsync, "Task returned by TryFetchInputParameterEncryptionInfo, when in sync mode, in PrepareForTransparentEncryption."); - Debug.Assert((describeParameterEncryptionRpcOriginalRpcMap != null) == BatchRPCMode, - "describeParameterEncryptionRpcOriginalRpcMap can be non-null if and only if it is in BatchRPCMode."); + Debug.Assert((describeParameterEncryptionRpcOriginalRpcMap != null) == _batchRPCMode, + "describeParameterEncryptionRpcOriginalRpcMap can be non-null if and only if it is in _batchRPCMode."); // If we didn't have parameters, we can fall back to regular code path, by simply returning. if (!describeParameterEncryptionNeeded) { - Debug.Assert(null == fetchInputParameterEncryptionInfoTask, + Debug.Assert(fetchInputParameterEncryptionInfoTask == null, "fetchInputParameterEncryptionInfoTask should not be set if describe parameter encryption is not needed."); - Debug.Assert(null == describeParameterEncryptionDataReader, + Debug.Assert(describeParameterEncryptionDataReader == null, "SqlDataReader created for describe parameter encryption params when it is not needed."); return; @@ -3912,7 +3993,7 @@ private SqlDataReader GetParameterEncryptionDataReader(out Task returnTask, Task SqlCommand command = (SqlCommand)state; bool processFinallyBlockAsync = true; bool decrementAsyncCountInFinallyBlockAsync = true; -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -3931,7 +4012,7 @@ private SqlDataReader GetParameterEncryptionDataReader(out Task returnTask, Task // Complete executereader. describeParameterEncryptionDataReader = command.CompleteAsyncExecuteReader(forDescribeParameterEncryption: true); - Debug.Assert(null == command._stateObj, "non-null state object in PrepareForTransparentEncryption."); + Debug.Assert(command._stateObj == null, "non-null state object in PrepareForTransparentEncryption."); // Read the results of describe parameter encryption. command.ReadDescribeEncryptionParameterResults(describeParameterEncryptionDataReader, describeParameterEncryptionRpcOriginalRpcMap, inRetry); @@ -3986,7 +4067,7 @@ private SqlDataReader GetParameterEncryptionDataReaderAsync(out Task returnTask, bool processFinallyBlockAsync = true; bool decrementAsyncCountInFinallyBlockAsync = true; -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -4005,7 +4086,7 @@ private SqlDataReader GetParameterEncryptionDataReaderAsync(out Task returnTask, // Complete executereader. describeParameterEncryptionDataReader = CompleteAsyncExecuteReader(forDescribeParameterEncryption: true); - Debug.Assert(null == _stateObj, "non-null state object in PrepareForTransparentEncryption."); + Debug.Assert(_stateObj == null, "non-null state object in PrepareForTransparentEncryption."); // Read the results of describe parameter encryption. ReadDescribeEncryptionParameterResults(describeParameterEncryptionDataReader, @@ -4077,32 +4158,32 @@ private SqlDataReader TryFetchInputParameterEncryptionInfo(int timeout, } } - if (BatchRPCMode) + if (_batchRPCMode) { // Count the rpc requests that need to be transparently encrypted // We simply look for any parameters in a request and add the request to be queried for parameter encryption Dictionary<_SqlRPC, _SqlRPC> describeParameterEncryptionRpcOriginalRpcDictionary = new Dictionary<_SqlRPC, _SqlRPC>(); - for (int i = 0; i < _SqlRPCBatchArray.Length; i++) + for (int i = 0; i < _RPCList.Count; i++) { // In BatchRPCMode, the actual T-SQL query is in the first parameter and not present as the rpcName, as is the case with non-BatchRPCMode. // So input parameters start at parameters[1]. parameters[0] is the actual T-SQL Statement. rpcName is sp_executesql. - if (_SqlRPCBatchArray[i].systemParams.Length > 1) + if (_RPCList[i].systemParams.Length > 1) { - _SqlRPCBatchArray[i].needsFetchParameterEncryptionMetadata = true; + _RPCList[i].needsFetchParameterEncryptionMetadata = true; // Since we are going to need multiple RPC objects, allocate a new one here for each command in the batch. _SqlRPC rpcDescribeParameterEncryptionRequest = new _SqlRPC(); // Prepare the describe parameter encryption request. - PrepareDescribeParameterEncryptionRequest(_SqlRPCBatchArray[i], ref rpcDescribeParameterEncryptionRequest, i == 0 ? serializedAttestationParameters : null); + PrepareDescribeParameterEncryptionRequest(_RPCList[i], ref rpcDescribeParameterEncryptionRequest, i == 0 ? serializedAttestationParameters : null); Debug.Assert(rpcDescribeParameterEncryptionRequest != null, "rpcDescribeParameterEncryptionRequest should not be null, after call to PrepareDescribeParameterEncryptionRequest."); Debug.Assert(!describeParameterEncryptionRpcOriginalRpcDictionary.ContainsKey(rpcDescribeParameterEncryptionRequest), "There should not already be a key referring to the current rpcDescribeParameterEncryptionRequest, in the dictionary describeParameterEncryptionRpcOriginalRpcDictionary."); // Add the describe parameter encryption RPC request as the key and its corresponding original rpc request to the dictionary. - describeParameterEncryptionRpcOriginalRpcDictionary.Add(rpcDescribeParameterEncryptionRequest, _SqlRPCBatchArray[i]); + describeParameterEncryptionRpcOriginalRpcDictionary.Add(rpcDescribeParameterEncryptionRequest, _RPCList[i]); } } @@ -4122,7 +4203,7 @@ private SqlDataReader TryFetchInputParameterEncryptionInfo(int timeout, describeParameterEncryptionRpcOriginalRpcMap.Keys.CopyTo(_sqlRPCParameterEncryptionReqArray, 0); Debug.Assert(_sqlRPCParameterEncryptionReqArray.Length > 0, "There should be at-least 1 describe parameter encryption rpc request."); - Debug.Assert(_sqlRPCParameterEncryptionReqArray.Length <= _SqlRPCBatchArray.Length, + Debug.Assert(_sqlRPCParameterEncryptionReqArray.Length <= _RPCList.Count, "The number of decribe parameter encryption RPC requests is more than the number of original RPC requests."); } //Always Encrypted generally operates only on parameterized queries. However enclave based Always encrypted also supports unparameterized queries @@ -4193,11 +4274,11 @@ private void PrepareDescribeParameterEncryptionRequest(_SqlRPC originalRpcReques // Prepare @tsql parameter string text; - // In BatchRPCMode, The actual T-SQL query is in the first parameter and not present as the rpcName, as is the case with non-BatchRPCMode. - if (BatchRPCMode) + // In _batchRPCMode, The actual T-SQL query is in the first parameter and not present as the rpcName, as is the case with non-_batchRPCMode. + if (_batchRPCMode) { Debug.Assert(originalRpcRequest.systemParamCount > 0, - "originalRpcRequest didn't have at-least 1 parameter in BatchRPCMode, in PrepareDescribeParameterEncryptionRequest."); + "originalRpcRequest didn't have at-least 1 parameter in _batchRPCMode, in PrepareDescribeParameterEncryptionRequest."); text = (string)originalRpcRequest.systemParams[0].Value; //@tsql SqlParameter tsqlParam = describeParameterEncryptionRequest.systemParams[0]; @@ -4231,7 +4312,7 @@ private void PrepareDescribeParameterEncryptionRequest(_SqlRPC originalRpcReques // In BatchRPCMode, the input parameters start at parameters[1]. parameters[0] is the T-SQL statement. rpcName is sp_executesql. // And it is already in the format expected out of BuildParamList, which is not the case with Non-BatchRPCMode. - if (BatchRPCMode) + if (_batchRPCMode) { // systemParamCount == 2 when user parameters are supplied to BuildExecuteSql if (originalRpcRequest.systemParamCount > 1) @@ -4324,8 +4405,8 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi SqlTceCipherInfoEntry cipherInfoEntry; Dictionary columnEncryptionKeyTable = new Dictionary(); - Debug.Assert((describeParameterEncryptionRpcOriginalRpcMap != null) == BatchRPCMode, - "describeParameterEncryptionRpcOriginalRpcMap should be non-null if and only if it is BatchRPCMode."); + Debug.Assert((describeParameterEncryptionRpcOriginalRpcMap != null) == _batchRPCMode, + "describeParameterEncryptionRpcOriginalRpcMap should be non-null if and only if it is _batchRPCMode."); // Indicates the current result set we are reading, used in BatchRPCMode, where we can have more than 1 result set. int resultSetSequenceNumber = 0; @@ -4341,12 +4422,12 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi do { - if (BatchRPCMode) + if (_batchRPCMode) { // If we got more RPC results from the server than what was requested. if (resultSetSequenceNumber >= _sqlRPCParameterEncryptionReqArray.Length) { - Debug.Assert(false, "Server sent back more results than what was expected for describe parameter encryption requests in BatchRPCMode."); + Debug.Assert(false, "Server sent back more results than what was expected for describe parameter encryption requests in _batchRPCMode."); // Ignore the rest of the results from the server, if for whatever reason it sends back more than what we expect. break; } @@ -4463,7 +4544,7 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi // Find the RPC command that generated this tce request - if (BatchRPCMode) + if (_batchRPCMode) { Debug.Assert(_sqlRPCParameterEncryptionReqArray[resultSetSequenceNumber] != null, "_sqlRPCParameterEncryptionReqArray[resultSetSequenceNumber] should not be null."); @@ -4485,7 +4566,7 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi Debug.Assert(rpc != null, "rpc should not be null here."); int userParamCount = rpc.userParams?.Count ?? 0; - int recievedMetadataCount = 0; + int receivedMetadataCount = 0; if (!enclaveMetadataExists || ds.NextResult()) { @@ -4506,11 +4587,11 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi SqlParameter sqlParameter = rpc.userParams[index]; Debug.Assert(sqlParameter != null, "sqlParameter should not be null."); - if (SqlParameter.ParameterNamesEqual(sqlParameter.ParameterName,parameterName,StringComparison.Ordinal)) + if (SqlParameter.ParameterNamesEqual(sqlParameter.ParameterName, parameterName, StringComparison.Ordinal)) { Debug.Assert(sqlParameter.CipherMetadata == null, "param.CipherMetadata should be null."); sqlParameter.HasReceivedMetadata = true; - recievedMetadataCount += 1; + receivedMetadataCount += 1; // Found the param, setup the encryption info. byte columnEncryptionType = ds.GetByte((int)DescribeParameterEncryptionResultSet2.ColumnEncryptionType); if ((byte)SqlClientEncryptionType.PlainText != columnEncryptionType) @@ -4536,8 +4617,8 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi Debug.Assert(_activeConnection != null, @"_activeConnection should not be null"); SqlSecurityUtility.DecryptSymmetricKey(sqlParameter.CipherMetadata, _activeConnection, this); - // This is effective only for BatchRPCMode even though we set it for non-BatchRPCMode also, - // since for non-BatchRPCMode mode, paramoptions gets thrown away and reconstructed in BuildExecuteSql. + // This is effective only for _batchRPCMode even though we set it for non-_batchRPCMode also, + // since for non-_batchRPCMode mode, paramoptions gets thrown away and reconstructed in BuildExecuteSql. int options = (int)(rpc.userParamMap[index] >> 32); options |= TdsEnums.RPC_PARAM_ENCRYPTED; rpc.userParamMap[index] = ((((long)options) << 32) | (long)index); @@ -4552,7 +4633,7 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi // When the RPC object gets reused, the parameter array has more parameters that the valid params for the command. // Null is used to indicate the end of the valid part of the array. Refer to GetRPCObject(). - if (recievedMetadataCount != userParamCount) + if (receivedMetadataCount != userParamCount) { for (int index = 0; index < userParamCount; index++) { @@ -4621,19 +4702,19 @@ private void ReadDescribeEncryptionParameterResults(SqlDataReader ds, ReadOnlyDi } while (ds.NextResult()); // Verify that we received response for each rpc call needs tce - if (BatchRPCMode) + if (_batchRPCMode) { - for (int i = 0; i < _SqlRPCBatchArray.Length; i++) + for (int i = 0; i < _RPCList.Count; i++) { - if (_SqlRPCBatchArray[i].needsFetchParameterEncryptionMetadata) + if (_RPCList[i].needsFetchParameterEncryptionMetadata) { - throw SQL.ProcEncryptionMetadataMissing(_SqlRPCBatchArray[i].rpcName); + throw SQL.ProcEncryptionMetadataMissing(_RPCList[i].rpcName); } } } // If we are not in Batch RPC mode, update the query cache with the encryption MD. - if (!BatchRPCMode && ShouldCacheEncryptionMetadata && (_parameters is not null && _parameters.Count > 0)) + if (!_batchRPCMode && ShouldCacheEncryptionMetadata && (_parameters is not null && _parameters.Count > 0)) { SqlQueryMetadataCache.GetInstance().AddQueryMetadata(this, ignoreQueriesWithReturnValueParams: true); } @@ -4650,7 +4731,7 @@ internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior // task is created in case of pending asynchronous write, returned SqlDataReader should not be utilized until that task is complete internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, TaskCompletionSource completion, int timeout, out Task task, out bool usedCache, bool asyncWrite = false, bool inRetry = false, [CallerMemberName] string method = "") { - bool isAsync = (null != completion); + bool isAsync = completion != null; usedCache = false; task = null; @@ -4674,7 +4755,7 @@ internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior CheckNotificationStateAndAutoEnlist(); // Only call after validate - requires non null connection! SqlStatistics statistics = Statistics; - if (null != statistics) + if (statistics != null) { if ((!this.IsDirty && this.IsPrepared && !_hiddenPrepare) || (this.IsPrepared && _execType == EXECTYPE.PREPAREPENDING)) @@ -4837,7 +4918,7 @@ private void GenerateEnclavePackage() return; } - if (string.IsNullOrWhiteSpace(this._activeConnection.EnclaveAttestationUrl) && + if (string.IsNullOrWhiteSpace(this._activeConnection.EnclaveAttestationUrl) && Connection.AttestationProtocol != SqlConnectionAttestationProtocol.None) { throw SQL.NoAttestationUrlSpecifiedForEnclaveBasedQueryGeneratingEnclavePackage(this._activeConnection.Parser.EnclaveType); @@ -4908,7 +4989,7 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi // make sure we have good parameter information // prepare the command // execute - Debug.Assert(null != _activeConnection.Parser, "TdsParser class should not be null in Command.Execute!"); + Debug.Assert(_activeConnection.Parser != null, "TdsParser class should not be null in Command.Execute!"); bool inSchema = (0 != (cmdBehavior & CommandBehavior.SchemaOnly)); @@ -4949,13 +5030,13 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi Debug.Assert(_sqlRPCParameterEncryptionReqArray != null, "RunExecuteReader rpc array not provided for describe parameter encryption request."); writeTask = _stateObj.Parser.TdsExecuteRPC(this, _sqlRPCParameterEncryptionReqArray, timeout, inSchema, this.Notification, _stateObj, CommandType.StoredProcedure == CommandType, sync: !asyncWrite); } - else if (BatchRPCMode) + else if (_batchRPCMode) { Debug.Assert(inSchema == false, "Batch RPC does not support schema only command behavior"); Debug.Assert(!IsPrepared, "Batch RPC should not be prepared!"); Debug.Assert(!IsDirty, "Batch RPC should not be marked as dirty!"); - Debug.Assert(_SqlRPCBatchArray != null, "RunExecuteReader rpc array not provided"); - writeTask = _stateObj.Parser.TdsExecuteRPC(this, _SqlRPCBatchArray, timeout, inSchema, this.Notification, _stateObj, CommandType.StoredProcedure == CommandType, sync: !asyncWrite); + Debug.Assert(_RPCList != null, "RunExecuteReader rpc array not provided"); + writeTask = _stateObj.Parser.TdsExecuteRPC(this, _RPCList, timeout, inSchema, this.Notification, _stateObj, CommandType.StoredProcedure == CommandType, sync: !asyncWrite); } else if ((CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) { @@ -5048,14 +5129,16 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi } // turn set options ON - if (null != optionSettings) + if (optionSettings != null) { Task executeTask = _stateObj.Parser.TdsExecuteSQLBatch(optionSettings, timeout, this.Notification, _stateObj, sync: true); Debug.Assert(executeTask == null, "Shouldn't get a task when doing sync writes"); Debug.Assert(_stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, out bool dataReady); - if (!result) - { throw SQL.SynchronousCallMayNotPend(); } + TdsOperationStatus result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, null, null, _stateObj, out bool dataReady); + if (result != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } // and turn OFF when the ds exhausts the stream on Close() optionSettings = GetResetOptionsString(cmdBehavior); } @@ -5091,7 +5174,7 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi if (decrementAsyncCountOnFailure) { SqlInternalConnectionTds innerConnectionTds = (_activeConnection.InnerConnection as SqlInternalConnectionTds); - if (null != innerConnectionTds) + if (innerConnectionTds != null) { // it may be closed innerConnectionTds.DecrementAsyncCount(); } @@ -5107,7 +5190,7 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi } } - Debug.Assert(isAsync || null == _stateObj, "non-null state object in RunExecuteReader"); + Debug.Assert(isAsync || _stateObj == null, "non-null state object in RunExecuteReader"); return ds; } @@ -5211,11 +5294,12 @@ private void FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, stri { try { - bool dataReady; Debug.Assert(_stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, ds, null, _stateObj, out dataReady); - if (!result) - { throw SQL.SynchronousCallMayNotPend(); } + TdsOperationStatus result = _stateObj.Parser.TryRun(RunBehavior.UntilDone, this, ds, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } catch (Exception e) { @@ -5231,7 +5315,7 @@ private void FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, stri _execType = EXECTYPE.PREPAREPENDING; // reset execution type to pending } - if (null != ds) + if (ds != null) { try { @@ -5324,7 +5408,7 @@ private Task RegisterForConnectionCloseNotification(Task outerTask) // throws exception for error case, returns false if the commandText is empty private void ValidateCommand(bool isAsync, [CallerMemberName] string method = "") { - if (null == _activeConnection) + if (_activeConnection == null) { throw ADP.ConnectionRequired(method); } @@ -5335,8 +5419,8 @@ private void ValidateCommand(bool isAsync, [CallerMemberName] string method = "" // Ensure that if column encryption override was used then server supports its if (((SqlCommandColumnEncryptionSetting.UseConnectionSetting == ColumnEncryptionSetting && _activeConnection.IsColumnEncryptionSettingEnabled) || (ColumnEncryptionSetting == SqlCommandColumnEncryptionSetting.Enabled || ColumnEncryptionSetting == SqlCommandColumnEncryptionSetting.ResultSetOnly)) - && null != tdsConnection - && null != tdsConnection.Parser + && tdsConnection != null + && tdsConnection.Parser != null && !tdsConnection.Parser.IsColumnEncryptionSupported) { throw SQL.TceNotSupported(); @@ -5370,22 +5454,30 @@ private void ValidateCommand(bool isAsync, [CallerMemberName] string method = "" _activeConnection.ValidateConnectionForExecute(method, this); // Check to see if the currently set transaction has completed. If so, // null out our local reference. - if (null != _transaction && _transaction.Connection == null) + if (_transaction != null && _transaction.Connection == null) + { _transaction = null; + } // throw if the connection is in a transaction but there is no // locally assigned transaction object - if (_activeConnection.HasLocalTransactionFromAPI && (null == _transaction)) + if (_activeConnection.HasLocalTransactionFromAPI && _transaction == null) + { throw ADP.TransactionRequired(method); + } // if we have a transaction, check to ensure that the active // connection property matches the connection associated with // the transaction - if (null != _transaction && _activeConnection != _transaction.Connection) + if (_transaction != null && _activeConnection != _transaction.Connection) + { throw ADP.TransactionConnectionMismatch(); + } if (string.IsNullOrEmpty(this.CommandText)) + { throw ADP.CommandTextRequired(method); + } } private void ValidateAsyncCommand() @@ -5406,8 +5498,8 @@ private void ValidateAsyncCommand() private void GetStateObject(TdsParser parser = null) { - Debug.Assert(null == _stateObj, "StateObject not null on GetStateObject"); - Debug.Assert(null != _activeConnection, "no active connection?"); + Debug.Assert(_stateObj == null, "StateObject not null on GetStateObject"); + Debug.Assert(_activeConnection != null, "no active connection?"); if (_pendingCancel) { @@ -5458,7 +5550,7 @@ private void PutStateObject() TdsParserStateObject stateObj = _stateObj; _stateObj = null; - if (null != stateObj) + if (stateObj != null) { stateObj.CloseSession(); } @@ -5467,28 +5559,28 @@ private void PutStateObject() internal void OnDoneDescribeParameterEncryptionProc(TdsParserStateObject stateObj) { // called per rpc batch complete - if (BatchRPCMode) + if (_batchRPCMode) { OnDone(stateObj, _currentlyExecutingDescribeParameterEncryptionRPC, _sqlRPCParameterEncryptionReqArray, _rowsAffected); _currentlyExecutingDescribeParameterEncryptionRPC++; } } - internal void OnDoneProc() + internal void OnDoneProc(TdsParserStateObject stateObject) { // called per rpc batch complete - if (BatchRPCMode) + if (_batchRPCMode) { - OnDone(_stateObj, _currentlyExecutingBatch, _SqlRPCBatchArray, _rowsAffected); + OnDone(stateObject, _currentlyExecutingBatch, _RPCList, _rowsAffected); _currentlyExecutingBatch++; - Debug.Assert(_parameterCollectionList.Count >= _currentlyExecutingBatch, "OnDoneProc: Too many DONEPROC events"); + Debug.Assert(_RPCList.Count >= _currentlyExecutingBatch, "OnDoneProc: Too many DONEPROC events"); } } - private static void OnDone(TdsParserStateObject stateObj, int index, _SqlRPC[] array, int rowsAffected) + private static void OnDone(TdsParserStateObject stateObj, int index, IList<_SqlRPC> rpcList, int rowsAffected) { - _SqlRPC current = array[index]; - _SqlRPC previous = (index > 0) ? array[index - 1] : null; + _SqlRPC current = rpcList[index]; + _SqlRPC previous = (index > 0) ? rpcList[index - 1] : null; // track the records affected for the just completed rpc batch // _rowsAffected is cumulative for ExecuteNonQuery across all rpc batches @@ -5499,6 +5591,11 @@ private static void OnDone(TdsParserStateObject stateObj, int index, _SqlRPC[] a ? (rowsAffected - Math.Max(previous.cumulativeRecordsAffected, 0)) : rowsAffected); + if (current.batchCommand != null) + { + current.batchCommand.SetRecordAffected(current.recordsAffected.GetValueOrDefault()); + } + // track the error collection (not available from TdsParser after ExecuteNonQuery) // and the which errors are associated with the just completed rpc batch current.errorsIndexStart = previous?.errorsIndexEnd ?? 0; @@ -5521,11 +5618,11 @@ internal void OnReturnStatus(int status) } SqlParameterCollection parameters = _parameters; - if (BatchRPCMode) + if (_batchRPCMode) { - if (_parameterCollectionList.Count > _currentlyExecutingBatch) + if (_RPCList.Count > _currentlyExecutingBatch) { - parameters = _parameterCollectionList[_currentlyExecutingBatch]; + parameters = _RPCList[_currentlyExecutingBatch].userParams; } else { @@ -5543,7 +5640,7 @@ internal void OnReturnStatus(int status) object v = parameter.Value; // if the user bound a sqlint32 (the only valid one for status, use it) - if ((null != v) && (v.GetType() == typeof(SqlInt32))) + if (v != null && (v.GetType() == typeof(SqlInt32))) { parameter.Value = new SqlInt32(status); // value type } @@ -5555,7 +5652,7 @@ internal void OnReturnStatus(int status) // If we are not in Batch RPC mode, update the query cache with the encryption MD. // We can do this now that we have distinguished between ReturnValue and ReturnStatus. // Read comment in AddQueryMetadata() for more details. - if (!BatchRPCMode && CachingQueryMetadataPostponed && + if (!_batchRPCMode && CachingQueryMetadataPostponed && ShouldCacheEncryptionMetadata && (_parameters is not null && _parameters.Count > 0)) { SqlQueryMetadataCache.GetInstance().AddQueryMetadata(this, ignoreQueriesWithReturnValueParams: false); @@ -5589,7 +5686,7 @@ internal void OnReturnValue(SqlReturnValue rec, TdsParserStateObject stateObj) SqlParameter thisParam = GetParameterForOutputValueExtraction(parameters, rec.parameter, count); - if (null != thisParam) + if (thisParam != null) { // If the parameter's direction is InputOutput, Output or ReturnValue and it needs to be transparently encrypted/decrypted // then simply decrypt, deserialize and set the value. @@ -5709,7 +5806,7 @@ internal void OnReturnValue(SqlReturnValue rec, TdsParserStateObject stateObj) else if (rec.type == SqlDbType.Xml) { SqlCachedBuffer cachedBuffer = (thisParam.Value as SqlCachedBuffer); - if (null != cachedBuffer) + if (cachedBuffer != null) { thisParam.Value = cachedBuffer.ToString(); } @@ -5728,11 +5825,11 @@ internal void OnReturnValue(SqlReturnValue rec, TdsParserStateObject stateObj) private SqlParameterCollection GetCurrentParameterCollection() { - if (BatchRPCMode) + if (_batchRPCMode) { - if (_parameterCollectionList.Count > _currentlyExecutingBatch) + if (_RPCList.Count > _currentlyExecutingBatch) { - return _parameterCollectionList[_currentlyExecutingBatch]; + return _RPCList[_currentlyExecutingBatch].userParams; } else { @@ -5752,7 +5849,7 @@ private SqlParameter GetParameterForOutputValueExtraction(SqlParameterCollection SqlParameter thisParam = null; bool foundParam = false; - if (null == paramName) + if (paramName == null) { // rec.parameter should only be null for a return value from a function for (int i = 0; i < paramCount; i++) @@ -5773,9 +5870,9 @@ private SqlParameter GetParameterForOutputValueExtraction(SqlParameterCollection thisParam = parameters[i]; // searching for Output or InputOutput or ReturnValue with matching name if ( - thisParam.Direction != ParameterDirection.Input && - thisParam.Direction != ParameterDirection.ReturnValue && - SqlParameter.ParameterNamesEqual(paramName, thisParam.ParameterName,StringComparison.Ordinal) + thisParam.Direction != ParameterDirection.Input && + thisParam.Direction != ParameterDirection.ReturnValue && + SqlParameter.ParameterNamesEqual(paramName, thisParam.ParameterName, StringComparison.Ordinal) ) { foundParam = true; @@ -5881,12 +5978,12 @@ private void SetUpRPCParameters(_SqlRPC rpc, bool inSchema, SqlParameterCollecti // set default value bit if (parameter.Direction != ParameterDirection.Output) { - // remember that null == Convert.IsEmpty, DBNull.Value is a database null! + // remember that Convert.IsEmpty is null, DBNull.Value is a database null! // Don't assume a default value exists for parameters in the case when // the user is simply requesting schema. // TVPs use DEFAULT and do not allow NULL, even for schema only. - if (null == parameter.Value && (!inSchema || SqlDbType.Structured == parameter.SqlDbType)) + if (parameter.Value == null && (!inSchema || SqlDbType.Structured == parameter.SqlDbType)) { options |= TdsEnums.RPC_PARAM_DEFAULT; } @@ -5983,7 +6080,7 @@ private static bool ShouldSendParameter(SqlParameter p, bool includeReturnValue } } - private int CountSendableParameters(SqlParameterCollection parameters) + private static int CountSendableParameters(SqlParameterCollection parameters) { int cParams = 0; @@ -6002,9 +6099,9 @@ private int CountSendableParameters(SqlParameterCollection parameters) } // Returns total number of parameters - private int GetParameterCount(SqlParameterCollection parameters) + private static int GetParameterCount(SqlParameterCollection parameters) { - return (null != parameters) ? parameters.Count : 0; + return parameters != null ? parameters.Count : 0; } // @@ -6105,7 +6202,7 @@ private void BuildExecuteSql(CommandBehavior behavior, string commandText, SqlPa if (userParamCount > 0) { - string paramList = BuildParamList(_stateObj.Parser, BatchRPCMode ? parameters : _parameters); + string paramList = BuildParamList(_stateObj.Parser, _batchRPCMode ? parameters : _parameters); sqlParam = rpc.systemParams[1]; sqlParam.SqlDbType = ((paramList.Length << 1) <= TdsEnums.TYPE_SIZE_LIMIT) ? SqlDbType.NVarChar : SqlDbType.NText; sqlParam.Size = paramList.Length; @@ -6339,10 +6436,10 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete string s = null; // deal with the sql types - if ((null != val) && (DBNull.Value != val)) + if (val != null && (DBNull.Value != val)) { s = (val as string); - if (null == s) + if (s == null) { SqlString sval = val is SqlString ? (SqlString)val : SqlString.Null; if (!sval.IsNull) @@ -6352,7 +6449,7 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete } } - if (null != s) + if (s != null) { int actualBytes = parser.GetEncodingCharLength(s, sqlParam.GetActualSize(), sqlParam.Offset, null); // if actual number of bytes is greater than the user given number of chars, use actual bytes @@ -6369,7 +6466,7 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete paramList.Append(size); paramList.Append(')'); } - else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt)) + else if (mt.IsPlp && (mt.SqlDbType != SqlDbType.Xml) && (mt.SqlDbType != SqlDbType.Udt) && (mt.SqlDbType != SqlDbTypeExtensions.Json)) { paramList.Append("(max) "); } @@ -6404,7 +6501,7 @@ private static string QuoteIdentifier(ReadOnlySpan strings) { bld.Append('.'); } - if (null != strings[i] && 0 != strings[i].Length) + if (strings[i] != null && 0 != strings[i].Length) { ADP.AppendQuotedString(bld, "[", "]", strings[i]); } @@ -6523,7 +6620,7 @@ internal bool IsDirty // only mark the command as dirty if it is already prepared // but always clear the value if it we are clearing the dirty flag _dirty = value ? IsPrepared : false; - if (null != _parameters) + if (_parameters != null) { _parameters.IsDirty = _dirty; } @@ -6586,48 +6683,35 @@ private void ClearDescribeParameterEncryptionRequests() internal void ClearBatchCommand() { - List<_SqlRPC> rpcList = _RPCList; - if (null != rpcList) - { - rpcList.Clear(); - } - if (null != _parameterCollectionList) - { - _parameterCollectionList.Clear(); - } - - _SqlRPCBatchArray = null; + _RPCList?.Clear(); _currentlyExecutingBatch = 0; } - internal bool BatchRPCMode + internal void SetBatchRPCMode(bool value, int commandCount = 1) { - get + _batchRPCMode = value; + ClearBatchCommand(); + if (_batchRPCMode) { - return _batchRPCMode; - } - set - { - _batchRPCMode = value; - - if (_batchRPCMode == false) + if (_RPCList == null) { - ClearBatchCommand(); + _RPCList = new List<_SqlRPC>(commandCount); } else { - if (_RPCList == null) - { - _RPCList = new List<_SqlRPC>(); - } - if (_parameterCollectionList == null) - { - _parameterCollectionList = new List(); - } + _RPCList.Capacity = commandCount; } } } + internal void SetBatchRPCModeReadyToExecute() + { + Debug.Assert(_batchRPCMode, "Command is not in batch RPC Mode"); + Debug.Assert(_RPCList != null, "No batch commands specified"); + + _currentlyExecutingBatch = 0; + } + /// /// Set the column encryption setting to the new one. /// Do not allow conflicting column encryption settings. @@ -6645,71 +6729,86 @@ private void SetColumnEncryptionSetting(SqlCommandColumnEncryptionSetting newCol } } - internal void AddBatchCommand(string commandText, SqlParameterCollection parameters, CommandType cmdType, SqlCommandColumnEncryptionSetting columnEncryptionSetting) + internal void AddBatchCommand(SqlBatchCommand batchCommand) { - Debug.Assert(BatchRPCMode, "Command is not in batch RPC Mode"); + Debug.Assert(_batchRPCMode, "Command is not in batch RPC Mode"); Debug.Assert(_RPCList != null); - Debug.Assert(_parameterCollectionList != null); - _SqlRPC rpc = new _SqlRPC(); + _SqlRPC rpc = new _SqlRPC + { + batchCommand = batchCommand + }; + string commandText = batchCommand.CommandText; + CommandType cmdType = batchCommand.CommandType; CommandText = commandText; CommandType = cmdType; // Set the column encryption setting. - SetColumnEncryptionSetting(columnEncryptionSetting); + SetColumnEncryptionSetting(batchCommand.ColumnEncryptionSetting); GetStateObject(); if (cmdType == CommandType.StoredProcedure) { - BuildRPC(false, parameters, ref rpc); + BuildRPC(false, batchCommand.Parameters, ref rpc); } else { // All batch sql statements must be executed inside sp_executesql, including those without parameters - BuildExecuteSql(CommandBehavior.Default, commandText, parameters, ref rpc); + BuildExecuteSql(CommandBehavior.Default, commandText, batchCommand.Parameters, ref rpc); } _RPCList.Add(rpc); - // Always add a parameters collection per RPC, even if there are no parameters. - _parameterCollectionList.Add(parameters); ReliablePutStateObject(); } - internal int ExecuteBatchRPCCommand() + internal int? GetRecordsAffected(int commandIndex) { - Debug.Assert(BatchRPCMode, "Command is not in batch RPC Mode"); - Debug.Assert(_RPCList != null, "No batch commands specified"); + Debug.Assert(_batchRPCMode, "Command is not in batch RPC Mode"); + Debug.Assert(_RPCList != null, "batch command have been cleared"); + return _RPCList[commandIndex].recordsAffected; + } - _SqlRPCBatchArray = _RPCList.ToArray(); - _currentlyExecutingBatch = 0; - return ExecuteNonQuery(); // Check permissions, execute, return output params + internal SqlBatchCommand GetCurrentBatchCommand() + { + if (_batchRPCMode) + { + return _RPCList[_currentlyExecutingBatch].batchCommand; + } + else + { + return _rpcArrayOf1?[0].batchCommand; + } } - internal int? GetRecordsAffected(int commandIndex) + internal SqlBatchCommand GetBatchCommand(int index) + { + return _RPCList[index].batchCommand; + } + + internal int GetCurrentBatchIndex() { - Debug.Assert(BatchRPCMode, "Command is not in batch RPC Mode"); - Debug.Assert(_SqlRPCBatchArray != null, "batch command have been cleared"); - return _SqlRPCBatchArray[commandIndex].recordsAffected; + return _batchRPCMode ? _currentlyExecutingBatch : -1; } internal SqlException GetErrors(int commandIndex) { SqlException result = null; - int length = (_SqlRPCBatchArray[commandIndex].errorsIndexEnd - _SqlRPCBatchArray[commandIndex].errorsIndexStart); + _SqlRPC rpc = _RPCList[commandIndex]; + int length = (rpc.errorsIndexEnd - rpc.errorsIndexStart); if (0 < length) { SqlErrorCollection errors = new SqlErrorCollection(); - for (int i = _SqlRPCBatchArray[commandIndex].errorsIndexStart; i < _SqlRPCBatchArray[commandIndex].errorsIndexEnd; ++i) + for (int i = rpc.errorsIndexStart; i < rpc.errorsIndexEnd; ++i) { - errors.Add(_SqlRPCBatchArray[commandIndex].errors[i]); + errors.Add(rpc.errors[i]); } - for (int i = _SqlRPCBatchArray[commandIndex].warningsIndexStart; i < _SqlRPCBatchArray[commandIndex].warningsIndexEnd; ++i) + for (int i = rpc.warningsIndexStart; i < rpc.warningsIndexEnd; ++i) { - errors.Add(_SqlRPCBatchArray[commandIndex].warnings[i]); + errors.Add(rpc.warnings[i]); } - result = SqlException.CreateException(errors, Connection.ServerVersion, Connection.ClientConnectionId); + result = SqlException.CreateException(errors, Connection.ServerVersion, Connection.ClientConnectionId, innerException: null, batchCommand: null); } return result; } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs index e314171b23..7da530b12a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -19,6 +19,7 @@ using System.Threading.Tasks; using Microsoft.Data.Common; using Microsoft.Data.ProviderBase; +using Microsoft.Data.SqlClient.Diagnostics; using Microsoft.SqlServer.Server; namespace Microsoft.Data.SqlClient @@ -202,6 +203,10 @@ public SqlConnection(string connectionString, SqlCredential credential) : this() { throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); } + else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) + { + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + } Credential = credential; } @@ -223,6 +228,7 @@ private SqlConnection(SqlConnection connection) } _accessToken = connection._accessToken; + _accessTokenCallback = connection._accessTokenCallback; CacheConnectionStringProperties(); } @@ -462,7 +468,7 @@ public bool StatisticsEnabled // start if (ConnectionState.Open == State) { - if (null == _statistics) + if (_statistics == null) { _statistics = new SqlStatistics(); _statistics._openTimestamp = ADP.TimerCurrent(); @@ -476,7 +482,7 @@ public bool StatisticsEnabled else { // stop - if (null != _statistics) + if (_statistics != null) { if (ConnectionState.Open == State) { @@ -530,6 +536,11 @@ private bool UsesActiveDirectoryDefault(SqlConnectionString opt) return opt != null && opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryDefault; } + private bool UsesActiveDirectoryWorkloadIdentity(SqlConnectionString opt) + { + return opt != null && opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity; + } + private bool UsesAuthentication(SqlConnectionString opt) { return opt != null && opt.Authentication != SqlAuthenticationMethod.NotSpecified; @@ -545,7 +556,7 @@ private bool UsesIntegratedSecurity(SqlConnectionString opt) private bool UsesClearUserIdOrPassword(SqlConnectionString opt) { bool result = false; - if (null != opt) + if (opt != null) { result = (!string.IsNullOrEmpty(opt.UserID) || !string.IsNullOrEmpty(opt.Password)); } @@ -619,6 +630,10 @@ public override string ConnectionString { throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); } + else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) + { + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); } @@ -647,7 +662,7 @@ public override int ConnectionTimeout get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; - return ((null != constr) ? constr.ConnectTimeout : SqlConnectionString.DEFAULT.Connect_Timeout); + return constr != null ? constr.ConnectTimeout : SqlConnectionString.DEFAULT.Connect_Timeout; } } @@ -659,7 +674,7 @@ public int CommandTimeout get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; - return ((null != constr) ? constr.CommandTimeout : SqlConnectionString.DEFAULT.Command_Timeout); + return constr != null ? constr.CommandTimeout : SqlConnectionString.DEFAULT.Command_Timeout; } } @@ -734,14 +749,14 @@ public override string Database SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; - if (null != innerConnection) + if (innerConnection != null) { result = innerConnection.CurrentDatabase; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; - result = ((null != constr) ? constr.InitialCatalog : SqlConnectionString.DEFAULT.Initial_Catalog); + result = constr != null ? constr.InitialCatalog : SqlConnectionString.DEFAULT.Initial_Catalog; } return result; } @@ -757,7 +772,7 @@ internal string SQLDNSCachingSupportedState SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); string result; - if (null != innerConnection) + if (innerConnection != null) { result = innerConnection.IsSQLDNSCachingSupported ? "true" : "false"; } @@ -780,7 +795,7 @@ internal string SQLDNSCachingSupportedStateBeforeRedirect SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); string result; - if (null != innerConnection) + if (innerConnection != null) { result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false"; } @@ -805,14 +820,14 @@ public override string DataSource SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; - if (null != innerConnection) + if (innerConnection != null) { result = innerConnection.CurrentDataSource; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; - result = ((null != constr) ? constr.DataSource : SqlConnectionString.DEFAULT.Data_Source); + result = constr != null ? constr.DataSource : SqlConnectionString.DEFAULT.Data_Source; } return result; } @@ -832,14 +847,14 @@ public int PacketSize SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); int result; - if (null != innerConnection) + if (innerConnection != null) { result = innerConnection.PacketSize; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; - result = ((null != constr) ? constr.PacketSize : SqlConnectionString.DEFAULT.Packet_Size); + result = constr != null ? constr.PacketSize : SqlConnectionString.DEFAULT.Packet_Size; } return result; } @@ -855,7 +870,7 @@ public Guid ClientConnectionId { SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); - if (null != innerConnection) + if (innerConnection != null) { return innerConnection.ClientConnectionId; } @@ -864,7 +879,7 @@ public Guid ClientConnectionId Task reconnectTask = _currentReconnectionTask; // Connection closed but previously open should return the correct ClientConnectionId DbConnectionClosedPreviouslyOpened innerConnectionClosed = (InnerConnection as DbConnectionClosedPreviouslyOpened); - if ((reconnectTask != null && !reconnectTask.IsCompleted) || null != innerConnectionClosed) + if ((reconnectTask != null && !reconnectTask.IsCompleted) || innerConnectionClosed != null) { return _originalConnectionId; } @@ -999,6 +1014,10 @@ public SqlCredential Credential { throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); } + else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) + { + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); @@ -1237,7 +1256,7 @@ public static void ClearPool(SqlConnection connection) ADP.CheckArgumentNull(connection, nameof(connection)); DbConnectionOptions connectionOptions = connection.UserConnectionOptions; - if (null != connectionOptions) + if (connectionOptions != null) { SqlConnectionFactory.SingletonInstance.ClearPool(connection); } @@ -1306,7 +1325,7 @@ public override void Close() CloseInnerConnection(); GC.SuppressFinalize(this); - if (null != Statistics) + if (Statistics != null) { _statistics._closeTimestamp = ADP.TimerCurrent(); } @@ -1671,8 +1690,8 @@ private Task InternalOpenAsync(CancellationToken cancellationToken) TaskCompletionSource completion = new TaskCompletionSource(transaction); TaskCompletionSource result = new TaskCompletionSource(state: this); - if (s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterOpenConnection) || - s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlErrorOpenConnection)) + if (s_diagnosticListener.IsEnabled(SqlClientConnectionOpenAfter.Name) || + s_diagnosticListener.IsEnabled(SqlClientConnectionOpenError.Name)) { result.Task.ContinueWith( continuationAction: s_openAsyncComplete, @@ -1775,6 +1794,14 @@ public override DataTable GetSchema(string collectionName, string[] restrictionV return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues); } +#if NET6_0_OR_GREATER + /// + public override bool CanCreateBatch => true; + + /// + protected override DbBatch CreateDbBatch() => new SqlBatch(this); +#endif + private class OpenAsyncRetry { private SqlConnection _parent; @@ -1853,10 +1880,10 @@ internal void Retry(Task retryTask) private void PrepareStatisticsForNewConnection() { if (StatisticsEnabled || - s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand) || - s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterOpenConnection)) + s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name) || + s_diagnosticListener.IsEnabled(SqlClientConnectionOpenAfter.Name)) { - if (null == _statistics) + if (_statistics == null) { _statistics = new SqlStatistics(); } @@ -1959,7 +1986,7 @@ private bool TryOpen(TaskCompletionSource retry, SqlConnec // The _statistics can change with StatisticsEnabled. Copying to a local variable before checking for a null value. SqlStatistics statistics = _statistics; if (StatisticsEnabled || - (s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand) && statistics != null)) + (s_diagnosticListener.IsEnabled(SqlClientCommandAfter.Name) && statistics != null)) { _statistics._openTimestamp = ADP.TimerCurrent(); tdsInnerConnection.Parser.Statistics = _statistics; @@ -2119,7 +2146,7 @@ internal void OnError(SqlException exception, bool breakConnection, Action RegisterForConnectionCloseNotification(Task outerTask, ob /// public void ResetStatistics() { - if (null != Statistics) + if (Statistics != null) { Statistics.Reset(); if (ConnectionState.Open == State) @@ -2349,7 +2375,7 @@ public void ResetStatistics() /// public IDictionary RetrieveStatistics() { - if (null != Statistics) + if (Statistics != null) { UpdateStatistics(); return Statistics.GetDictionary(); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.AssemblyLoadContext.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.AssemblyLoadContext.cs index 7338b8d4d2..230b7ae5fc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.AssemblyLoadContext.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.AssemblyLoadContext.cs @@ -2,13 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NET6_0_OR_GREATER + using System; using System.Reflection; using System.Runtime.Loader; namespace Microsoft.Data.SqlClient { - sealed internal partial class SqlConnectionFactory + internal sealed partial class SqlConnectionFactory { partial void SubscribeToAssemblyLoadContextUnload() { @@ -21,3 +23,5 @@ private void SqlConnectionFactoryAssemblyLoadContext_Unloading(AssemblyLoadConte } } } + +#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs index 7526f38623..d84b433d68 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs @@ -85,8 +85,7 @@ override protected DbConnectionInternal CreateConnection(DbConnectionOptions opt redirectedUserInstance = true; string instanceName; - if ((null == pool) || - (null != pool && pool.Count <= 0)) + if (pool == null || (pool != null && pool.Count <= 0)) { // Non-pooled or pooled and no connections in the pool. SqlInternalConnectionTds sseConnection = null; try @@ -105,7 +104,7 @@ override protected DbConnectionInternal CreateConnection(DbConnectionOptions opt throw SQL.NonLocalSSEInstance(); } - if (null != pool) + if (pool != null) { // Pooled connection - cache result SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo)pool.ProviderInfo; // No lock since we are already in creation mutex @@ -114,7 +113,7 @@ override protected DbConnectionInternal CreateConnection(DbConnectionOptions opt } finally { - if (null != sseConnection) + if (sseConnection != null) { sseConnection.Dispose(); } @@ -208,7 +207,7 @@ override internal DbConnectionPoolGroupProviderInfo CreateConnectionPoolGroupPro internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKey key) { SqlConnectionString connectionOptions = (SqlConnectionString)SingletonInstance.FindConnectionOptions(key); - if (null == connectionOptions) + if (connectionOptions == null) { connectionOptions = new SqlConnectionString(key.ConnectionString); } @@ -223,7 +222,7 @@ internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKe override internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection) { SqlConnection c = (connection as SqlConnection); - if (null != c) + if (c != null) { return c.PoolGroup; } @@ -233,7 +232,7 @@ override internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection conn override internal DbConnectionInternal GetInnerConnection(DbConnection connection) { SqlConnection c = (connection as SqlConnection); - if (null != c) + if (c != null) { return c.InnerConnection; } @@ -243,7 +242,7 @@ override internal DbConnectionInternal GetInnerConnection(DbConnection connectio override protected int GetObjectId(DbConnection connection) { SqlConnection c = (connection as SqlConnection); - if (null != c) + if (c != null) { return c.ObjectID; } @@ -253,7 +252,7 @@ override protected int GetObjectId(DbConnection connection) override internal void PermissionDemand(DbConnection outerConnection) { SqlConnection c = (outerConnection as SqlConnection); - if (null != c) + if (c != null) { c.PermissionDemand(); } @@ -262,7 +261,7 @@ override internal void PermissionDemand(DbConnection outerConnection) override internal void SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup) { SqlConnection c = (outerConnection as SqlConnection); - if (null != c) + if (c != null) { c.PoolGroup = poolGroup; } @@ -271,7 +270,7 @@ override internal void SetConnectionPoolGroup(DbConnection outerConnection, DbCo override internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to) { SqlConnection c = (owningObject as SqlConnection); - if (null != c) + if (c != null) { c.SetInnerConnectionEvent(to); } @@ -280,7 +279,7 @@ override internal void SetInnerConnectionEvent(DbConnection owningObject, DbConn override internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from) { SqlConnection c = (owningObject as SqlConnection); - if (null != c) + if (c != null) { return c.SetInnerConnectionFrom(to, from); } @@ -290,7 +289,7 @@ override internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConne override internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to) { SqlConnection c = (owningObject as SqlConnection); - if (null != c) + if (c != null) { c.SetInnerConnectionTo(to); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionHelper.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionHelper.cs index a34be614cd..aa8420d8bb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionHelper.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionHelper.cs @@ -54,7 +54,7 @@ internal DbConnectionOptions ConnectionOptions get { DbConnectionPoolGroup poolGroup = PoolGroup; - return ((null != poolGroup) ? poolGroup.ConnectionOptions : null); + return poolGroup != null ? poolGroup.ConnectionOptions : null; } } @@ -63,7 +63,7 @@ private string ConnectionString_Get() SqlClientEventSource.Log.TryTraceEvent(" {0}", ObjectID); bool hidePassword = InnerConnection.ShouldHidePassword; DbConnectionOptions connectionOptions = UserConnectionOptions; - return ((null != connectionOptions) ? connectionOptions.UsersConnectionString(hidePassword) : ""); + return connectionOptions != null ? connectionOptions.UsersConnectionString(hidePassword) : ""; } private void ConnectionString_Set(DbConnectionPoolKey key) @@ -108,7 +108,7 @@ internal DbConnectionPoolGroup PoolGroup } set { - Debug.Assert(null != value, "null poolGroup"); + Debug.Assert(value != null, "null poolGroup"); _poolGroup = value; } } @@ -137,7 +137,7 @@ internal void Abort(Exception e) // will end the reliable try... if (e is OutOfMemoryException) { - SqlClientEventSource.Log.TryTraceEvent(" {0}, Aborting operation due to asynchronous exception: {'OutOfMemory'}", ObjectID); + SqlClientEventSource.Log.TryTraceEvent(" {0}, Aborting operation due to asynchronous exception: OutOfMemory", ObjectID); } else { @@ -226,13 +226,13 @@ internal void PermissionDemand() { Debug.Assert(DbConnectionClosedConnecting.SingletonInstance == _innerConnection, "not connecting"); DbConnectionPoolGroup poolGroup = PoolGroup; - DbConnectionOptions connectionOptions = ((null != poolGroup) ? poolGroup.ConnectionOptions : null); - if ((null == connectionOptions) || connectionOptions.IsEmpty) + DbConnectionOptions connectionOptions = poolGroup != null ? poolGroup.ConnectionOptions : null; + if (connectionOptions == null || connectionOptions.IsEmpty) { throw ADP.NoConnectionString(); } DbConnectionOptions userConnectionOptions = UserConnectionOptions; - Debug.Assert(null != userConnectionOptions, "null UserConnectionOptions"); + Debug.Assert(userConnectionOptions != null, "null UserConnectionOptions"); } internal void RemoveWeakReference(object value) @@ -242,8 +242,8 @@ internal void RemoveWeakReference(object value) internal void SetInnerConnectionEvent(DbConnectionInternal to) { - Debug.Assert(null != _innerConnection, "null InnerConnection"); - Debug.Assert(null != to, "to null InnerConnection"); + Debug.Assert(_innerConnection != null, "null InnerConnection"); + Debug.Assert(to != null, "to null InnerConnection"); ConnectionState originalState = _innerConnection.State & ConnectionState.Open; ConnectionState currentState = to.State & ConnectionState.Open; @@ -276,17 +276,17 @@ internal void SetInnerConnectionEvent(DbConnectionInternal to) internal bool SetInnerConnectionFrom(DbConnectionInternal to, DbConnectionInternal from) { - Debug.Assert(null != _innerConnection, "null InnerConnection"); - Debug.Assert(null != from, "from null InnerConnection"); - Debug.Assert(null != to, "to null InnerConnection"); + Debug.Assert(_innerConnection != null, "null InnerConnection"); + Debug.Assert(from != null, "from null InnerConnection"); + Debug.Assert(to != null, "to null InnerConnection"); bool result = (from == Interlocked.CompareExchange(ref _innerConnection, to, from)); return result; } internal void SetInnerConnectionTo(DbConnectionInternal to) { - Debug.Assert(null != _innerConnection, "null InnerConnection"); - Debug.Assert(null != to, "to null InnerConnection"); + Debug.Assert(_innerConnection != null, "null InnerConnection"); + Debug.Assert(to != null, "to null InnerConnection"); _innerConnection = to; } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs index 1cc9acd2f2..cc07cd03c3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs @@ -14,6 +14,8 @@ using System.IO; using System.Reflection; using System.Runtime.CompilerServices; +using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Xml; @@ -256,7 +258,7 @@ internal _SqlMetaDataSet MetaData } Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - if (!TryConsumeMetaData()) + if (TryConsumeMetaData() != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -270,7 +272,7 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData() SmiExtendedMetaData[] metaDataReturn = null; _SqlMetaDataSet metaData = this.MetaData; - if (null != metaData && 0 < metaData.Length) + if (metaData != null && 0 < metaData.Length) { metaDataReturn = new SmiExtendedMetaData[metaData.VisibleColumnCount]; int returnIndex = 0; @@ -318,12 +320,12 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData() length, colMetaData.precision, colMetaData.scale, - (null != collation) ? collation.LCID : _defaultLCID, - (null != collation) ? collation.SqlCompareOptions : SqlCompareOptions.None, + collation != null ? collation.LCID : _defaultLCID, + collation != null ? collation.SqlCompareOptions : SqlCompareOptions.None, colMetaData.udt?.Type, - false, // isMultiValued - null, // fieldmetadata - null, // extended properties + isMultiValued: false, + fieldMetaData: null, + extendedProperties: null, colMetaData.column, typeSpecificNamePart1, typeSpecificNamePart2, @@ -354,8 +356,10 @@ override public int RecordsAffected { get { - if (null != _command) + if (_command != null) + { return _command.InternalRecordsAffected; + } // cached locally for after Close() when command is nulled out return _recordsAffected; @@ -429,9 +433,9 @@ override public object this[string name] internal void Bind(TdsParserStateObject stateObj) { - Debug.Assert(null != stateObj, "null stateobject"); + Debug.Assert(stateObj != null, "null stateobject"); - Debug.Assert(null == _snapshot, "Should not change during execution of asynchronous command"); + Debug.Assert(_snapshot == null, "Should not change during execution of asynchronous command"); stateObj.Owner = this; _stateObj = stateObj; @@ -439,14 +443,14 @@ internal void Bind(TdsParserStateObject stateObj) _defaultLCID = _parser.DefaultLCID; } -#if NET6_0_OR_GREATER +#if !NETFRAMEWORK [SuppressMessage("ReflectionAnalysis", "IL2111", Justification = "System.Type.TypeInitializer would not be used in dataType and providerSpecificDataType columns.")] #endif internal DataTable BuildSchemaTable() { _SqlMetaDataSet md = this.MetaData; - Debug.Assert(null != md, "BuildSchemaTable - unexpected null metadata information"); + Debug.Assert(md != null, "BuildSchemaTable - unexpected null metadata information"); DataTable schemaTable = new DataTable("SchemaTable"); schemaTable.Locale = CultureInfo.InvariantCulture; @@ -747,7 +751,7 @@ internal void Cancel(SqlCommand command) { Debug.Assert(command == _command, "Calling command from an object that isn't this reader's command"); TdsParserStateObject stateObj = _stateObj; - if (null != stateObj) + if (stateObj != null) { stateObj.Cancel(command); } @@ -755,18 +759,20 @@ internal void Cancel(SqlCommand command) // wipe any data off the wire from a partial read // and reset all pointers for sequential access - private bool TryCleanPartialRead() + private TdsOperationStatus TryCleanPartialRead() { AssertReaderState(requireData: true, permitAsync: true); // VSTS DEVDIV2 380446: It is possible that read attempt we are cleaning after ended with partially // processed header (if it falls between network packets). In this case the first thing to do is to // finish reading the header, otherwise code will start treating unread header as TDS payload. + TdsOperationStatus result; if (_stateObj._partialHeaderBytesRead > 0) { - if (!_stateObj.TryProcessHeader()) + result = _stateObj.TryProcessHeader(); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } @@ -784,24 +790,27 @@ private bool TryCleanPartialRead() // i. user called read but didn't fetch anything if (0 == _sharedState._nextColumnHeaderToRead) { - if (!_stateObj.Parser.TrySkipRow(_metaData, _stateObj)) + result = _stateObj.Parser.TrySkipRow(_metaData, _stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } else { // iia. if we still have bytes left from a partially read column, skip - if (!TryResetBlobState()) + result = TryResetBlobState(); + if (result != TdsOperationStatus.Done) { - return false; + return result; } // iib. // now read the remaining values off the wire for this row - if (!_stateObj.Parser.TrySkipRow(_metaData, _sharedState._nextColumnHeaderToRead, _stateObj)) + result = _stateObj.Parser.TrySkipRow(_metaData, _sharedState._nextColumnHeaderToRead, _stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } @@ -809,9 +818,10 @@ private bool TryCleanPartialRead() if (_stateObj.HasPendingData) { byte token; - if (!_stateObj.TryPeekByte(out token)) + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(TdsParser.IsValidTdsToken(token), $"Invalid token after performing CleanPartialRead: {token,-2:X2}"); @@ -819,15 +829,15 @@ private bool TryCleanPartialRead() #endif _sharedState._dataReady = false; - return true; + return TdsOperationStatus.Done; } private void CleanPartialReadReliable() { AssertReaderState(requireData: true, permitAsync: false); - bool result = TryCleanPartialRead(); - Debug.Assert(result, "Should not pend on sync call"); + TdsOperationStatus result = TryCleanPartialRead(); + Debug.Assert(result == TdsOperationStatus.Done, "Should not pend on sync call"); Debug.Assert(!_sharedState._dataReady, "_dataReady should be cleared"); } @@ -923,7 +933,7 @@ public override void Close() // in which case we need to switch to syncOverAsync stateObj._syncOverAsync = true; - if (!TryCloseInternal(true /*closeReader*/)) + if (TryCloseInternal(closeReader: true) != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -939,13 +949,14 @@ public override void Close() } } - private bool TryCloseInternal(bool closeReader) + private TdsOperationStatus TryCloseInternal(bool closeReader) { TdsParser parser = _parser; TdsParserStateObject stateObj = _stateObj; bool closeConnection = (IsCommandBehavior(CommandBehavior.CloseConnection)); bool aborting = false; bool cleanDataFailed = false; + TdsOperationStatus result; try { @@ -968,22 +979,24 @@ private bool TryCloseInternal(bool closeReader) if (_sharedState._dataReady) { cleanDataFailed = true; - if (TryCleanPartialRead()) + result = TryCleanPartialRead(); + if (result == TdsOperationStatus.Done) { cleanDataFailed = false; } else { - return false; + return result; } } #if DEBUG else { byte token; - if (!_stateObj.TryPeekByte(out token)) + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); @@ -991,16 +1004,16 @@ private bool TryCloseInternal(bool closeReader) #endif - bool ignored; - if (!parser.TryRun(RunBehavior.Clean, _command, this, null, stateObj, out ignored)) + result = parser.TryRun(RunBehavior.Clean, _command, this, null, stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } } RestoreServerSettings(parser, stateObj); - return true; + return TdsOperationStatus.Done; } finally { @@ -1042,7 +1055,7 @@ private bool TryCloseInternal(bool closeReader) // IsClosed may be true if CloseReaderFromConnection was called - in which case, the session has already been closed - if ((!wasClosed) && (null != stateObj)) + if (!wasClosed && stateObj != null) { if (!cleanDataFailed) { @@ -1061,8 +1074,8 @@ private bool TryCloseInternal(bool closeReader) // DO NOT USE stateObj after this point - it has been returned to the TdsParser's session pool and potentially handed out to another thread // do not retry here - bool result = TrySetMetaData(null, false); - Debug.Assert(result, "Should not pend a synchronous request"); + result = TrySetMetaData(null, false); + Debug.Assert(result == TdsOperationStatus.Done, "Should not pend a synchronous request"); _fieldNameLookup = null; // if the user calls ExecuteReader(CommandBehavior.CloseConnection) @@ -1127,7 +1140,7 @@ virtual internal void CloseReaderFromConnection() } } - private bool TryConsumeMetaData() + private TdsOperationStatus TryConsumeMetaData() { // warning: Don't check the MetaData property within this function // warning: as it will be a reentrant call @@ -1140,18 +1153,21 @@ private bool TryConsumeMetaData() // NOTE: We doom connection for TdsParserState.Closed since it indicates that it is in some abnormal and unstable state, probably as a result of // closing from another thread. In general, TdsParserState.Closed does not necessitate dooming the connection. if (_parser.Connection != null) + { _parser.Connection.DoomThisConnection(); + } throw SQL.ConnectionDoomed(); } bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out ignored)) + TdsOperationStatus result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out ignored); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(!ignored, "Parser read a row token while trying to read metadata"); } - return true; + return TdsOperationStatus.Done; } /// @@ -1224,7 +1240,7 @@ private string GetDataTypeNameInternal(_SqlMetaData metaData) virtual internal SqlBuffer.StorageType GetVariantInternalStorageType(int i) { - Debug.Assert(null != _data, "Attempting to get variant internal storage type"); + Debug.Assert(_data != null, "Attempting to get variant internal storage type"); Debug.Assert(i < _data.Length, "Reading beyond data length?"); return _data[i].VariantInternalStorageType; @@ -1237,7 +1253,7 @@ override public IEnumerator GetEnumerator() } /// -#if NET6_0_OR_GREATER +#if !NETFRAMEWORK [SuppressMessage("ReflectionAnalysis", "IL2093:MismatchOnMethodReturnValueBetweenOverrides", Justification = "Annotations for DbDataReader was not shipped in net6.0")] [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] @@ -1258,7 +1274,7 @@ override public Type GetFieldType(int i) } } -#if NET6_0_OR_GREATER +#if !NETFRAMEWORK [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif private Type GetFieldTypeInternal(_SqlMetaData metaData) @@ -1353,7 +1369,7 @@ override public string GetName(int i) } /// -#if NET7_0_OR_GREATER +#if !NETFRAMEWORK && NET8_0_OR_GREATER [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif override public Type GetProviderSpecificFieldType(int i) @@ -1372,7 +1388,7 @@ override public Type GetProviderSpecificFieldType(int i) } } -#if NET6_0_OR_GREATER +#if !NETFRAMEWORK [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif private Type GetProviderSpecificFieldTypeInternal(_SqlMetaData metaData) @@ -1435,7 +1451,7 @@ override public int GetOrdinal(string name) try { statistics = SqlStatistics.StartTimer(Statistics); - if (null == _fieldNameLookup) + if (_fieldNameLookup == null) { CheckMetaDataIsReady(); _fieldNameLookup = new FieldNameLookup(this, _defaultLCID); @@ -1469,12 +1485,12 @@ public override DataTable GetSchemaTable() try { statistics = SqlStatistics.StartTimer(Statistics); - if (null == _metaData || null == _metaData.schemaTable) + if (_metaData == null || _metaData.schemaTable == null) { - if (null != this.MetaData) + if (this.MetaData != null) { _metaData.schemaTable = BuildSchemaTable(); - Debug.Assert(null != _metaData.schemaTable, "No schema information yet!"); + Debug.Assert(_metaData.schemaTable != null, "No schema information yet!"); } } return _metaData?.schemaTable; @@ -1627,18 +1643,18 @@ virtual internal long GetBytesInternal(int i, long dataIndex, byte[] buffer, int long value; Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = TryGetBytesInternal(i, dataIndex, buffer, bufferIndex, length, out value); - if (!result) + TdsOperationStatus result = TryGetBytesInternal(i, dataIndex, buffer, bufferIndex, length, out value); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } return value; } - private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int bufferIndex, int length, out long remaining) + private TdsOperationStatus TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int bufferIndex, int length, out long remaining) { remaining = 0; - + TdsOperationStatus result; int cbytes = 0; AssertReaderState(requireData: true, permitAsync: true, columnIndex: i, enforceSequentialAccess: true); @@ -1654,9 +1670,10 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe if (_sharedState._nextColumnHeaderToRead <= i) { - if (!TryReadColumnHeader(i)) + result = TryReadColumnHeader(i); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } @@ -1670,32 +1687,35 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe if ((-1 == _sharedState._columnDataBytesRemaining) && (_metaData[i].metaType.IsPlp)) { ulong left; - if (!_parser.TryPlpBytesLeft(_stateObj, out left)) + result = _parser.TryPlpBytesLeft(_stateObj, out left); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _sharedState._columnDataBytesRemaining = (long)left; } if (0 == _sharedState._columnDataBytesRemaining) { - return true; // We've read this column to the end + return TdsOperationStatus.Done; // We've read this column to the end } // if no buffer is passed in, return the number total of bytes, or -1 - if (null == buffer) + if (buffer == null) { if (_metaData[i].metaType.IsPlp) { remaining = (long)_parser.PlpBytesTotalLength(_stateObj); - return true; + return TdsOperationStatus.Done; } remaining = _sharedState._columnDataBytesRemaining; - return true; + return TdsOperationStatus.Done; } if (dataIndex < 0) + { throw ADP.NegativeParameter(nameof(dataIndex)); + } if (dataIndex < _columnDataBytesRead) { @@ -1708,19 +1728,25 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe // if dataIndex is outside of the data range, return 0 if ((cb > _sharedState._columnDataBytesRemaining) && !_metaData[i].metaType.IsPlp) { - return true; + return TdsOperationStatus.Done; } // if bad buffer index, throw if (bufferIndex < 0 || bufferIndex >= buffer.Length) + { throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + } // if there is not enough room in the buffer for data if (length + bufferIndex > buffer.Length) + { throw ADP.InvalidBufferSizeOrIndex(length, bufferIndex); + } if (length < 0) + { throw ADP.InvalidDataLength(length); + } // Skip if needed if (cb > 0) @@ -1728,17 +1754,19 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe if (_metaData[i].metaType.IsPlp) { ulong skipped; - if (!_parser.TrySkipPlpValue((ulong)cb, _stateObj, out skipped)) + result = _parser.TrySkipPlpValue((ulong)cb, _stateObj, out skipped); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _columnDataBytesRead += (long)skipped; } else { - if (!_stateObj.TrySkipLongBytes(cb)) + result = _stateObj.TrySkipLongBytes(cb); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _columnDataBytesRead += cb; _sharedState._columnDataBytesRemaining -= cb; @@ -1746,7 +1774,7 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe } int bytesRead; - bool result = TryGetBytesInternalSequential(i, buffer, bufferIndex, length, out bytesRead); + result = TryGetBytesInternalSequential(i, buffer, bufferIndex, length, out bytesRead); remaining = (int)bytesRead; return result; } @@ -1755,7 +1783,9 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe // note that since we are caching in an array, and arrays aren't 64 bit ready yet, // we need can cast to int if the dataIndex is in range if (dataIndex < 0) + { throw ADP.NegativeParameter(nameof(dataIndex)); + } if (dataIndex > int.MaxValue) { @@ -1792,16 +1822,16 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe cbytes = data.Length; // if no buffer is passed in, return the number of characters we have - if (null == buffer) + if (buffer == null) { remaining = cbytes; - return true; + return TdsOperationStatus.Done; } // if dataIndex is outside of data range, return 0 if (ndataIndex < 0 || ndataIndex >= cbytes) { - return true; + return TdsOperationStatus.Done; } try { @@ -1809,9 +1839,13 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe { // help the user out in the case where there's less data than requested if ((ndataIndex + length) > cbytes) + { cbytes = cbytes - ndataIndex; + } else + { cbytes = length; + } } Buffer.BlockCopy(data, ndataIndex, buffer, bufferIndex, cbytes); @@ -1825,21 +1859,27 @@ private bool TryGetBytesInternal(int i, long dataIndex, byte[] buffer, int buffe cbytes = data.Length; if (length < 0) + { throw ADP.InvalidDataLength(length); + } // if bad buffer index, throw if (bufferIndex < 0 || bufferIndex >= buffer.Length) + { throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + } // if there is not enough room in the buffer for data if (cbytes + bufferIndex > buffer.Length) + { throw ADP.InvalidBufferSizeOrIndex(cbytes, bufferIndex); + } throw; } remaining = cbytes; - return true; + return TdsOperationStatus.Done; } internal int GetBytesInternalSequential(int i, byte[] buffer, int index, int length, long? timeoutMilliseconds = null) @@ -1857,14 +1897,14 @@ internal int GetBytesInternalSequential(int i, byte[] buffer, int index, int len statistics = SqlStatistics.StartTimer(Statistics); SetTimeout(timeoutMilliseconds ?? _defaultTimeoutMilliseconds); - bool result = TryReadColumnHeader(i); - if (!result) + TdsOperationStatus result = TryReadColumnHeader(i); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } result = TryGetBytesInternalSequential(i, buffer, index, length, out value); - if (!result) + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -1880,7 +1920,7 @@ internal int GetBytesInternalSequential(int i, byte[] buffer, int index, int len // This is meant to be called from other internal methods once we are at the column to read // NOTE: This method must be retriable WITHOUT replaying a snapshot // Every time you call this method increment the index and decrease length by the value of bytesRead - internal bool TryGetBytesInternalSequential(int i, byte[] buffer, int index, int length, out int bytesRead) + internal TdsOperationStatus TryGetBytesInternalSequential(int i, byte[] buffer, int index, int length, out int bytesRead) { AssertReaderState(requireData: true, permitAsync: true, columnIndex: i, enforceSequentialAccess: true); Debug.Assert(_sharedState._nextColumnHeaderToRead == i + 1 && _sharedState._nextColumnDataToRead == i, "Non sequential access"); @@ -1890,12 +1930,12 @@ internal bool TryGetBytesInternalSequential(int i, byte[] buffer, int index, int Debug.Assert(index + length <= buffer.Length, "Buffer too small"); bytesRead = 0; - + TdsOperationStatus result; if ((_sharedState._columnDataBytesRemaining == 0) || (length == 0)) { // No data left or nothing requested, return 0 bytesRead = 0; - return true; + return TdsOperationStatus.Done; } else { @@ -1903,28 +1943,29 @@ internal bool TryGetBytesInternalSequential(int i, byte[] buffer, int index, int if (_metaData[i].metaType.IsPlp) { // Read in data - bool result = _stateObj.TryReadPlpBytes(ref buffer, index, length, out bytesRead); + result = _stateObj.TryReadPlpBytes(ref buffer, index, length, out bytesRead); _columnDataBytesRead += bytesRead; - if (!result) + if (result != TdsOperationStatus.Done) { - return false; + return result; } // Query for number of bytes left ulong left; - if (!_parser.TryPlpBytesLeft(_stateObj, out left)) + result = _parser.TryPlpBytesLeft(_stateObj, out left); + if (result != TdsOperationStatus.Done) { _sharedState._columnDataBytesRemaining = -1; - return false; + return result; } _sharedState._columnDataBytesRemaining = (long)left; - return true; + return TdsOperationStatus.Done; } else { // Read data (not exceeding the total amount of data available) int bytesToRead = (int)Math.Min((long)length, _sharedState._columnDataBytesRemaining); - bool result = _stateObj.TryReadByteArray(buffer.AsSpan(index), bytesToRead, out bytesRead); + result = _stateObj.TryReadByteArray(buffer.AsSpan(index), bytesToRead, out bytesRead); _columnDataBytesRead += bytesRead; _sharedState._columnDataBytesRemaining -= bytesRead; return result; @@ -1966,7 +2007,11 @@ override public TextReader GetTextReader(int i) } System.Text.Encoding encoding; - if (mt.IsNCharType) + if (mt.SqlDbType == SqlDbTypeExtensions.Json) + { + encoding = new UTF8Encoding(); + } + else if (mt.IsNCharType) { // NChar types always use unicode encoding = SqlUnicodeEncoding.SqlUnicodeEncodingInstance; @@ -1975,7 +2020,6 @@ override public TextReader GetTextReader(int i) { encoding = _metaData[i].encoding; } - _currentTextReader = new SqlSequentialTextReader(this, i, encoding); _lastColumnWithDataChunkRead = i; return _currentTextReader; @@ -2130,12 +2174,16 @@ override public long GetChars(int i, long dataIndex, char[] buffer, int bufferIn int ndataIndex = (int)dataIndex; // if no buffer is passed in, return the number of characters we have - if (null == buffer) + if (buffer == null) + { return cchars; + } // if dataIndex outside of data range, return 0 if (ndataIndex < 0 || ndataIndex >= cchars) + { return 0; + } try { @@ -2143,9 +2191,13 @@ override public long GetChars(int i, long dataIndex, char[] buffer, int bufferIn { // help the user out in the case where there's less data than requested if ((ndataIndex + length) > cchars) + { cchars = cchars - ndataIndex; + } else + { cchars = length; + } } Array.Copy(_columnDataChars, ndataIndex, buffer, bufferIndex, cchars); @@ -2160,15 +2212,21 @@ override public long GetChars(int i, long dataIndex, char[] buffer, int bufferIn cchars = _columnDataChars.Length; if (length < 0) + { throw ADP.InvalidDataLength(length); + } // if bad buffer index, throw if (bufferIndex < 0 || bufferIndex >= buffer.Length) + { throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + } // if there is not enough room in the buffer for data if (cchars + bufferIndex > buffer.Length) + { throw ADP.InvalidBufferSizeOrIndex(cchars, bufferIndex); + } throw; } @@ -2218,7 +2276,9 @@ private long GetCharsFromPlpData(int i, long dataIndex, char[] buffer, int buffe // _columnDataCharsRead is 0 and dataIndex > _columnDataCharsRead is true below. // In both cases we will clean decoder if (dataIndex == 0) + { _stateObj._plpdecoder = null; + } bool isUnicode = _metaData[i].metaType.IsNCharType; @@ -2235,7 +2295,7 @@ private long GetCharsFromPlpData(int i, long dataIndex, char[] buffer, int buffe } // if no buffer is passed in, return the total number of characters or -1 - if (null == buffer) + if (buffer == null) { cch = (long)_parser.PlpBytesTotalLength(_stateObj); return (isUnicode && (cch > 0)) ? cch >> 1 : cch; @@ -2520,6 +2580,14 @@ virtual public SqlXml GetSqlXml(int i) return sx; } + /// + virtual public SqlJson GetSqlJson(int i) + { + ReadColumn(i); + SqlJson json = _data[i].IsNull ? SqlJson.Null : _data[i].SqlJson; + return json; + } + /// virtual public object GetSqlValue(int i) { @@ -2545,8 +2613,8 @@ private object GetSqlValueInternal(int i) } Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = TryReadColumn(i, setTimeout: false); - if (!result) + TdsOperationStatus result = TryReadColumn(i, setTimeout: false); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -2583,7 +2651,7 @@ private object GetSqlValueFromSqlBufferInternal(SqlBuffer data, _SqlMetaData met } else { - throw ADP.DataReaderClosed(nameof(GetSqlValueFromSqlBufferInternal)); + throw ADP.DataReaderClosed(); } } else @@ -2614,7 +2682,7 @@ virtual public int GetSqlValues(object[] values) { statistics = SqlStatistics.StartTimer(Statistics); CheckDataIsReady(); - if (null == values) + if (values == null) { throw ADP.ArgumentNull(nameof(values)); } @@ -2735,8 +2803,8 @@ private object GetValueInternal(int i) } Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = TryReadColumn(i, setTimeout: false); - if (!result) + TdsOperationStatus result = TryReadColumn(i, setTimeout: false); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -2783,7 +2851,7 @@ private object GetValueFromSqlBufferInternal(SqlBuffer data, _SqlMetaData metaDa } else { - throw ADP.DataReaderClosed(nameof(GetValueFromSqlBufferInternal)); + throw ADP.DataReaderClosed(); } } } @@ -2803,8 +2871,8 @@ private T GetFieldValueInternal(int i, bool isAsync) Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); bool forStreaming = typeof(T) == typeof(XmlReader) || typeof(T) == typeof(TextReader) || typeof(T) == typeof(Stream); - bool result = TryReadColumn(i, setTimeout: false, forStreaming: forStreaming); - if (!result) + TdsOperationStatus result = TryReadColumn(i, setTimeout: false, forStreaming: forStreaming); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -2862,12 +2930,12 @@ private T GetFieldValueFromSqlBufferInternal(SqlBuffer data, _SqlMetaData met { return (T)(object)data.DateTime; } -#if NET6_0_OR_GREATER - else if (typeof(T) == typeof(DateOnly) && dataType == typeof(DateTime) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005 && metaData.Is2008DateTimeType) +#if !NETFRAMEWORK + else if (typeof(T) == typeof(DateOnly) && dataType == typeof(DateTime) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005) { return (T)(object)data.DateOnly; } - else if (typeof(T) == typeof(TimeOnly) && dataType == typeof(TimeOnly) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005 && metaData.Is2008DateTimeType) + else if (typeof(T) == typeof(TimeOnly) && dataType == typeof(TimeOnly) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005) { return (T)(object)data.TimeOnly; } @@ -2973,6 +3041,16 @@ private T GetFieldValueFromSqlBufferInternal(SqlBuffer data, _SqlMetaData met return (T)(object)new MemoryStream(value, writable: false); } } + else if (typeof(T) == typeof(JsonDocument)) + { + MetaType metaType = metaData.metaType; + if (metaType.SqlDbType != SqlDbTypeExtensions.Json) + { + throw SQL.JsonDocumentNotSupportedOnColumnType(metaData.column); + } + JsonDocument document = JsonDocument.Parse(data.Value as string); + return (T)(object)document; + } else { if (typeof(INullable).IsAssignableFrom(typeof(T))) @@ -3028,7 +3106,7 @@ override public int GetValues(object[] values) { statistics = SqlStatistics.StartTimer(Statistics); - if (null == values) + if (values == null) { throw ADP.ArgumentNull(nameof(values)); } @@ -3044,8 +3122,8 @@ override public int GetValues(object[] values) _commandBehavior &= ~CommandBehavior.SequentialAccess; // Read in all of the columns in one TryReadColumn call - bool result = TryReadColumn(maximumColumn, setTimeout: false); - if (!result) + TdsOperationStatus result = TryReadColumn(maximumColumn, setTimeout: false); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -3117,36 +3195,55 @@ private MetaType GetVersionedMetaType(MetaType actualMetaType) return metaType; } - private bool TryHasMoreResults(out bool moreResults) + private TdsOperationStatus TryHasMoreResults(out bool moreResults) { - if (null != _parser) + if (_parser != null) { bool moreRows; - if (!TryHasMoreRows(out moreRows)) + TdsOperationStatus result = TryHasMoreRows(out moreRows); + if (result != TdsOperationStatus.Done) { moreResults = false; - return false; + return result; } if (moreRows) { // When does this happen? This is only called from NextResult(), which loops until Read() false. moreResults = false; - return true; + return TdsOperationStatus.Done; } - Debug.Assert(null != _command, "unexpected null command from the data reader!"); + Debug.Assert(_command != null, "unexpected null command from the data reader!"); while (_stateObj.HasPendingData) { byte token; - if (!_stateObj.TryPeekByte(out token)) + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) { moreResults = false; - return false; + return result; } switch (token) { + case TdsEnums.SQLROW: + case TdsEnums.SQLNBCROW: + // always happens if there is a row following an altrow + moreResults = true; + return TdsOperationStatus.Done; + case TdsEnums.SQLDONE: + Debug.Assert(_altRowStatus == ALTROWSTATUS.Done || _altRowStatus == ALTROWSTATUS.Null, "invalid AltRowStatus"); + _altRowStatus = ALTROWSTATUS.Null; + _metaData = null; + _altMetaDataSetCollection = null; + moreResults = true; + return TdsOperationStatus.Done; + case TdsEnums.SQLCOLMETADATA: + moreResults = true; + return TdsOperationStatus.Done; + + // deprecated case TdsEnums.SQLALTROW: if (_altRowStatus == ALTROWSTATUS.Null) { @@ -3161,22 +3258,7 @@ private bool TryHasMoreResults(out bool moreResults) _altRowStatus = ALTROWSTATUS.AltRow; _hasRows = true; moreResults = true; - return true; - case TdsEnums.SQLROW: - case TdsEnums.SQLNBCROW: - // always happens if there is a row following an altrow - moreResults = true; - return true; - case TdsEnums.SQLDONE: - Debug.Assert(_altRowStatus == ALTROWSTATUS.Done || _altRowStatus == ALTROWSTATUS.Null, "invalid AltRowStatus"); - _altRowStatus = ALTROWSTATUS.Null; - _metaData = null; - _altMetaDataSetCollection = null; - moreResults = true; - return true; - case TdsEnums.SQLCOLMETADATA: - moreResults = true; - return true; + return TdsOperationStatus.Done; } // TryRun() will immediately return if the TdsParser is closed/broken, causing us to enter an infinite loop @@ -3186,26 +3268,26 @@ private bool TryHasMoreResults(out bool moreResults) throw ADP.ClosedConnectionError(); } - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out ignored)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { moreResults = false; - return false; + return result; } } } moreResults = false; - return true; + return TdsOperationStatus.Done; } - private bool TryHasMoreRows(out bool moreRows) + private TdsOperationStatus TryHasMoreRows(out bool moreRows) { - if (null != _parser) + if (_parser != null) { if (_sharedState._dataReady) { moreRows = true; - return true; + return TdsOperationStatus.Done; } // NextResult: previous call to NextResult started to process the altrowpackage, can't peek anymore @@ -3215,19 +3297,20 @@ private bool TryHasMoreRows(out bool moreRows) { case ALTROWSTATUS.AltRow: moreRows = true; - return true; + return TdsOperationStatus.Done; case ALTROWSTATUS.Done: moreRows = false; - return true; + return TdsOperationStatus.Done; } if (_stateObj.HasPendingData) { // Consume error's, info's, done's on HasMoreRows, so user obtains error on Read. byte b; - if (!_stateObj.TryPeekByte(out b)) + TdsOperationStatus result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { moreRows = false; - return false; + return result; } bool ParsedDoneToken = false; @@ -3255,18 +3338,19 @@ private bool TryHasMoreRows(out bool moreRows) throw ADP.ClosedConnectionError(); } - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out ignored)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { moreRows = false; - return false; + return result; } if (_stateObj.HasPendingData) { - if (!_stateObj.TryPeekByte(out b)) + result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { moreRows = false; - return false; + return result; } } else @@ -3279,12 +3363,12 @@ private bool TryHasMoreRows(out bool moreRows) if (IsRowToken(b)) { moreRows = true; - return true; + return TdsOperationStatus.Done; } } } moreRows = false; - return true; + return TdsOperationStatus.Done; } private bool IsRowToken(byte token) @@ -3321,12 +3405,10 @@ override public bool NextResult() } bool more; - bool result; Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - result = TryNextResult(out more); - - if (!result) + TdsOperationStatus result = TryNextResult(out more); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -3334,8 +3416,9 @@ override public bool NextResult() } // recordset is automatically positioned on the first result set - private bool TryNextResult(out bool more) + private TdsOperationStatus TryNextResult(out bool more) { + TdsOperationStatus result; SqlStatistics statistics = null; using (TryEventScope.Create("SqlDataReader.NextResult | API | Object Id {0}", ObjectID)) { @@ -3357,10 +3440,11 @@ private bool TryNextResult(out bool more) // if we are specifically only processing a single result, then read all the results off the wire and detach if (IsCommandBehavior(CommandBehavior.SingleResult)) { - if (!TryCloseInternal(false /*closeReader*/)) + result = TryCloseInternal(closeReader: false); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } // In the case of not closing the reader, null out the metadata AFTER @@ -3368,31 +3452,34 @@ private bool TryNextResult(out bool more) // and use the metadata. ClearMetaData(); more = success; - return true; + return TdsOperationStatus.Done; } - if (null != _parser) + if (_parser != null) { // if there are more rows, then skip them, the user wants the next result bool moreRows = true; while (moreRows) { - if (!TryReadInternal(false, out moreRows)) - { // don't reset set the timeout value + result = TryReadInternal(false, out moreRows); + if (result != TdsOperationStatus.Done) + { + // don't reset set the timeout value more = false; - return false; + return result; } } } // we may be done, so continue only if we have not detached ourselves from the parser - if (null != _parser) + if (_parser != null) { bool moreResults; - if (!TryHasMoreResults(out moreResults)) + result = TryHasMoreResults(out moreResults); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } if (moreResults) { @@ -3403,10 +3490,11 @@ private bool TryNextResult(out bool more) { case ALTROWSTATUS.AltRow: int altRowId; - if (!_parser.TryGetAltRowId(_stateObj, out altRowId)) + result = _parser.TryGetAltRowId(_stateObj, out altRowId); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } _SqlMetaDataSet altMetaDataSet = _altMetaDataSetCollection.GetAltMetaData(altRowId); if (altMetaDataSet != null) @@ -3422,15 +3510,16 @@ private bool TryNextResult(out bool more) _altRowStatus = ALTROWSTATUS.Null; break; default: - if (!TryConsumeMetaData()) + result = TryConsumeMetaData(); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } if (_metaData == null) { more = false; - return true; + return TdsOperationStatus.Done; } break; } @@ -3440,19 +3529,21 @@ private bool TryNextResult(out bool more) else { // detach the parser from this reader now - if (!TryCloseInternal(false /*closeReader*/)) + result = TryCloseInternal(closeReader: false); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return TdsOperationStatus.Done; } // In the case of not closing the reader, null out the metadata AFTER // CloseInternal finishes - since CloseInternal may go to the wire // and use the metadata. - if (!TrySetMetaData(null, false)) + result = TrySetMetaData(null, false); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } } @@ -3464,7 +3555,7 @@ private bool TryNextResult(out bool more) } more = success; - return true; + return TdsOperationStatus.Done; } finally { @@ -3483,12 +3574,11 @@ override public bool Read() } bool more; - bool result; Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - result = TryReadInternal(true, out more); + TdsOperationStatus result = TryReadInternal(true, out more); - if (!result) + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -3496,20 +3586,21 @@ override public bool Read() } // user must call Read() to position on the first row - private bool TryReadInternal(bool setTimeout, out bool more) + private TdsOperationStatus TryReadInternal(bool setTimeout, out bool more) { SqlStatistics statistics = null; using (TryEventScope.Create("SqlDataReader.TryReadInternal | API | Object Id {0}", ObjectID)) { -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try { + TdsOperationStatus result; statistics = SqlStatistics.StartTimer(Statistics); - if (null != _parser) + if (_parser != null) { if (setTimeout) { @@ -3517,10 +3608,11 @@ private bool TryReadInternal(bool setTimeout, out bool more) } if (_sharedState._dataReady) { - if (!TryCleanPartialRead()) + result = TryCleanPartialRead(); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } @@ -3535,10 +3627,11 @@ private bool TryReadInternal(bool setTimeout, out bool more) if (!_haltRead) { bool moreRows; - if (!TryHasMoreRows(out moreRows)) + result = TryHasMoreRows(out moreRows); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } if (moreRows) { @@ -3548,10 +3641,11 @@ private bool TryReadInternal(bool setTimeout, out bool more) if (_altRowStatus != ALTROWSTATUS.AltRow) { // if this is an ordinary row we let the run method consume the ROW token - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } if (_sharedState._dataReady) { @@ -3571,16 +3665,17 @@ private bool TryReadInternal(bool setTimeout, out bool more) { _haltRead = IsCommandBehavior(CommandBehavior.SingleRow); more = true; - return true; + return TdsOperationStatus.Done; } } if (!_stateObj.HasPendingData) { - if (!TryCloseInternal(false /*closeReader*/)) + result = TryCloseInternal(closeReader: false); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } } @@ -3590,10 +3685,11 @@ private bool TryReadInternal(bool setTimeout, out bool more) // success must be false - or else we could have just read off row and set // halt to true bool moreRows; - if (!TryHasMoreRows(out moreRows)) + result = TryHasMoreRows(out moreRows); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } while (moreRows) { @@ -3601,19 +3697,21 @@ private bool TryReadInternal(bool setTimeout, out bool more) // read the rest of the rows, if any while (_stateObj.HasPendingData && !_sharedState._dataReady) { - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } if (_sharedState._dataReady) { - if (!TryCleanPartialRead()) + result = TryCleanPartialRead(); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } @@ -3622,10 +3720,11 @@ private bool TryReadInternal(bool setTimeout, out bool more) _sharedState._nextColumnHeaderToRead = 0; - if (!TryHasMoreRows(out moreRows)) + result = TryHasMoreRows(out moreRows); + if (result != TdsOperationStatus.Done) { more = false; - return false; + return result; } } @@ -3643,16 +3742,17 @@ private bool TryReadInternal(bool setTimeout, out bool more) if ((!_sharedState._dataReady) && (_stateObj.HasPendingData)) { byte token; - if (!_stateObj.TryPeekByte(out token)) + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); } #endif - return true; + return TdsOperationStatus.Done; } catch (OutOfMemoryException e) { @@ -3702,14 +3802,14 @@ private void ReadColumn(int i, bool setTimeout = true, bool allowPartiallyReadCo } Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = TryReadColumn(i, setTimeout, allowPartiallyReadColumn); - if (!result) + TdsOperationStatus result = TryReadColumn(i, setTimeout, allowPartiallyReadColumn); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } } - private bool TryReadColumn(int i, bool setTimeout, bool allowPartiallyReadColumn = false, bool forStreaming = false) + private TdsOperationStatus TryReadColumn(int i, bool setTimeout, bool allowPartiallyReadColumn = false, bool forStreaming = false) { CheckDataIsReady(columnIndex: i, permitAsync: true, allowPartiallyReadColumn: allowPartiallyReadColumn, methodName: null); @@ -3721,17 +3821,18 @@ private bool TryReadColumn(int i, bool setTimeout, bool allowPartiallyReadColumn SetTimeout(_defaultTimeoutMilliseconds); } - if (!TryReadColumnInternal(i, readHeaderOnly: false, forStreaming: forStreaming)) + TdsOperationStatus result = TryReadColumnInternal(i, readHeaderOnly: false, forStreaming: forStreaming); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - Debug.Assert(null != _data[i], " data buffer is null?"); + Debug.Assert(_data[i] != null, " data buffer is null?"); - return true; + return TdsOperationStatus.Done; } - private bool TryReadColumnData() + private TdsOperationStatus TryReadColumnData() { // If we've already read the value (because it was NULL) we don't // bother to read here. @@ -3739,29 +3840,31 @@ private bool TryReadColumnData() { _SqlMetaData columnMetaData = _metaData[_sharedState._nextColumnDataToRead]; - if (!_parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)_sharedState._columnDataBytesRemaining, _stateObj, + TdsOperationStatus result = _parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)_sharedState._columnDataBytesRemaining, _stateObj, _command != null ? _command.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting, - columnMetaData.column)) - { // will read UDTs as VARBINARY. - return false; + columnMetaData.column, _command); + if (result != TdsOperationStatus.Done) + { + // will read UDTs as VARBINARY. + return result; } _sharedState._columnDataBytesRemaining = 0; } _sharedState._nextColumnDataToRead++; - return true; + return TdsOperationStatus.Done; } private void ReadColumnHeader(int i) { Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = TryReadColumnHeader(i); - if (!result) + TdsOperationStatus result = TryReadColumnHeader(i); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } } - private bool TryReadColumnHeader(int i) + private TdsOperationStatus TryReadColumnHeader(int i) { if (!_sharedState._dataReady) { @@ -3770,7 +3873,7 @@ private bool TryReadColumnHeader(int i) return TryReadColumnInternal(i, readHeaderOnly: true); } - internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool forStreaming = false) + internal TdsOperationStatus TryReadColumnInternal(int i, bool readHeaderOnly = false, bool forStreaming = false) { AssertReaderState(requireData: true, permitAsync: true, columnIndex: i); @@ -3792,7 +3895,7 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for (_metaData[i].type == SqlDbType.Timestamp), // Or SqlClient: IsDBNull always returns false for timestamp datatype "Gone past column, be we have no data stored for it"); - return true; + return TdsOperationStatus.Done; } } @@ -3800,6 +3903,7 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for // If we're in sequential access mode, we can safely clear out any // data from the previous column. + TdsOperationStatus result; bool isSequentialAccess = IsCommandBehavior(CommandBehavior.SequentialAccess); if (isSequentialAccess) { @@ -3817,17 +3921,19 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for else if (_sharedState._nextColumnDataToRead < _sharedState._nextColumnHeaderToRead) { // We read the header but not the column for the previous column - if (!TryReadColumnData()) + result = TryReadColumnData(); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(_sharedState._nextColumnDataToRead == _sharedState._nextColumnHeaderToRead); } // if we still have bytes left from the previous blob read, clear the wire and reset - if (!TryResetBlobState()) + result = TryResetBlobState(); + if (result != TdsOperationStatus.Done) { - return false; + return result; } do @@ -3840,9 +3946,10 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for { // SkipValue is no-op if the column appears in NBC bitmask // if not, it skips regular and PLP types - if (!_parser.TrySkipValue(columnMetaData, _sharedState._nextColumnHeaderToRead, _stateObj)) + result = _parser.TrySkipValue(columnMetaData, _sharedState._nextColumnHeaderToRead, _stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _sharedState._nextColumnDataToRead = _sharedState._nextColumnHeaderToRead; @@ -3852,9 +3959,10 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for { bool isNull; ulong dataLength; - if (!_parser.TryProcessColumnHeader(columnMetaData, _stateObj, _sharedState._nextColumnHeaderToRead, out isNull, out dataLength)) + result = _parser.TryProcessColumnHeader(columnMetaData, _stateObj, _sharedState._nextColumnHeaderToRead, out isNull, out dataLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _sharedState._nextColumnDataToRead = _sharedState._nextColumnHeaderToRead; @@ -3877,11 +3985,13 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for { // If we're in sequential mode try to read the data and then if it succeeds update shared // state so there are no remaining bytes and advance the next column to read - if (!_parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)dataLength, _stateObj, + result = _parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)dataLength, _stateObj, _command != null ? _command.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting, - columnMetaData.column)) - { // will read UDTs as VARBINARY. - return false; + columnMetaData.column); + if (result != TdsOperationStatus.Done) + { + // will read UDTs as VARBINARY. + return result; } _sharedState._columnDataBytesRemaining = 0; _sharedState._nextColumnDataToRead++; @@ -3894,7 +4004,6 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for } else { - // we have read past the column somehow, this is an error Debug.Assert(false, "We have read past the column somehow, this is an error"); } } @@ -3902,9 +4011,10 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for { bool isNull; ulong dataLength; - if (!_parser.TryProcessColumnHeader(columnMetaData, _stateObj, _sharedState._nextColumnHeaderToRead, out isNull, out dataLength)) + result = _parser.TryProcessColumnHeader(columnMetaData, _stateObj, _sharedState._nextColumnHeaderToRead, out isNull, out dataLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _sharedState._nextColumnDataToRead = _sharedState._nextColumnHeaderToRead; @@ -3931,11 +4041,13 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for // If we're not in sequential access mode, we have to // save the data we skip over so that the consumer // can read it out of order - if (!_parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)dataLength, _stateObj, + result = _parser.TryReadSqlValue(_data[_sharedState._nextColumnDataToRead], columnMetaData, (int)dataLength, _stateObj, _command != null ? _command.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting, - columnMetaData.column, _command)) - { // will read UDTs as VARBINARY. - return false; + columnMetaData.column, _command); + if (result != TdsOperationStatus.Done) + { + // will read UDTs as VARBINARY. + return result; } _sharedState._nextColumnDataToRead++; } @@ -3959,7 +4071,7 @@ internal bool TryReadColumnInternal(int i, bool readHeaderOnly = false, bool for } } while (_sharedState._nextColumnHeaderToRead <= i); - return true; + return TdsOperationStatus.Done; } // Estimates if there is enough data available to read the number of columns requested @@ -4048,12 +4160,12 @@ private bool WillHaveEnoughData(int targetColumn, bool headerOnly = false) } // clean remainder bytes for the column off the wire - private bool TryResetBlobState() + private TdsOperationStatus TryResetBlobState() { - Debug.Assert(null != _stateObj, "null state object"); // _parser may be null at this point + Debug.Assert(_stateObj != null, "null state object"); // _parser may be null at this point AssertReaderState(requireData: true, permitAsync: true); Debug.Assert(_sharedState._nextColumnHeaderToRead <= _metaData.Length, "_sharedState._nextColumnHeaderToRead too large"); - + TdsOperationStatus result; // If we haven't already entirely read the column if (_sharedState._nextColumnDataToRead < _sharedState._nextColumnHeaderToRead) { @@ -4061,10 +4173,10 @@ private bool TryResetBlobState() { if (_stateObj._longlen != 0) { - ulong ignored; - if (!_stateObj.Parser.TrySkipPlpValue(ulong.MaxValue, _stateObj, out ignored)) + result = _stateObj.Parser.TrySkipPlpValue(ulong.MaxValue, _stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } if (_streamingXml != null) @@ -4076,9 +4188,10 @@ private bool TryResetBlobState() } else if (0 < _sharedState._columnDataBytesRemaining) { - if (!_stateObj.TrySkipLongBytes(_sharedState._columnDataBytesRemaining)) + result = _stateObj.TrySkipLongBytes(_sharedState._columnDataBytesRemaining); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } } @@ -4096,7 +4209,7 @@ private bool TryResetBlobState() _columnDataCharsIndex = -1; _stateObj._plpdecoder = null; - return true; + return TdsOperationStatus.Done; } private void CloseActiveSequentialStreamAndTextReader() @@ -4116,7 +4229,7 @@ private void CloseActiveSequentialStreamAndTextReader() private void RestoreServerSettings(TdsParser parser, TdsParserStateObject stateObj) { // turn off any set options - if (null != parser && null != _resetOptionsString) + if (parser != null && _resetOptionsString != null) { // It is possible for this to be called during connection close on a // broken connection, so check state first. @@ -4133,7 +4246,7 @@ private void RestoreServerSettings(TdsParser parser, TdsParserStateObject stateO } } - internal bool TrySetAltMetaDataSet(_SqlMetaDataSet metaDataSet, bool metaDataConsumed) + internal TdsOperationStatus TrySetAltMetaDataSet(_SqlMetaDataSet metaDataSet, bool metaDataConsumed) { if (_altMetaDataSetCollection == null) { @@ -4145,23 +4258,25 @@ internal bool TrySetAltMetaDataSet(_SqlMetaDataSet metaDataSet, bool metaDataCon } _altMetaDataSetCollection.SetAltMetaData(metaDataSet); _metaDataConsumed = metaDataConsumed; - if (_metaDataConsumed && null != _parser) + if (_metaDataConsumed && _parser != null) { byte b; - if (!_stateObj.TryPeekByte(out b)) + TdsOperationStatus result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (TdsEnums.SQLORDER == b) { - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out ignored)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!_stateObj.TryPeekByte(out b)) + result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } if (b == TdsEnums.SQLINFO) @@ -4169,19 +4284,21 @@ internal bool TrySetAltMetaDataSet(_SqlMetaDataSet metaDataSet, bool metaDataCon try { _stateObj._accumulateInfoEvents = true; - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, null, null, _stateObj, out ignored)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, null, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } finally { _stateObj._accumulateInfoEvents = false; } - if (!_stateObj.TryPeekByte(out b)) + + result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } _hasRows = IsRowToken(b); @@ -4193,7 +4310,7 @@ internal bool TrySetAltMetaDataSet(_SqlMetaDataSet metaDataSet, bool metaDataCon _data = SqlBuffer.CreateBufferArray(metaDataSet.Length); } } - return true; + return TdsOperationStatus.Done; } private void ClearMetaData() @@ -4205,13 +4322,13 @@ private void ClearMetaData() _browseModeInfoConsumed = false; } - internal bool TrySetSensitivityClassification(SensitivityClassification sensitivityClassification) + internal TdsOperationStatus TrySetSensitivityClassification(SensitivityClassification sensitivityClassification) { SensitivityClassification = sensitivityClassification; - return true; + return TdsOperationStatus.Done; } - internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) + internal TdsOperationStatus TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) { _metaData = metaData; @@ -4224,7 +4341,7 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) _fieldNameLookup = null; - if (null != metaData) + if (metaData != null) { // we are done consuming metadata only if there is no moreInfo if (!moreInfo) @@ -4236,22 +4353,25 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) // Peek, and if row token present, set _hasRows true since there is a // row in the result byte b; - if (!_stateObj.TryPeekByte(out b)) + TdsOperationStatus result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } // simply rip the order token off the wire if (b == TdsEnums.SQLORDER) - { // same logic as SetAltMetaDataSet - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, null, null, null, _stateObj, out ignored)) + { + // same logic as SetAltMetaDataSet + result = _parser.TryRun(RunBehavior.ReturnImmediately, null, null, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!_stateObj.TryPeekByte(out b)) + result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } if (b == TdsEnums.SQLINFO) @@ -4262,19 +4382,21 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) try { _stateObj._accumulateInfoEvents = true; - bool ignored; - if (!_parser.TryRun(RunBehavior.ReturnImmediately, null, null, null, _stateObj, out ignored)) + result = _parser.TryRun(RunBehavior.ReturnImmediately, null, null, null, _stateObj, out _); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } finally { _stateObj._accumulateInfoEvents = false; } - if (!_stateObj.TryPeekByte(out b)) + + result = _stateObj.TryPeekByte(out b); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } _hasRows = IsRowToken(b); @@ -4291,7 +4413,7 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo) } _browseModeInfoConsumed = false; - return true; + return TdsOperationStatus.Done; } private void SetTimeout(long timeoutMilliseconds) @@ -4299,7 +4421,7 @@ private void SetTimeout(long timeoutMilliseconds) // WebData 111653,112003 -- we now set timeouts per operation, not // per command (it's not supposed to be a cumulative per command). TdsParserStateObject stateObj = _stateObj; - if (null != stateObj) + if (stateObj != null) { stateObj.SetTimeoutMilliseconds(timeoutMilliseconds); } @@ -4476,7 +4598,7 @@ private static Task NextResultAsyncExecute(Task task, object state) context.Reader.PrepareForAsyncContinuation(); } - if (context.Reader.TryNextResult(out bool more)) + if (context.Reader.TryNextResult(out bool more) == TdsOperationStatus.Done) { // completed return more ? ADP.TrueTask : ADP.FalseTask; @@ -4586,7 +4708,7 @@ private static Task GetBytesAsyncSeekExecute(Task task, object state) // Prepare for stateObj timeout reader.SetTimeout(reader._defaultTimeoutMilliseconds); - if (reader.TryReadColumnHeader(context._columnIndex)) + if (reader.TryReadColumnHeader(context._columnIndex) == TdsOperationStatus.Done) { // Only once we have read up to where we need to be can we check the cancellation tokens (otherwise we will be in an unknown state) @@ -4649,7 +4771,7 @@ private static Task GetBytesAsyncReadExecute(Task task, object state) reader.SetTimeout(reader._defaultTimeoutMilliseconds); int bytesReadThisIteration; - bool result = reader.TryGetBytesInternalSequential( + TdsOperationStatus result = reader.TryGetBytesInternalSequential( context._columnIndex, context._buffer, context._index + context._totalBytesRead, @@ -4659,7 +4781,7 @@ out bytesReadThisIteration context._totalBytesRead += bytesReadThisIteration; Debug.Assert(context._totalBytesRead <= context._length, "Read more bytes than required"); - if (result) + if (result == TdsOperationStatus.Done) { return Task.FromResult(context._totalBytesRead); } @@ -4681,7 +4803,7 @@ private Task GetBytesAsyncReadDataStage(GetBytesAsyncCallContext context, b SetTimeout(_defaultTimeoutMilliseconds); // Try to read without any continuations (all the data may already be in the stateObj's buffer) - bool filledBuffer = context.Reader.TryGetBytesInternalSequential( + TdsOperationStatus filledBuffer = context.Reader.TryGetBytesInternalSequential( context._columnIndex, context._buffer, context._index + context._totalBytesRead, @@ -4691,7 +4813,7 @@ out bytesRead context._totalBytesRead += bytesRead; Debug.Assert(context._totalBytesRead <= context._length, "Read more bytes than required"); - if (!filledBuffer) + if (filledBuffer != TdsOperationStatus.Done) { // This will be the 'state' for the callback if (!isContinuation) @@ -4809,8 +4931,8 @@ public override Task ReadAsync(CancellationToken cancellationToken) if (_stateObj.IsRowTokenReady()) { // Read the ROW token - bool result = TryReadInternal(true, out more); - Debug.Assert(result, "Should not have run out of data"); + TdsOperationStatus result = TryReadInternal(true, out more); + Debug.Assert(result == TdsOperationStatus.Done, "Should not have run out of data"); rowTokenRead = true; if (more) @@ -4825,7 +4947,7 @@ public override Task ReadAsync(CancellationToken cancellationToken) { // Read row data result = TryReadColumn(_metaData.Length - 1, setTimeout: true); - Debug.Assert(result, "Should not have run out of data"); + Debug.Assert(result == TdsOperationStatus.Done, "Should not have run out of data"); return ADP.TrueTask; } } @@ -4903,7 +5025,7 @@ private static Task ReadAsyncExecute(Task task, object state) reader.PrepareForAsyncContinuation(); } - if (hasReadRowToken || reader.TryReadInternal(true, out hasMoreData)) + if (hasReadRowToken || (reader.TryReadInternal(true, out hasMoreData) == TdsOperationStatus.Done)) { // If there are no more rows, or this is Sequential Access, then we are done if (!hasMoreData || (reader._commandBehavior & CommandBehavior.SequentialAccess) == CommandBehavior.SequentialAccess) @@ -4926,7 +5048,8 @@ private static Task ReadAsyncExecute(Task task, object state) } // if non-sequentialaccess then read entire row before returning - if (reader.TryReadColumn(reader._metaData.Length - 1, true)) + TdsOperationStatus result = reader.TryReadColumn(reader._metaData.Length - 1, true); + if (result == TdsOperationStatus.Done) { // completed return ADP.TrueTask; @@ -5077,7 +5200,8 @@ private static Task IsDBNullAsyncExecute(Task task, object state) reader.PrepareForAsyncContinuation(); } - if (reader.TryReadColumnHeader(context._columnIndex)) + TdsOperationStatus result = reader.TryReadColumnHeader(context._columnIndex); + if (result == TdsOperationStatus.Done) { return reader._data[context._columnIndex].IsNull ? ADP.TrueTask : ADP.FalseTask; } @@ -5109,7 +5233,7 @@ override public Task GetFieldValueAsync(int i, CancellationToken cancellat var metaData = _metaData; if ((data != null) && (metaData != null)) { - return Task.FromResult(GetFieldValueFromSqlBufferInternal(data[i], metaData[i], isAsync:false)); + return Task.FromResult(GetFieldValueFromSqlBufferInternal(data[i], metaData[i], isAsync: false)); } else { @@ -5149,7 +5273,7 @@ override public Task GetFieldValueAsync(int i, CancellationToken cancellat { _stateObj._shouldHaveEnoughData = true; #endif - return Task.FromResult(GetFieldValueInternal(i, isAsync:true)); + return Task.FromResult(GetFieldValueInternal(i, isAsync: true)); #if DEBUG } finally @@ -5215,15 +5339,22 @@ private static Task GetFieldValueAsyncExecute(Task task, object state) if (typeof(T) == typeof(Stream) || typeof(T) == typeof(TextReader) || typeof(T) == typeof(XmlReader)) { - if (reader.IsCommandBehavior(CommandBehavior.SequentialAccess) && reader._sharedState._dataReady && reader.TryReadColumnInternal(context._columnIndex, readHeaderOnly: true)) + if (reader.IsCommandBehavior(CommandBehavior.SequentialAccess) && reader._sharedState._dataReady) { - return Task.FromResult(reader.GetFieldValueFromSqlBufferInternal(reader._data[columnIndex], reader._metaData[columnIndex], isAsync: true)); + bool internalReadSuccess = false; + internalReadSuccess = reader.TryReadColumnInternal(context._columnIndex, readHeaderOnly: true) == TdsOperationStatus.Done; + + if (internalReadSuccess) + { + return Task.FromResult(reader.GetFieldValueFromSqlBufferInternal(reader._data[columnIndex], reader._metaData[columnIndex], isAsync: true)); + } } } - if (reader.TryReadColumn(columnIndex, setTimeout: false)) + TdsOperationStatus result = reader.TryReadColumn(columnIndex, setTimeout: false); + if (result == TdsOperationStatus.Done) { - return Task.FromResult(reader.GetFieldValueFromSqlBufferInternal(reader._data[columnIndex], reader._metaData[columnIndex], isAsync:false)); + return Task.FromResult(reader.GetFieldValueFromSqlBufferInternal(reader._data[columnIndex], reader._metaData[columnIndex], isAsync: false)); } else { @@ -5589,7 +5720,7 @@ private void CompleteAsyncCall(Task task, SqlDataReaderBaseAsyncCallContex } - internal class Snapshot + internal sealed class Snapshot { public bool _dataReady; public bool _haltRead; @@ -5759,17 +5890,17 @@ public ReadOnlyCollection GetColumnSchema() try { statistics = SqlStatistics.StartTimer(Statistics); - if (null == _metaData || null == _metaData.dbColumnSchema) + if (_metaData == null || _metaData.dbColumnSchema == null) { - if (null != this.MetaData) + if (this.MetaData != null) { _metaData.dbColumnSchema = BuildColumnSchema(); - Debug.Assert(null != _metaData.dbColumnSchema, "No schema information yet!"); + Debug.Assert(_metaData.dbColumnSchema != null, "No schema information yet!"); // filter table? } } - if (null != _metaData) + if (_metaData != null) { return _metaData.dbColumnSchema; } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetCoreApp.cs index c4655c4355..561f9bd6fb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetCoreApp.cs @@ -7,7 +7,7 @@ namespace Microsoft.Data.SqlClient { - sealed internal partial class SqlDelegatedTransaction : IPromotableSinglePhaseNotification + internal sealed partial class SqlDelegatedTransaction : IPromotableSinglePhaseNotification { // Get the server-side Global Transaction Id from the PromotedDTCToken // Skip first 4 bytes since they contain the version diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetStandard.cs deleted file mode 100644 index cb97c4d677..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.NetStandard.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Transactions; - -namespace Microsoft.Data.SqlClient -{ - sealed internal partial class SqlDelegatedTransaction : IPromotableSinglePhaseNotification - { - // Get the server-side Global Transaction Id from the PromotedDTCToken - // Skip first 4 bytes since they contain the version - private Guid GetGlobalTxnIdentifierFromToken() - { - byte[] txnGuid = new byte[16]; - Array.Copy(_connection.PromotedDTCToken, _globalTransactionsTokenVersionSizeInBytes, // Skip the version - txnGuid, 0, txnGuid.Length); - return new Guid(txnGuid); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs index 680b34079d..6b99b1dfdc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDelegatedTransaction.cs @@ -34,7 +34,7 @@ sealed internal partial class SqlDelegatedTransaction : IPromotableSinglePhaseNo internal SqlDelegatedTransaction(SqlInternalConnection connection, Transaction tx) { - Debug.Assert(null != connection, "null connection?"); + Debug.Assert(connection != null, "null connection?"); _connection = connection; _atomicTransaction = tx; _active = false; @@ -81,7 +81,7 @@ public void Initialize() SqlInternalConnection connection = _connection; SqlConnection usersConnection = connection.Connection; SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.Initialize | RES | CPOOL | Object Id {0}, Client Connection Id {1}, delegating transaction.", ObjectID, usersConnection?.ClientConnectionId); -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -99,7 +99,7 @@ public void Initialize() connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Begin, null, _isolationLevel, _internalTransaction, true); // Handle case where ExecuteTran didn't produce a new transaction, but also didn't throw. - if (null == connection.CurrentTransaction) + if (connection.CurrentTransaction == null) { connection.DoomThisConnection(); throw ADP.InternalError(ADP.InternalErrorCode.UnknownTransactionFailure); @@ -142,11 +142,11 @@ public byte[] Promote() Exception promoteException; byte[] returnValue = null; - if (null != connection) + if (connection != null) { SqlConnection usersConnection = connection.Connection; SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.Promote | RES | CPOOL | Object Id {0}, Client Connection Id {1}, promoting transaction.", ObjectID, usersConnection?.ClientConnectionId); -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -159,17 +159,17 @@ public byte[] Promote() ValidateActiveOnConnection(connection); connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Promote, null, System.Data.IsolationLevel.Unspecified, _internalTransaction, true); - returnValue = _connection.PromotedDTCToken; + returnValue = connection.PromotedDTCToken; // For Global Transactions, we need to set the Transaction Id since we use a Non-MSDTC Promoter type. - if (_connection.IsGlobalTransaction) + if (connection.IsGlobalTransaction) { if (SysTxForGlobalTransactions.SetDistributedTransactionIdentifier == null) { throw SQL.UnsupportedSysTxForGlobalTransactions(); } - if (!_connection.IsGlobalTransactionsEnabledForServer) + if (!connection.IsGlobalTransactionsEnabledForServer) { throw SQL.GlobalTransactionsNotEnabled(); } @@ -249,14 +249,14 @@ public byte[] Promote() // Called by transaction to initiate abort sequence public void Rollback(SinglePhaseEnlistment enlistment) { - Debug.Assert(null != enlistment, "null enlistment?"); + Debug.Assert(enlistment != null, "null enlistment?"); SqlInternalConnection connection = GetValidConnection(); - if (null != connection) + if (connection != null) { SqlConnection usersConnection = connection.Connection; SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.Rollback | RES | CPOOL | Object Id {0}, Client Connection Id {1}, rolling back transaction.", ObjectID, usersConnection?.ClientConnectionId); -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -336,33 +336,35 @@ public void Rollback(SinglePhaseEnlistment enlistment) // Called by the transaction to initiate commit sequence public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) { - Debug.Assert(null != enlistment, "null enlistment?"); + Debug.Assert(enlistment != null, "null enlistment?"); SqlInternalConnection connection = GetValidConnection(); - if (null != connection) + if (connection != null) { SqlConnection usersConnection = connection.Connection; SqlClientEventSource.Log.TryTraceEvent("SqlDelegatedTransaction.SinglePhaseCommit | RES | CPOOL | Object Id {0}, Client Connection Id {1}, committing transaction.", ObjectID, usersConnection?.ClientConnectionId); -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try { - Exception commitException = null; - - lock (connection) + // If the connection is doomed, we can be certain that the + // transaction will eventually be rolled back or has already been aborted externally, and we shouldn't + // attempt to commit it. + if (connection.IsConnectionDoomed) { - // If the connection is doomed, we can be certain that the - // transaction will eventually be rolled back or has already been aborted externally, and we shouldn't - // attempt to commit it. - if (connection.IsConnectionDoomed) + lock (connection) { _active = false; // set to inactive first, doesn't matter how the rest completes, this transaction is done. _connection = null; - - enlistment.Aborted(SQL.ConnectionDoomed()); } - else + + enlistment.Aborted(SQL.ConnectionDoomed()); + } + else + { + Exception commitException; + lock (connection) { try { @@ -370,7 +372,7 @@ public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) ValidateActiveOnConnection(connection); _active = false; // set to inactive first, doesn't matter how the rest completes, this transaction is done. - _connection = null; // Set prior to ExecuteTransaction call in case this initiates a TransactionEnd event + _connection = null; // Set prior to ExecuteTransaction call in case this initiates a TransactionEnd event connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, System.Data.IsolationLevel.Unspecified, _internalTransaction, true); } @@ -391,35 +393,40 @@ public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) ADP.TraceExceptionWithoutRethrow(e); connection.DoomThisConnection(); } - if (commitException != null) + } + if (commitException != null) + { + // connection.ExecuteTransaction failed with exception + if (_internalTransaction.IsCommitted) { - // connection.ExecuteTransaction failed with exception - if (_internalTransaction.IsCommitted) - { - // Even though we got an exception, the transaction - // was committed by the server. - enlistment.Committed(); - } - else if (_internalTransaction.IsAborted) - { - // The transaction was aborted, report that to - // SysTx. - enlistment.Aborted(commitException); - } - else - { - // The transaction is still active, we cannot - // know the state of the transaction. - enlistment.InDoubt(commitException); - } - - // We eat the exception. This is called on the SysTx - // thread, not the applications thread. If we don't - // eat the exception an UnhandledException will occur, - // causing the process to FailFast. + // Even though we got an exception, the transaction + // was committed by the server. + enlistment.Committed(); + } + else if (_internalTransaction.IsAborted) + { + // The transaction was aborted, report that to + // SysTx. + enlistment.Aborted(commitException); + } + else + { + // The transaction is still active, we cannot + // know the state of the transaction. + enlistment.InDoubt(commitException); } - connection.CleanupConnectionOnTransactionCompletion(_atomicTransaction); + // We eat the exception. This is called on the SysTx + // thread, not the applications thread. If we don't + // eat the exception an UnhandledException will occur, + // causing the process to FailFast. + } + + connection.CleanupConnectionOnTransactionCompletion(_atomicTransaction); + if (commitException == null) + { + // connection.ExecuteTransaction succeeded + enlistment.Committed(); } } @@ -483,7 +490,7 @@ internal void TransactionEnded(Transaction transaction) private SqlInternalConnection GetValidConnection() { SqlInternalConnection connection = _connection; - if (null == connection && Transaction.TransactionInformation.Status != TransactionStatus.Aborted) + if (connection == null && Transaction.TransactionInformation.Status != TransactionStatus.Aborted) { throw ADP.ObjectDisposed(this); } @@ -502,11 +509,11 @@ private void ValidateActiveOnConnection(SqlInternalConnection connection) { // Invalid indicates something BAAAD happened (Commit after TransactionEnded, for instance) // Doom anything remotely involved. - if (null != connection) + if (connection != null) { connection.DoomThisConnection(); } - if (connection != _connection && null != _connection) + if (connection != _connection && _connection != null) { _connection.DoomThisConnection(); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 6a0ee2e0e0..1f7cb869b1 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -109,6 +109,10 @@ internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposa // CONNECTION AND STATE VARIABLES private readonly SqlConnectionPoolGroupProviderInfo _poolGroupProviderInfo; // will only be null when called for ChangePassword, or creating SSE User Instance private TdsParser _parser; + + // Connection re-route limit + internal const int _maxNumberOfRedirectRoute = 10; + private SqlLoginAck _loginAck; private SqlCredential _credential; private FederatedAuthenticationFeatureExtensionData _fedAuthFeatureExtensionData; @@ -130,10 +134,9 @@ internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposa // The Federated Authentication returned by TryGetFedAuthTokenLocked or GetFedAuthToken. SqlFedAuthToken _fedAuthToken = null; internal byte[] _accessTokenInBytes; - internal readonly Func> _accessTokenCallback; + internal readonly Func> _accessTokenCallback; private readonly ActiveDirectoryAuthenticationTimeoutRetryHelper _activeDirectoryAuthTimeoutRetryHelper; - private readonly SqlAuthenticationProviderManager _sqlAuthenticationProviderManager; internal bool _cleanSQLDNSCaching = false; private bool _serverSupportsDNSCaching = false; @@ -201,6 +204,9 @@ internal bool IsDNSCachingBeforeRedirectSupported internal SQLDNSInfo pendingSQLDNSObject = null; + // Json Support Flag + internal bool IsJsonSupportEnabled = false; + // TCE flags internal byte _tceVersionSupported; @@ -484,7 +490,6 @@ internal SqlInternalConnectionTds( _accessTokenCallback = accessTokenCallback; _activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper(); - _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.Instance; _identity = identity; Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null"); @@ -643,7 +648,7 @@ internal protected override bool IsNonPoolableTransactionRoot { get { - return IsTransactionRoot && (!Is2008OrNewer || null == Pool); + return IsTransactionRoot && (!Is2008OrNewer || Pool == null); } } @@ -691,7 +696,7 @@ protected override bool ReadyToPrepareTransaction { get { - bool result = (null == FindLiveReader(null)); // can't prepare with a live data reader... + bool result = FindLiveReader(null) == null; // can't prepare with a live data reader... return result; } } @@ -747,7 +752,7 @@ public override void Dispose() TdsParser parser = Interlocked.Exchange(ref _parser, null); // guard against multiple concurrent dispose calls -- Delegated Transactions might cause this. Debug.Assert(parser != null && _fConnectionOpen || parser == null && !_fConnectionOpen, "Unexpected state on dispose"); - if (null != parser) + if (parser != null) { parser.Disconnect(); } @@ -774,7 +779,7 @@ internal override void ValidateConnectionForExecute(SqlCommand command) SqlDataReader reader = null; if (parser.MARSOn) { - if (null != command) + if (command != null) { // command can't have datareader already associated with it reader = FindLiveReader(command); } @@ -788,7 +793,7 @@ internal override void ValidateConnectionForExecute(SqlCommand command) reader = FindLiveReader(null); } - if (null != reader) + if (reader != null) { // if MARS is on, then a datareader associated with the command exists // or if MARS is off, then a datareader exists @@ -884,7 +889,7 @@ protected override void Activate(Transaction transaction) // Regardless of whether we're required to automatically enlist, // when there is not a current transaction, we cannot leave the // connection enlisted in a transaction. - if (null != transaction) + if (transaction != null) { if (ConnectionOptions.Enlist) { @@ -915,7 +920,7 @@ protected override void InternalDeactivate() // transaction is completed and we can do it all then. if (!IsNonPoolableTransactionRoot) { - Debug.Assert(null != _parser || IsConnectionDoomed, "Deactivating a disposed connection?"); + Debug.Assert(_parser != null || IsConnectionDoomed, "Deactivating a disposed connection?"); if (_parser != null) { _parser.Deactivate(IsConnectionDoomed); @@ -973,7 +978,7 @@ internal override void DisconnectTransaction(SqlInternalTransaction internalTran { TdsParser parser = Parser; - if (null != parser) + if (parser != null) { parser.DisconnectTransaction(internalTransaction); } @@ -1006,7 +1011,7 @@ internal override void ExecuteTransaction(TransactionRequest transactionRequest, } } - string transactionName = (null == name) ? string.Empty : name; + string transactionName = name == null ? string.Empty : name; ExecuteTransaction2005(transactionRequest, transactionName, iso, internalTransaction, isDelegateControlRequest); } @@ -1122,7 +1127,7 @@ bool isDelegateControlRequest // an object that the ExecTMReq will also lock, but since we're on // the same thread, the lock is a no-op. - if (null != internalTransaction && internalTransaction.IsDelegated) + if (internalTransaction != null && internalTransaction.IsDelegated) { if (_parser.MARSOn) { @@ -1171,7 +1176,7 @@ internal override void DelegatedTransactionEnded() protected override byte[] GetDTCAddress() { byte[] dtcAddress = _parser.GetDTCAddress(ConnectionOptions.ConnectTimeout, _parser.GetSession(this)); - Debug.Assert(null != dtcAddress, "null dtcAddress?"); + Debug.Assert(dtcAddress != null, "null dtcAddress?"); return dtcAddress; } @@ -1330,6 +1335,7 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword, || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryMSI || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryDefault + || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity // Since AD Integrated may be acting like Windows integrated, additionally check _fedAuthRequired || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && _fedAuthRequired) || _accessTokenCallback != null) @@ -1361,9 +1367,15 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword, // The GLOBALTRANSACTIONS, DATACLASSIFICATION, TCE, and UTF8 support features are implicitly requested requestedFeatures |= TdsEnums.FeatureExtension.GlobalTransactions | TdsEnums.FeatureExtension.DataClassification | TdsEnums.FeatureExtension.Tce | TdsEnums.FeatureExtension.UTF8Support; + // The AzureSQLSupport feature is implicitly set for ReadOnly login + if (ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly) + { + requestedFeatures |= TdsEnums.FeatureExtension.AzureSQLSupport; + } + // The SQLDNSCaching feature is implicitly set requestedFeatures |= TdsEnums.FeatureExtension.SQLDNSCaching; - + requestedFeatures |= TdsEnums.FeatureExtension.JsonSupport; _parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData, encrypt); } @@ -1392,7 +1404,7 @@ private void OpenLoginEnlist(TimeoutTimer timeout, ServerInfo dataSource = new ServerInfo(connectionOptions); string failoverPartner; - if (null != PoolGroupProviderInfo) + if (PoolGroupProviderInfo != null) { useFailoverPartner = PoolGroupProviderInfo.UseFailoverPartner; failoverPartner = PoolGroupProviderInfo.FailoverPartner; @@ -1438,6 +1450,23 @@ private void OpenLoginEnlist(TimeoutTimer timeout, credential, timeout); } + + if (!IsAzureSQLConnection) + { + // If not a connection to Azure SQL, Readonly with FailoverPartner is not supported + if (ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly) + { + if (!string.IsNullOrEmpty(ConnectionOptions.FailoverPartner)) + { + throw SQL.ROR_FailoverNotSupportedConnString(); + } + + if (ServerProvidedFailOverPartner != null) + { + throw SQL.ROR_FailoverNotSupportedServer(this); + } + } + } _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin); } catch (Exception e) @@ -1545,7 +1574,7 @@ private void LoginNoFailover(ServerInfo serverInfo, newSecurePassword, connectionOptions.MultiSubnetFailover ? intervalTimer : timeout); - if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) + if (connectionOptions.MultiSubnetFailover && ServerProvidedFailOverPartner != null) { // connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this); @@ -1554,9 +1583,9 @@ private void LoginNoFailover(ServerInfo serverInfo, if (RoutingInfo != null) { SqlClientEventSource.Log.TryTraceEvent(" Routed to {0}", serverInfo.ExtendedServerName); - if (routingAttempts > 0) + if (routingAttempts > _maxNumberOfRedirectRoute) { - throw SQL.ROR_RecursiveRoutingNotSupported(this); + throw SQL.ROR_RecursiveRoutingNotSupported(this, _maxNumberOfRedirectRoute); } if (timeout.IsExpired) @@ -1592,12 +1621,13 @@ private void LoginNoFailover(ServerInfo serverInfo, continue; } - if (null == _parser - || TdsParserState.Closed != _parser.State - || IsDoNotRetryConnectError(sqlex) - || timeout.IsExpired) - { // no more time to try again - throw; // Caller will call LoginFailure() + if (_parser == null + || TdsParserState.Closed != _parser.State + || IsDoNotRetryConnectError(sqlex) + || timeout.IsExpired) + { + // no more time to try again + throw; // Caller will call LoginFailure() } // Check sleep interval to make sure we won't exceed the timeout @@ -1611,7 +1641,7 @@ private void LoginNoFailover(ServerInfo serverInfo, // We only get here when we failed to connect, but are going to re-try // Switch to failover logic if the server provided a partner - if (null != ServerProvidedFailOverPartner) + if (ServerProvidedFailOverPartner != null) { if (connectionOptions.MultiSubnetFailover) { @@ -1645,7 +1675,7 @@ private void LoginNoFailover(ServerInfo serverInfo, } _activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn; - if (null != PoolGroupProviderInfo) + if (PoolGroupProviderInfo != null) { // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover @@ -1711,7 +1741,7 @@ TimeoutTimer timeout ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost, connectionOptions.FailoverPartnerSPN); ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions); - if (null == ServerProvidedFailOverPartner) + if (ServerProvidedFailOverPartner == null) { ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions); } @@ -1751,7 +1781,9 @@ TimeoutTimer timeout // Re-allocate parser each time to make sure state is known // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created if (_parser != null) + { _parser.Disconnect(); + } _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous); Debug.Assert(SniContext.Undefined == Parser._physicalStateObj.SniContext, $"SniContext should be Undefined; actual Value: {Parser._physicalStateObj.SniContext}"); @@ -1760,7 +1792,7 @@ TimeoutTimer timeout if (useFailoverHost) { // Primary server may give us a different failover partner than the connection string indicates. Update it - if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) + if (ServerProvidedFailOverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) { SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, new failover partner={1}", ObjectID, ServerProvidedFailOverPartner); failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailOverPartner); @@ -1784,15 +1816,44 @@ TimeoutTimer timeout intervalTimer, withFailover: true ); - - if (RoutingInfo != null) + int routingAttemps = 0; + while (RoutingInfo != null) { - // We are in login with failover scenation and server sent routing information - // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before) - // If it is something else, not known yet (future server) - this client is not designed to support this. - // In any case, server should not have sent the routing info. + if (routingAttemps > _maxNumberOfRedirectRoute) + { + throw SQL.ROR_RecursiveRoutingNotSupported(this, _maxNumberOfRedirectRoute); + } + routingAttemps++; + SqlClientEventSource.Log.TryTraceEvent(" Routed to {0}", RoutingInfo.ServerName); - throw SQL.ROR_UnexpectedRoutingInfo(this); + + if(_parser != null) + { + _parser.Disconnect(); + } + + _parser = new TdsParser(ConnectionOptions.MARS, connectionOptions.Asynchronous); + + Debug.Assert(SniContext.Undefined == Parser._physicalStateObj.SniContext, $"SniContext should be Undefined; actual Value: {Parser._physicalStateObj.SniContext}"); + + currentServerInfo = new ServerInfo(ConnectionOptions, RoutingInfo, currentServerInfo.ResolvedServerName, currentServerInfo.ServerSPN); + _timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.RoutingDestination); + _originalClientConnectionId = _clientConnectionId; + _routingDestination = currentServerInfo.UserServerName; + + // restore properties that could be changed by the environemnt tokens + _currentPacketSize = connectionOptions.PacketSize; + _currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage; + CurrentDatabase = _originalDatabase = connectionOptions.InitialCatalog; + _currentFailoverPartner = null; + _instanceName = string.Empty; + + AttemptOneLogin( + currentServerInfo, + newPassword, + newSecurePassword, + intervalTimer, + withFailover: true); } break; // leave the while loop -- we've successfully connected } @@ -1809,7 +1870,7 @@ TimeoutTimer timeout throw; // Caller will call LoginFailure() } - if (IsConnectionDoomed) + if (!ADP.IsAzureSqlServerEndpoint(connectionOptions.DataSource) && IsConnectionDoomed) { throw; } @@ -1845,12 +1906,12 @@ TimeoutTimer timeout _activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn; // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error - if (useFailoverHost && null == ServerProvidedFailOverPartner) + if (useFailoverHost && ServerProvidedFailOverPartner == null) { throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase); } - if (null != PoolGroupProviderInfo) + if (PoolGroupProviderInfo != null) { // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover @@ -1911,7 +1972,7 @@ private void AttemptOneLogin( TimeoutTimer timeout, bool withFailover = false) { - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, timout={1}[msec], server={2}", ObjectID, timeout.MillisecondsRemaining, serverInfo.ExtendedServerName); + SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, timeout={1}[msec], server={2}", ObjectID, timeout.MillisecondsRemaining, serverInfo.ExtendedServerName); RoutingInfo = null; // forget routing information _parser._physicalStateObj.SniContext = SniContext.Snix_Connect; @@ -2011,7 +2072,7 @@ internal void BreakConnection() var connection = Connection; SqlClientEventSource.Log.TryTraceEvent(" {0}, Breaking connection.", ObjectID); DoomThisConnection(); // Mark connection as unusable, so it will be destroyed - if (null != connection) + if (connection != null) { connection.Close(); } @@ -2159,6 +2220,7 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo) || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryMSI || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryDefault + || ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && _fedAuthRequired), "Credentials aren't provided for calling MSAL"); Debug.Assert(fedAuthInfo != null, "info should not be null."); @@ -2254,6 +2316,11 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo) { // GetFedAuthToken should have updated _newDbConnectionPoolAuthenticationContext. Debug.Assert(_newDbConnectionPoolAuthenticationContext != null, "_newDbConnectionPoolAuthenticationContext should not be null."); + + if (_newDbConnectionPoolAuthenticationContext != null) + { + _dbConnectionPool.AuthenticationContexts.TryAdd(_dbConnectionPoolAuthenticationContextKey, _newDbConnectionPoolAuthenticationContext); + } } } else if (!attemptRefreshTokenLocked) @@ -2293,7 +2360,7 @@ internal bool TryGetFedAuthTokenLocked(SqlFedAuthInfo fedAuthInfo, DbConnectionP bool authenticationContextLocked = false; // Prepare CER to ensure the lock on authentication context is released. -#if !NET6_0_OR_GREATER +#if NETFRAMEWORK RuntimeHelpers.PrepareConstrainedRegions(); #endif try @@ -2355,7 +2422,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) // Username to use in error messages. string username = null; - var authProvider = _sqlAuthenticationProviderManager.GetProvider(ConnectionOptions.Authentication); + var authProvider = SqlAuthenticationProvider.GetProvider(ConnectionOptions.Authentication); if (authProvider == null && _accessTokenCallback == null) throw SQL.CannotFindAuthProvider(ConnectionOptions.Authentication.ToString()); @@ -2406,6 +2473,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) case SqlAuthenticationMethod.ActiveDirectoryManagedIdentity: case SqlAuthenticationMethod.ActiveDirectoryMSI: case SqlAuthenticationMethod.ActiveDirectoryDefault: + case SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity: if (_activeDirectoryAuthTimeoutRetryHelper.State == ActiveDirectoryAuthenticationTimeoutRetryState.Retrying) { _fedAuthToken = _activeDirectoryAuthTimeoutRetryHelper.CachedToken; @@ -2733,23 +2801,33 @@ internal void OnFeatureExtAck(int featureId, byte[] data) } break; } - - case TdsEnums.FEATUREEXT_UTF8SUPPORT: + case TdsEnums.FEATUREEXT_AZURESQLSUPPORT: { - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, Received feature extension acknowledgement for UTF8 support", ObjectID); + SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, Received feature extension acknowledgement for AzureSQLSupport", ObjectID); + if (data.Length < 1) { - SqlClientEventSource.Log.TryTraceEvent(" {0}, Unknown value for UTF8 support", ObjectID); - throw SQL.ParsingError(); + throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream); + } + + IsAzureSQLConnection = true; + + // Bit 0 for RO/FP support + if ((data[0] & 1) == 1 && SqlClientEventSource.Log.IsTraceEnabled()) + { + SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, FailoverPartner enabled with Readonly intent for AzureSQL DB", ObjectID); + } break; } case TdsEnums.FEATUREEXT_DATACLASSIFICATION: { SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, Received feature extension acknowledgement for DATACLASSIFICATION", ObjectID); + if (data.Length < 1) { SqlClientEventSource.Log.TryTraceEvent(" {0}, Unknown token for DATACLASSIFICATION", ObjectID); + throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream); } byte supportedDataClassificationVersion = data[0]; @@ -2762,12 +2840,25 @@ internal void OnFeatureExtAck(int featureId, byte[] data) if (data.Length != 2) { SqlClientEventSource.Log.TryTraceEvent(" {0}, Unknown token for DATACLASSIFICATION", ObjectID); + throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream); } byte enabled = data[1]; _parser.DataClassificationVersion = (enabled == 0) ? TdsEnums.DATA_CLASSIFICATION_NOT_ENABLED : supportedDataClassificationVersion; break; } + case TdsEnums.FEATUREEXT_UTF8SUPPORT: + { + SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, Received feature extension acknowledgement for UTF8 support", ObjectID); + + if (data.Length < 1) + { + SqlClientEventSource.Log.TryTraceEvent(" {0}, Unknown value for UTF8 support", ObjectID); + + throw SQL.ParsingError(); + } + break; + } case TdsEnums.FEATUREEXT_SQLDNSCACHING: { @@ -2804,6 +2895,24 @@ internal void OnFeatureExtAck(int featureId, byte[] data) break; } + case TdsEnums.FEATUREEXT_JSONSUPPORT: + { + SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, Received feature extension acknowledgement for JSONSUPPORT", ObjectID); + if (data.Length != 1) + { + SqlClientEventSource.Log.TryTraceEvent(" {0}, Unknown token for JSONSUPPORT", ObjectID); + throw SQL.ParsingError(ParsingErrorState.CorruptedTdsStream); + } + byte jsonSupportVersion = data[0]; + if (jsonSupportVersion == 0 || jsonSupportVersion > TdsEnums.MAX_SUPPORTED_JSON_VERSION) + { + SqlClientEventSource.Log.TryTraceEvent(" {0}, Invalid version number for JSONSUPPORT", ObjectID); + throw SQL.ParsingError(); + } + IsJsonSupportEnabled = true; + break; + } + default: { // Unknown feature ack @@ -2888,7 +2997,7 @@ private ServerInfo(SqlConnectionString userOptions, string serverName) { //----------------- // Preconditions - Debug.Assert(null != userOptions); + Debug.Assert(userOptions != null); //----------------- //Method body @@ -2907,7 +3016,7 @@ internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string { //----------------- // Preconditions - Debug.Assert(null != userOptions && null != routing); + Debug.Assert(userOptions != null && routing != null); //----------------- //Method body diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs deleted file mode 100644 index 1998e13e96..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs +++ /dev/null @@ -1,2218 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Globalization; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Transactions; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient -{ - internal static class AsyncHelper - { - internal static Task CreateContinuationTask(Task task, Action onSuccess, Action onFailure = null) - { - if (task == null) - { - onSuccess(); - return null; - } - else - { - TaskCompletionSource completion = new TaskCompletionSource(); - ContinueTaskWithState(task, completion, - state: Tuple.Create(onSuccess, onFailure, completion), - onSuccess: static (object state) => - { - var parameters = (Tuple, TaskCompletionSource>)state; - Action success = parameters.Item1; - TaskCompletionSource taskCompletionSource = parameters.Item3; - success(); - taskCompletionSource.SetResult(null); - }, - onFailure: static (Exception exception, object state) => - { - var parameters = (Tuple, TaskCompletionSource>)state; - Action failure = parameters.Item2; - failure?.Invoke(exception); - } - ); - return completion.Task; - } - } - - internal static Task CreateContinuationTaskWithState(Task task, object state, Action onSuccess, Action onFailure = null) - { - if (task == null) - { - onSuccess(state); - return null; - } - else - { - var completion = new TaskCompletionSource(); - ContinueTaskWithState(task, completion, state, - onSuccess: (object continueState) => - { - onSuccess(continueState); - completion.SetResult(null); - }, - onFailure: onFailure - ); - return completion.Task; - } - } - - internal static Task CreateContinuationTask(Task task, Action onSuccess, T1 arg1, T2 arg2, SqlInternalConnectionTds connectionToDoom = null, Action onFailure = null) - { - return CreateContinuationTask(task, () => onSuccess(arg1, arg2), onFailure); - } - - internal static void ContinueTask(Task task, - TaskCompletionSource completion, - Action onSuccess, - Action onFailure = null, - Action onCancellation = null, - Func exceptionConverter = null - ) - { - task.ContinueWith( - tsk => - { - if (tsk.Exception != null) - { - Exception exc = tsk.Exception.InnerException; - if (exceptionConverter != null) - { - exc = exceptionConverter(exc); - } - try - { - onFailure?.Invoke(exc); - } - finally - { - completion.TrySetException(exc); - } - } - else if (tsk.IsCanceled) - { - try - { - onCancellation?.Invoke(); - } - finally - { - completion.TrySetCanceled(); - } - } - else - { - try - { - onSuccess(); - } - catch (Exception e) - { - completion.SetException(e); - } - } - }, TaskScheduler.Default - ); - } - - // the same logic as ContinueTask but with an added state parameter to allow the caller to avoid the use of a closure - // the parameter allocation cannot be avoided here and using closure names is clearer than Tuple numbered properties - internal static void ContinueTaskWithState(Task task, - TaskCompletionSource completion, - object state, - Action onSuccess, - Action onFailure = null, - Action onCancellation = null, - Func exceptionConverter = null - ) - { - task.ContinueWith( - (Task tsk, object state2) => - { - if (tsk.Exception != null) - { - Exception exc = tsk.Exception.InnerException; - if (exceptionConverter != null) - { - exc = exceptionConverter(exc); - } - try - { - onFailure?.Invoke(exc, state2); - } - finally - { - completion.TrySetException(exc); - } - } - else if (tsk.IsCanceled) - { - try - { - onCancellation?.Invoke(state2); - } - finally - { - completion.TrySetCanceled(); - } - } - else - { - try - { - onSuccess(state2); - } - catch (Exception e) - { - completion.SetException(e); - } - } - }, - state: state, - scheduler: TaskScheduler.Default - ); - } - - internal static void WaitForCompletion(Task task, int timeout, Action onTimeout = null, bool rethrowExceptions = true) - { - try - { - task.Wait(timeout > 0 ? (1000 * timeout) : Timeout.Infinite); - } - catch (AggregateException ae) - { - if (rethrowExceptions) - { - Debug.Assert(ae.InnerExceptions.Count == 1, "There is more than one exception in AggregateException"); - ExceptionDispatchInfo.Capture(ae.InnerException).Throw(); - } - } - if (!task.IsCompleted) - { - task.ContinueWith(static t => { var ignored = t.Exception; }); //Ensure the task does not leave an unobserved exception - onTimeout?.Invoke(); - } - } - - internal static void SetTimeoutException(TaskCompletionSource completion, int timeout, Func onFailure, CancellationToken ctoken) - { - if (timeout > 0) - { - Task.Delay(timeout * 1000, ctoken).ContinueWith( - (Task task) => - { - if (!task.IsCanceled && !completion.Task.IsCompleted) - { - completion.TrySetException(onFailure()); - } - } - ); - } - } - - internal static void SetTimeoutExceptionWithState(TaskCompletionSource completion, int timeout, object state, Func onFailure, CancellationToken cancellationToken) - { - if (timeout > 0) - { - Task.Delay(timeout * 1000, cancellationToken).ContinueWith( - (Task task, object state) => - { - if (!task.IsCanceled && !completion.Task.IsCompleted) - { - completion.TrySetException(onFailure(state)); - } - }, - state: state, - cancellationToken: CancellationToken.None - ); - } - } - } - - internal static class SQL - { - // The class SQL defines the exceptions that are specific to the SQL Adapter. - // The class contains functions that take the proper informational variables and then construct - // the appropriate exception with an error string obtained from the resource Framework.txt. - // The exception is then returned to the caller, so that the caller may then throw from its - // location so that the catcher of the exception will have the appropriate call stack. - // This class is used so that there will be compile time checking of error - // messages. The resource Framework.txt will ensure proper string text based on the appropriate - // locale. - - // - // SQL specific exceptions - // - - // - // SQL.Connection - // - internal static Exception CannotGetDTCAddress() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CannotGetDTCAddress)); - } - - internal static Exception InvalidInternalPacketSize(string str) - { - return ADP.ArgumentOutOfRange(str); - } - internal static Exception InvalidPacketSize() - { - return ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SQL_InvalidTDSPacketSize)); - } - internal static Exception InvalidPacketSizeValue() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InvalidPacketSizeValue)); - } - internal static Exception InvalidSSPIPacketSize() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InvalidSSPIPacketSize)); - } - internal static Exception AuthenticationAndIntegratedSecurity() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_AuthenticationAndIntegratedSecurity)); - } - internal static Exception IntegratedWithPassword() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_IntegratedWithPassword)); - } - internal static Exception InteractiveWithPassword() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InteractiveWithPassword)); - } - internal static Exception DeviceFlowWithUsernamePassword() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_DeviceFlowWithUsernamePassword)); - } - internal static Exception NonInteractiveWithPassword(string authenticationMode) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_NonInteractiveWithPassword, authenticationMode)); - } - static internal Exception SettingIntegratedWithCredential() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingIntegratedWithCredential)); - } - static internal Exception SettingInteractiveWithCredential() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingInteractiveWithCredential)); - } - static internal Exception SettingDeviceFlowWithCredential() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingDeviceFlowWithCredential)); - } - static internal Exception SettingNonInteractiveWithCredential(string authenticationMode) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingNonInteractiveWithCredential, authenticationMode)); - } - static internal Exception SettingCredentialWithIntegratedArgument() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_SettingCredentialWithIntegrated)); - } - static internal Exception SettingCredentialWithInteractiveArgument() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_SettingCredentialWithInteractive)); - } - static internal Exception SettingCredentialWithDeviceFlowArgument() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_SettingCredentialWithDeviceFlow)); - } - static internal Exception SettingCredentialWithNonInteractiveArgument(string authenticationMode) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_SettingCredentialWithNonInteractive, authenticationMode)); - } - static internal Exception SettingCredentialWithIntegratedInvalid() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingCredentialWithIntegrated)); - } - static internal Exception SettingCredentialWithInteractiveInvalid() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingCredentialWithInteractive)); - } - static internal Exception SettingCredentialWithDeviceFlowInvalid() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingCredentialWithDeviceFlow)); - } - static internal Exception SettingCredentialWithNonInteractiveInvalid(string authenticationMode) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SettingCredentialWithNonInteractive, authenticationMode)); - } - internal static Exception NullEmptyTransactionName() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_NullEmptyTransactionName)); - } - internal static Exception UserInstanceFailoverNotCompatible() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_UserInstanceFailoverNotCompatible)); - } - internal static Exception CredentialsNotProvided(SqlAuthenticationMethod auth) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CredentialsNotProvided, DbConnectionStringBuilderUtil.AuthenticationTypeToString(auth))); - } - internal static Exception ParsingErrorLibraryType(ParsingErrorState state, int libraryType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorAuthLibraryType, ((int)state).ToString(CultureInfo.InvariantCulture), libraryType)); - } - internal static Exception InvalidSQLServerVersionUnknown() - { - return ADP.DataAdapter(StringsHelper.GetString(Strings.SQL_InvalidSQLServerVersionUnknown)); - } - internal static Exception SynchronousCallMayNotPend() - { - return new Exception(StringsHelper.GetString(Strings.Sql_InternalError)); - } - internal static Exception SocketDidNotThrow() - { - return new InternalException(StringsHelper.GetString(Strings.SQL_SocketDidNotThrow, nameof(SocketException), nameof(SocketError.WouldBlock))); - } - internal static Exception ConnectionLockedForBcpEvent() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ConnectionLockedForBcpEvent)); - } - internal static Exception InstanceFailure() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_InstanceFailure)); - } - internal static Exception ChangePasswordArgumentMissing(string argumentName) - { - return ADP.ArgumentNull(StringsHelper.GetString(Strings.SQL_ChangePasswordArgumentMissing, argumentName)); - } - internal static Exception ChangePasswordConflictsWithSSPI() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_ChangePasswordConflictsWithSSPI)); - } - internal static Exception ChangePasswordRequires2005() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ChangePasswordRequiresYukon)); - } - internal static Exception ChangePasswordUseOfUnallowedKey(string key) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ChangePasswordUseOfUnallowedKey, key)); - } - internal static Exception GlobalizationInvariantModeNotSupported() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_GlobalizationInvariantModeNotSupported)); - } - - // - // Global Transactions. - // - internal static Exception GlobalTransactionsNotEnabled() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.GT_Disabled)); - } - internal static Exception UnknownSysTxIsolationLevel(System.Transactions.IsolationLevel isolationLevel) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_UnknownSysTxIsolationLevel, isolationLevel.ToString())); - } - - - internal static Exception InvalidPartnerConfiguration(string server, string database) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_InvalidPartnerConfiguration, server, database)); - } - - internal static Exception BatchedUpdateColumnEncryptionSettingMismatch() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_BatchedUpdateColumnEncryptionSettingMismatch, "SqlCommandColumnEncryptionSetting", "SelectCommand", "InsertCommand", "UpdateCommand", "DeleteCommand")); - } - internal static Exception MARSUnsupportedOnConnection() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_MarsUnsupportedOnConnection)); - } - - internal static Exception CannotModifyPropertyAsyncOperationInProgress([CallerMemberName] string property = "") - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CannotModifyPropertyAsyncOperationInProgress, property)); - } - internal static Exception NonLocalSSEInstance() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_NonLocalSSEInstance)); - } - - // SQL.ActiveDirectoryAuth - // - internal static Exception UnsupportedAuthentication(string authentication) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedAuthentication, authentication)); - } - - internal static Exception UnsupportedSqlAuthenticationMethod(SqlAuthenticationMethod authentication) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedSqlAuthenticationMethod, authentication)); - } - - internal static Exception UnsupportedAuthenticationSpecified(SqlAuthenticationMethod authentication) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_UnsupportedAuthenticationSpecified, authentication)); - } - - internal static Exception CannotCreateAuthProvider(string authentication, string type, Exception e) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotCreateAuthProvider, authentication, type), e); - } - - internal static Exception CannotCreateSqlAuthInitializer(string type, Exception e) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotCreateAuthInitializer, type), e); - } - - internal static Exception CannotInitializeAuthProvider(string type, Exception e) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CannotInitializeAuthProvider, type), e); - } - - internal static Exception UnsupportedAuthenticationByProvider(string authentication, string type) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedAuthenticationByProvider, type, authentication)); - } - - internal static Exception CannotFindAuthProvider(string authentication) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotFindAuthProvider, authentication)); - } - - internal static Exception CannotGetAuthProviderConfig(Exception e) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CannotGetAuthProviderConfig), e); - } - - internal static Exception ParameterCannotBeEmpty(string paramName) - { - return ADP.ArgumentNull(StringsHelper.GetString(Strings.SQL_ParameterCannotBeEmpty, paramName)); - } - - internal static Exception ParameterDirectionInvalidForOptimizedBinding(string paramName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParameterDirectionInvalidForOptimizedBinding, paramName)); - } - - internal static Exception ActiveDirectoryInteractiveTimeout() - { - return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_Interactive_Authentication); - } - - internal static Exception ActiveDirectoryDeviceFlowTimeout() - { - return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_DeviceFlow_Authentication); - } - - internal static Exception ActiveDirectoryTokenRetrievingTimeout(string authenticaton, string errorCode, Exception exception) - { - return ADP.TimeoutException(StringsHelper.GetString(Strings.AAD_Token_Retrieving_Timeout, authenticaton, errorCode, exception?.Message), exception); - } - - // - // SQL.DataCommand - // - - internal static ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, int value) - { - return ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SQL_NotSupportedEnumerationValue, type.Name, value.ToString(System.Globalization.CultureInfo.InvariantCulture)), type.Name); - } - - internal static ArgumentOutOfRangeException NotSupportedCommandType(CommandType value) - { -#if DEBUG - switch (value) - { - case CommandType.Text: - case CommandType.StoredProcedure: - Debug.Fail("valid CommandType " + value.ToString()); - break; - case CommandType.TableDirect: - break; - default: - Debug.Fail("invalid CommandType " + value.ToString()); - break; - } -#endif - return NotSupportedEnumerationValue(typeof(CommandType), (int)value); - } - internal static ArgumentOutOfRangeException NotSupportedIsolationLevel(System.Data.IsolationLevel value) - { -#if DEBUG - switch (value) - { - case System.Data.IsolationLevel.Unspecified: - case System.Data.IsolationLevel.ReadCommitted: - case System.Data.IsolationLevel.ReadUncommitted: - case System.Data.IsolationLevel.RepeatableRead: - case System.Data.IsolationLevel.Serializable: - case System.Data.IsolationLevel.Snapshot: - Debug.Fail("valid IsolationLevel " + value.ToString()); - break; - case System.Data.IsolationLevel.Chaos: - break; - default: - Debug.Fail("invalid IsolationLevel " + value.ToString()); - break; - } -#endif - return NotSupportedEnumerationValue(typeof(System.Data.IsolationLevel), (int)value); - } - - internal static Exception OperationCancelled() - { - Exception exception = ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_OperationCancelled)); - return exception; - } - - internal static Exception PendingBeginXXXExists() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_PendingBeginXXXExists)); - } - - internal static ArgumentOutOfRangeException InvalidSqlDependencyTimeout(string param) - { - return ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SqlDependency_InvalidTimeout), param); - } - - internal static Exception NonXmlResult() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_NonXmlResult)); - } - - // - // SQL.DataParameter - // - internal static Exception InvalidUdt3PartNameFormat() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InvalidUdt3PartNameFormat)); - } - internal static Exception InvalidParameterTypeNameFormat() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InvalidParameterTypeNameFormat)); - } - internal static Exception InvalidParameterNameLength(string value) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_InvalidParameterNameLength, value)); - } - internal static Exception PrecisionValueOutOfRange(byte precision) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_PrecisionValueOutOfRange, precision.ToString(CultureInfo.InvariantCulture))); - } - internal static Exception ScaleValueOutOfRange(byte scale) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_ScaleValueOutOfRange, scale.ToString(CultureInfo.InvariantCulture))); - } - internal static Exception TimeScaleValueOutOfRange(byte scale) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_TimeScaleValueOutOfRange, scale.ToString(CultureInfo.InvariantCulture))); - } - internal static Exception InvalidSqlDbType(SqlDbType value) - { - return ADP.InvalidEnumerationValue(typeof(SqlDbType), (int)value); - } - internal static Exception UnsupportedTVPOutputParameter(ParameterDirection direction, string paramName) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SqlParameter_UnsupportedTVPOutputParameter, - direction.ToString(), paramName)); - } - internal static Exception DBNullNotSupportedForTVPValues(string paramName) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SqlParameter_DBNullNotSupportedForTVP, paramName)); - } - internal static Exception UnexpectedTypeNameForNonStructParams(string paramName) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SqlParameter_UnexpectedTypeNameForNonStruct, paramName)); - } - internal static Exception ParameterInvalidVariant(string paramName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParameterInvalidVariant, paramName)); - } - - internal static Exception MustSetTypeNameForParam(string paramType, string paramName) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_ParameterTypeNameRequired, paramType, paramName)); - } - internal static Exception NullSchemaTableDataTypeNotSupported(string columnName) - { - return ADP.Argument(StringsHelper.GetString(Strings.NullSchemaTableDataTypeNotSupported, columnName)); - } - internal static Exception InvalidSchemaTableOrdinals() - { - return ADP.Argument(StringsHelper.GetString(Strings.InvalidSchemaTableOrdinals)); - } - internal static Exception EnumeratedRecordMetaDataChanged(string fieldName, int recordNumber) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_EnumeratedRecordMetaDataChanged, fieldName, recordNumber)); - } - internal static Exception EnumeratedRecordFieldCountChanged(int recordNumber) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_EnumeratedRecordFieldCountChanged, recordNumber)); - } - - // - // SQL.SqlDataAdapter - // - - // - // SQL.TDSParser - // - internal static Exception InvalidTDSVersion() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_InvalidTDSVersion)); - } - internal static Exception ParsingError() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingError)); - } - internal static Exception ParsingError(ParsingErrorState state) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorWithState, ((int)state).ToString(CultureInfo.InvariantCulture))); - } - internal static Exception ParsingError(ParsingErrorState state, Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorWithState, ((int)state).ToString(CultureInfo.InvariantCulture)), innerException); - } - internal static Exception ParsingErrorValue(ParsingErrorState state, int value) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorValue, ((int)state).ToString(CultureInfo.InvariantCulture), value)); - } - internal static Exception ParsingErrorFeatureId(ParsingErrorState state, int featureId) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorFeatureId, ((int)state).ToString(CultureInfo.InvariantCulture), featureId)); - } - internal static Exception ParsingErrorToken(ParsingErrorState state, int token) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorToken, ((int)state).ToString(CultureInfo.InvariantCulture), token)); - } - internal static Exception ParsingErrorLength(ParsingErrorState state, int length) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorLength, ((int)state).ToString(CultureInfo.InvariantCulture), length)); - } - internal static Exception ParsingErrorStatus(ParsingErrorState state, int status) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorStatus, ((int)state).ToString(CultureInfo.InvariantCulture), status)); - } - internal static Exception ParsingErrorOffset(ParsingErrorState state, int offset) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParsingErrorOffset, ((int)state).ToString(CultureInfo.InvariantCulture), offset)); - } - internal static Exception MoneyOverflow(string moneyValue) - { - return ADP.Overflow(StringsHelper.GetString(Strings.SQL_MoneyOverflow, moneyValue)); - } - internal static Exception SmallDateTimeOverflow(string datetime) - { - return ADP.Overflow(StringsHelper.GetString(Strings.SQL_SmallDateTimeOverflow, datetime)); - } - internal static Exception SNIPacketAllocationFailure() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_SNIPacketAllocationFailure)); - } - internal static Exception TimeOverflow(string time) - { - return ADP.Overflow(StringsHelper.GetString(Strings.SQL_TimeOverflow, time)); - } - - // - // SQL.SqlDataReader - // - internal static Exception InvalidRead() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_InvalidRead)); - } - - internal static Exception NonBlobColumn(string columnName) - { - return ADP.InvalidCast(StringsHelper.GetString(Strings.SQL_NonBlobColumn, columnName)); - } - - internal static Exception NonCharColumn(string columnName) - { - return ADP.InvalidCast(StringsHelper.GetString(Strings.SQL_NonCharColumn, columnName)); - } - - internal static Exception StreamNotSupportOnColumnType(string columnName) - { - return ADP.InvalidCast(StringsHelper.GetString(Strings.SQL_StreamNotSupportOnColumnType, columnName)); - } - - internal static Exception StreamNotSupportOnEncryptedColumn(string columnName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_StreamNotSupportOnEncryptedColumn, columnName, "Stream")); - } - - internal static Exception SequentialAccessNotSupportedOnEncryptedColumn(string columnName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_SequentialAccessNotSupportedOnEncryptedColumn, columnName, "CommandBehavior=SequentialAccess")); - } - - internal static Exception TextReaderNotSupportOnColumnType(string columnName) - { - return ADP.InvalidCast(StringsHelper.GetString(Strings.SQL_TextReaderNotSupportOnColumnType, columnName)); - } - - internal static Exception XmlReaderNotSupportOnColumnType(string columnName) - { - return ADP.InvalidCast(StringsHelper.GetString(Strings.SQL_XmlReaderNotSupportOnColumnType, columnName)); - } - - internal static Exception UDTUnexpectedResult(string exceptionText) - { - return ADP.TypeLoad(StringsHelper.GetString(Strings.SQLUDT_Unexpected, exceptionText)); - } - - internal static Exception DateTimeOverflow() - { - return new OverflowException(SqlTypes.SQLResource.DateTimeOverflowMessage); - } - - // - // SQL.SqlDependency - // - internal static Exception SqlCommandHasExistingSqlNotificationRequest() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQLNotify_AlreadyHasCommand)); - } - - internal static Exception SqlDepDefaultOptionsButNoStart() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_DefaultOptionsButNoStart)); - } - - internal static Exception SqlDependencyDatabaseBrokerDisabled() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_DatabaseBrokerDisabled)); - } - - internal static Exception SqlDependencyEventNoDuplicate() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_EventNoDuplicate)); - } - - internal static Exception SqlDependencyDuplicateStart() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_DuplicateStart)); - } - - internal static Exception SqlDependencyIdMismatch() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_IdMismatch)); - } - - internal static Exception SqlDependencyNoMatchingServerStart() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_NoMatchingServerStart)); - } - - internal static Exception SqlDependencyNoMatchingServerDatabaseStart() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlDependency_NoMatchingServerDatabaseStart)); - } - - // - // SQL.SqlDelegatedTransaction - // - static internal Exception CannotCompleteDelegatedTransactionWithOpenResults(SqlInternalConnectionTds internalConnection, bool marsOn) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(TdsEnums.TIMEOUT_EXPIRED, (byte)0x00, TdsEnums.MIN_ERROR_CLASS, null, (StringsHelper.GetString(Strings.ADP_OpenReaderExists, marsOn ? ADP.Command : ADP.Connection)), "", 0, TdsEnums.SNI_WAIT_TIMEOUT)); - return SqlException.CreateException(errors, null, internalConnection); - } - - internal static TransactionPromotionException PromotionFailed(Exception inner) - { - TransactionPromotionException e = new TransactionPromotionException(StringsHelper.GetString(Strings.SqlDelegatedTransaction_PromotionFailed), inner); - ADP.TraceExceptionAsReturnValue(e); - return e; - } - //Failure while attempting to promote transaction. - - // - // SQL.SqlMetaData - // - internal static Exception UnexpectedUdtTypeNameForNonUdtParams() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQLUDT_UnexpectedUdtTypeName)); - } - internal static Exception MustSetUdtTypeNameForUdtParams() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQLUDT_InvalidUdtTypeName)); - } - internal static Exception UDTInvalidSqlType(string typeName) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQLUDT_InvalidSqlType, typeName)); - } - - internal static Exception UDTInvalidSize(int maxSize, int maxSupportedSize) - { - throw ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SQLUDT_InvalidSize, maxSize, maxSupportedSize)); - } - - internal static Exception InvalidSqlDbTypeForConstructor(SqlDbType type) - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlMetaData_InvalidSqlDbTypeForConstructorFormat, type.ToString())); - } - - internal static Exception NameTooLong(string parameterName) - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlMetaData_NameTooLong), parameterName); - } - - internal static Exception InvalidSortOrder(SortOrder order) - { - return ADP.InvalidEnumerationValue(typeof(SortOrder), (int)order); - } - - internal static Exception MustSpecifyBothSortOrderAndOrdinal(SortOrder order, int ordinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlMetaData_SpecifyBothSortOrderAndOrdinal, order.ToString(), ordinal)); - } - - internal static Exception UnsupportedColumnTypeForSqlProvider(string columnName, string typeName) - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlProvider_InvalidDataColumnType, columnName, typeName)); - } - internal static Exception InvalidColumnMaxLength(string columnName, long maxLength) - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlProvider_InvalidDataColumnMaxLength, columnName, maxLength)); - } - internal static Exception InvalidColumnPrecScale() - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlMisc_InvalidPrecScaleMessage)); - } - internal static Exception NotEnoughColumnsInStructuredType() - { - return ADP.Argument(StringsHelper.GetString(Strings.SqlProvider_NotEnoughColumnsInStructuredType)); - } - internal static Exception DuplicateSortOrdinal(int sortOrdinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlProvider_DuplicateSortOrdinal, sortOrdinal)); - } - internal static Exception MissingSortOrdinal(int sortOrdinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlProvider_MissingSortOrdinal, sortOrdinal)); - } - internal static Exception SortOrdinalGreaterThanFieldCount(int columnOrdinal, int sortOrdinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlProvider_SortOrdinalGreaterThanFieldCount, sortOrdinal, columnOrdinal)); - } - internal static Exception IEnumerableOfSqlDataRecordHasNoRows() - { - return ADP.Argument(StringsHelper.GetString(Strings.IEnumerableOfSqlDataRecordHasNoRows)); - } - - - - - // - // SQL.BulkLoad - // - internal static Exception BulkLoadMappingInaccessible() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadMappingInaccessible)); - } - internal static Exception BulkLoadMappingsNamesOrOrdinalsOnly() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadMappingsNamesOrOrdinalsOnly)); - } - internal static Exception BulkLoadCannotConvertValue(Type sourcetype, MetaType metatype, int ordinal, int rowNumber, bool isEncrypted, string columnName, string value, Exception e) - { - string quotedValue = string.Empty; - if (!isEncrypted) - { - quotedValue = string.Format(" '{0}'", (value.Length > 100 ? value.Substring(0, 100) : value)); - } - if (rowNumber == -1) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadCannotConvertValueWithoutRowNo, quotedValue, sourcetype.Name, metatype.TypeName, ordinal, columnName), e); - } - else - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadCannotConvertValue, quotedValue, sourcetype.Name, metatype.TypeName, ordinal, columnName, rowNumber), e); - } - } - internal static Exception BulkLoadNonMatchingColumnMapping() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadNonMatchingColumnMapping)); - } - internal static Exception BulkLoadNonMatchingColumnName(string columnName) - { - return BulkLoadNonMatchingColumnName(columnName, null); - } - internal static Exception BulkLoadNonMatchingColumnName(string columnName, Exception e) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadNonMatchingColumnName, columnName), e); - } - internal static Exception BulkLoadNullEmptyColumnName(string paramName) - { - return ADP.Argument(string.Format(StringsHelper.GetString(Strings.SQL_ParameterCannotBeEmpty), paramName)); - } - internal static Exception BulkLoadUnspecifiedSortOrder() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_BulkLoadUnspecifiedSortOrder)); - } - internal static Exception BulkLoadInvalidOrderHint() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_BulkLoadInvalidOrderHint)); - } - internal static Exception BulkLoadOrderHintInvalidColumn(string columnName) - { - return ADP.InvalidOperation(string.Format(StringsHelper.GetString(Strings.SQL_BulkLoadOrderHintInvalidColumn), columnName)); - } - internal static Exception BulkLoadOrderHintDuplicateColumn(string columnName) - { - return ADP.InvalidOperation(string.Format(StringsHelper.GetString(Strings.SQL_BulkLoadOrderHintDuplicateColumn), columnName)); - } - internal static Exception BulkLoadStringTooLong(string tableName, string columnName, string truncatedValue) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadStringTooLong, tableName, columnName, truncatedValue)); - } - internal static Exception BulkLoadInvalidVariantValue() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadInvalidVariantValue)); - } - internal static Exception BulkLoadInvalidTimeout(int timeout) - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_BulkLoadInvalidTimeout, timeout.ToString(CultureInfo.InvariantCulture))); - } - internal static Exception BulkLoadExistingTransaction() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadExistingTransaction)); - } - internal static Exception BulkLoadNoCollation() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadNoCollation)); - } - internal static Exception BulkLoadConflictingTransactionOption() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQL_BulkLoadConflictingTransactionOption)); - } - internal static Exception BulkLoadLcidMismatch(int sourceLcid, string sourceColumnName, int destinationLcid, string destinationColumnName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.Sql_BulkLoadLcidMismatch, sourceLcid, sourceColumnName, destinationLcid, destinationColumnName)); - } - internal static Exception InvalidOperationInsideEvent() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadInvalidOperationInsideEvent)); - } - internal static Exception BulkLoadMissingDestinationTable() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadMissingDestinationTable)); - } - internal static Exception BulkLoadInvalidDestinationTable(string tableName, Exception inner) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadInvalidDestinationTable, tableName), inner); - } - internal static Exception BulkLoadBulkLoadNotAllowDBNull(string columnName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadNotAllowDBNull, columnName)); - } - internal static Exception BulkLoadPendingOperation() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BulkLoadPendingOperation)); - } - internal static Exception InvalidTableDerivedPrecisionForTvp(string columnName, byte precision) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlParameter_InvalidTableDerivedPrecisionForTvp, precision, columnName, System.Data.SqlTypes.SqlDecimal.MaxPrecision)); - } - - // - // transactions. - // - internal static Exception ConnectionDoomed() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ConnectionDoomed)); - } - - internal static Exception OpenResultCountExceeded() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_OpenResultCountExceeded)); - } - - internal static Exception UnsupportedSysTxForGlobalTransactions() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_UnsupportedSysTxVersion)); - } - - internal static readonly byte[] AttentionHeader = new byte[] { - TdsEnums.MT_ATTN, // Message Type - TdsEnums.ST_EOM, // Status - TdsEnums.HEADER_LEN >> 8, // length - upper byte - TdsEnums.HEADER_LEN & 0xff, // length - lower byte - 0, // spid - 0, // spid - 0, // packet (out of band) - 0 // window - }; - - // - // MultiSubnetFailover - // - - /// - /// used to block two scenarios if MultiSubnetFailover is true: - /// * server-provided failover partner - raising SqlException in this case - /// * connection string with failover partner and MultiSubnetFailover=true - raising argument one in this case with the same message - /// - internal static Exception MultiSubnetFailoverWithFailoverPartner(bool serverProvidedFailoverPartner, SqlInternalConnectionTds internalConnection) - { - string msg = StringsHelper.GetString(Strings.SQLMSF_FailoverPartnerNotSupported); - if (serverProvidedFailoverPartner) - { - // Replacing InvalidOperation with SQL exception - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, msg, "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; // disable open retry logic on this error - return exc; - } - else - { - return ADP.Argument(msg); - } - } - - internal static Exception MultiSubnetFailoverWithMoreThan64IPs() - { - string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithMoreThan64IPs); - return ADP.InvalidOperation(msg); - } - - internal static Exception MultiSubnetFailoverWithInstanceSpecified() - { - string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithInstanceSpecified); - return ADP.Argument(msg); - } - - internal static Exception MultiSubnetFailoverWithNonTcpProtocol() - { - string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithNonTcpProtocol); - return ADP.Argument(msg); - } - - // - // Read-only routing - // - - internal static Exception ROR_FailoverNotSupportedConnString() - { - return ADP.Argument(StringsHelper.GetString(Strings.SQLROR_FailoverNotSupported)); - } - - internal static Exception ROR_FailoverNotSupportedServer(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (StringsHelper.GetString(Strings.SQLROR_FailoverNotSupported)), "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; - return exc; - } - - internal static Exception ROR_RecursiveRoutingNotSupported(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (StringsHelper.GetString(Strings.SQLROR_RecursiveRoutingNotSupported)), "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; - return exc; - } - - internal static Exception ROR_UnexpectedRoutingInfo(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (StringsHelper.GetString(Strings.SQLROR_UnexpectedRoutingInfo)), "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; - return exc; - } - - internal static Exception ROR_InvalidRoutingInfo(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (StringsHelper.GetString(Strings.SQLROR_InvalidRoutingInfo)), "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; - return exc; - } - - internal static Exception ROR_TimeoutAfterRoutingInfo(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (StringsHelper.GetString(Strings.SQLROR_TimeoutAfterRoutingInfo)), "", 0)); - SqlException exc = SqlException.CreateException(errors, null, internalConnection); - exc._doNotReconnect = true; - return exc; - } - - // - // Connection resiliency - // - internal static SqlException CR_ReconnectTimeout() - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(TdsEnums.TIMEOUT_EXPIRED, (byte)0x00, TdsEnums.MIN_ERROR_CLASS, null, SQLMessage.Timeout(), "", 0, TdsEnums.SNI_WAIT_TIMEOUT)); - SqlException exc = SqlException.CreateException(errors, ""); - return exc; - } - - internal static SqlException CR_ReconnectionCancelled() - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, SQLMessage.OperationCancelled(), "", 0)); - SqlException exc = SqlException.CreateException(errors, ""); - return exc; - } - - internal static Exception CR_NextAttemptWillExceedQueryTimeout(SqlException innerException, Guid connectionId) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_NextAttemptWillExceedQueryTimeout), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", connectionId, innerException); - return exc; - } - - internal static Exception CR_EncryptionChanged(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_EncryptionChanged), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", internalConnection); - return exc; - } - - internal static SqlException CR_AllAttemptsFailed(SqlException innerException, Guid connectionId) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_AllAttemptsFailed), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", connectionId, innerException); - return exc; - } - - internal static SqlException CR_NoCRAckAtReconnection(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_NoCRAckAtReconnection), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", internalConnection); - return exc; - } - - internal static SqlException CR_TDSVersionNotPreserved(SqlInternalConnectionTds internalConnection) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_TDSVestionNotPreserved), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", internalConnection); - return exc; - } - - internal static SqlException CR_UnrecoverableServer(Guid connectionId) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_UnrecoverableServer), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", connectionId); - return exc; - } - - internal static SqlException CR_UnrecoverableClient(Guid connectionId) - { - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQLCR_UnrecoverableClient), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", connectionId); - return exc; - } - - internal static Exception StreamWriteNotSupported() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_StreamWriteNotSupported)); - } - internal static Exception StreamReadNotSupported() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_StreamReadNotSupported)); - } - internal static Exception StreamSeekNotSupported() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_StreamSeekNotSupported)); - } - internal static System.Data.SqlTypes.SqlNullValueException SqlNullValue() - { - System.Data.SqlTypes.SqlNullValueException e = new System.Data.SqlTypes.SqlNullValueException(); - return e; - } - internal static Exception SubclassMustOverride() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SqlMisc_SubclassMustOverride)); - } - - // ProjectK\CoreCLR specific errors - internal static Exception UnsupportedKeyword(string keyword) - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedKeyword, keyword)); - } - internal static Exception NetworkLibraryKeywordNotSupported() - { - return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_NetworkLibraryNotSupported)); - } - internal static Exception UnsupportedFeatureAndToken(SqlInternalConnectionTds internalConnection, string token) - { - var innerException = ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedToken, token)); - - SqlErrorCollection errors = new SqlErrorCollection(); - errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, StringsHelper.GetString(Strings.SQL_UnsupportedFeature), "", 0)); - SqlException exc = SqlException.CreateException(errors, "", internalConnection, innerException); - return exc; - } - - internal static Exception BatchedUpdatesNotAvailableOnContextConnection() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_BatchedUpdatesNotAvailableOnContextConnection)); - } - internal static Exception Azure_ManagedIdentityException(string msg) - { - SqlErrorCollection errors = new SqlErrorCollection - { - new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, msg, "", 0) - }; - SqlException exc = SqlException.CreateException(errors, null); - exc._doNotReconnect = true; // disable open retry logic on this error - return exc; - } - - #region Always Encrypted Errors - - #region Always Encrypted - Certificate Store Provider Errors - internal static Exception InvalidKeyEncryptionAlgorithm(string encryptionAlgorithm, string validEncryptionAlgorithm, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidKeyEncryptionAlgorithmSysErr : Strings.TCE_InvalidKeyEncryptionAlgorithm; - return ADP.Argument(StringsHelper.GetString(message, encryptionAlgorithm, validEncryptionAlgorithm), TdsEnums.TCE_PARAM_ENCRYPTION_ALGORITHM); - } - - internal static Exception NullKeyEncryptionAlgorithm(bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_NullKeyEncryptionAlgorithmSysErr : Strings.TCE_NullKeyEncryptionAlgorithm; - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_ENCRYPTION_ALGORITHM, StringsHelper.GetString(message)); - } - - internal static Exception EmptyColumnEncryptionKey() - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_EmptyColumnEncryptionKey), TdsEnums.TCE_PARAM_COLUMNENCRYPTION_KEY); - } - - internal static Exception NullColumnEncryptionKey() - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_COLUMNENCRYPTION_KEY, StringsHelper.GetString(Strings.TCE_NullColumnEncryptionKey)); - } - - internal static Exception EmptyEncryptedColumnEncryptionKey() - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_EmptyEncryptedColumnEncryptionKey), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception NullEncryptedColumnEncryptionKey() - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_ENCRYPTED_CEK, StringsHelper.GetString(Strings.TCE_NullEncryptedColumnEncryptionKey)); - } - - internal static Exception LargeCertificatePathLength(int actualLength, int maxLength, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_LargeCertificatePathLengthSysErr : Strings.TCE_LargeCertificatePathLength; - return ADP.Argument(StringsHelper.GetString(message, actualLength, maxLength), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - - } - - internal static Exception NullCertificatePath(string[] validLocations, bool isSystemOp) - { - Debug.Assert(2 == validLocations.Length); - string message = isSystemOp ? Strings.TCE_NullCertificatePathSysErr : Strings.TCE_NullCertificatePath; - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(message, validLocations[0], validLocations[1], @"/")); - } - - internal static Exception NullCspKeyPath(bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_NullCspPathSysErr : Strings.TCE_NullCspPath; - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(message, @"/")); - } - - internal static Exception NullCngKeyPath(bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_NullCngPathSysErr : Strings.TCE_NullCngPath; - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(message, @"/")); - } - - internal static Exception InvalidCertificatePath(string actualCertificatePath, string[] validLocations, bool isSystemOp) - { - Debug.Assert(2 == validLocations.Length); - string message = isSystemOp ? Strings.TCE_InvalidCertificatePathSysErr : Strings.TCE_InvalidCertificatePath; - return ADP.Argument(StringsHelper.GetString(message, actualCertificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCspPath(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCspPathSysErr : Strings.TCE_InvalidCspPath; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCngPath(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCngPathSysErr : Strings.TCE_InvalidCngPath; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception EmptyCspName(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_EmptyCspNameSysErr : Strings.TCE_EmptyCspName; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception EmptyCngName(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_EmptyCngNameSysErr : Strings.TCE_EmptyCngName; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception EmptyCspKeyId(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_EmptyCspKeyIdSysErr : Strings.TCE_EmptyCspKeyId; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception EmptyCngKeyId(string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_EmptyCngKeyIdSysErr : Strings.TCE_EmptyCngKeyId; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCspName(string cspName, string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCspNameSysErr : Strings.TCE_InvalidCspName; - return ADP.Argument(StringsHelper.GetString(message, cspName, masterKeyPath), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCspKeyIdentifier(string keyIdentifier, string masterKeyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCspKeyIdSysErr : Strings.TCE_InvalidCspKeyId; - return ADP.Argument(StringsHelper.GetString(message, keyIdentifier, masterKeyPath), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCngKey(string masterKeyPath, string cngProviderName, string keyIdentifier, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCngKeySysErr : Strings.TCE_InvalidCngKey; - return ADP.Argument(StringsHelper.GetString(message, masterKeyPath, cngProviderName, keyIdentifier), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCertificateLocation(string certificateLocation, string certificatePath, string[] validLocations, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCertificateLocationSysErr : Strings.TCE_InvalidCertificateLocation; - return ADP.Argument(StringsHelper.GetString(message, certificateLocation, certificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidCertificateStore(string certificateStore, string certificatePath, string validCertificateStore, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_InvalidCertificateStoreSysErr : Strings.TCE_InvalidCertificateStore; - return ADP.Argument(StringsHelper.GetString(message, certificateStore, certificatePath, validCertificateStore), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception EmptyCertificateThumbprint(string certificatePath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_EmptyCertificateThumbprintSysErr : Strings.TCE_EmptyCertificateThumbprint; - return ADP.Argument(StringsHelper.GetString(message, certificatePath), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception CertificateNotFound(string thumbprint, string certificateLocation, string certificateStore, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_CertificateNotFoundSysErr : Strings.TCE_CertificateNotFound; - return ADP.Argument(StringsHelper.GetString(message, thumbprint, certificateLocation, certificateStore), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - - internal static Exception InvalidAlgorithmVersionInEncryptedCEK(byte actual, byte expected) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidAlgorithmVersionInEncryptedCEK, actual.ToString(@"X2"), expected.ToString(@"X2")), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidCiphertextLengthInEncryptedCEK(int actual, int expected, string certificateName) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCiphertextLengthInEncryptedCEK, actual, expected, certificateName), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidCiphertextLengthInEncryptedCEKCsp(int actual, int expected, string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCiphertextLengthInEncryptedCEKCsp, actual, expected, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidCiphertextLengthInEncryptedCEKCng(int actual, int expected, string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCiphertextLengthInEncryptedCEKCng, actual, expected, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidSignatureInEncryptedCEK(int actual, int expected, string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidSignatureInEncryptedCEK, actual, expected, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidSignatureInEncryptedCEKCsp(int actual, int expected, string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidSignatureInEncryptedCEKCsp, actual, expected, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidSignatureInEncryptedCEKCng(int actual, int expected, string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidSignatureInEncryptedCEKCng, actual, expected, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidCertificateSignature(string certificatePath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateSignature, certificatePath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception InvalidSignature(string masterKeyPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidSignature, masterKeyPath), TdsEnums.TCE_PARAM_ENCRYPTED_CEK); - } - - internal static Exception CertificateWithNoPrivateKey(string keyPath, bool isSystemOp) - { - string message = isSystemOp ? Strings.TCE_CertificateWithNoPrivateKeySysErr : Strings.TCE_CertificateWithNoPrivateKey; - return ADP.Argument(StringsHelper.GetString(message, keyPath), TdsEnums.TCE_PARAM_MASTERKEY_PATH); - } - #endregion Always Encrypted - Certificate Store Provider Errors - - #region Always Encrypted - Cryptographic Algorithms Error messages - internal static Exception NullPlainText() - { - return ADP.ArgumentNull(StringsHelper.GetString(Strings.TCE_NullPlainText)); - } - - internal static Exception NullCipherText() - { - return ADP.ArgumentNull(StringsHelper.GetString(Strings.TCE_NullCipherText)); - } - - internal static Exception NullColumnEncryptionAlgorithm(string supportedAlgorithms) - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_ENCRYPTION_ALGORITHM, StringsHelper.GetString(Strings.TCE_NullColumnEncryptionAlgorithm, supportedAlgorithms)); - } - - internal static Exception NullColumnEncryptionKeySysErr() - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_ENCRYPTIONKEY, StringsHelper.GetString(Strings.TCE_NullColumnEncryptionKeySysErr)); - } - - internal static Exception InvalidKeySize(string algorithmName, int actualKeylength, int expectedLength) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidKeySize, algorithmName, actualKeylength, expectedLength), TdsEnums.TCE_PARAM_ENCRYPTIONKEY); - } - - internal static Exception InvalidEncryptionType(string algorithmName, SqlClientEncryptionType encryptionType, params SqlClientEncryptionType[] validEncryptionTypes) - { - const string valueSeparator = @", "; - return ADP.Argument( - StringsHelper.GetString( - Strings.TCE_InvalidEncryptionType, - algorithmName, - encryptionType.ToString(), - string.Join(valueSeparator, Map(validEncryptionTypes, static validEncryptionType => $"'{validEncryptionType:G}'")) - ), - TdsEnums.TCE_PARAM_ENCRYPTIONTYPE - ); - } - - internal static Exception InvalidCipherTextSize(int actualSize, int minimumSize) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCipherTextSize, actualSize, minimumSize), TdsEnums.TCE_PARAM_CIPHERTEXT); - } - - internal static Exception InvalidAlgorithmVersion(byte actual, byte expected) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidAlgorithmVersion, actual.ToString(@"X2"), expected.ToString(@"X2")), TdsEnums.TCE_PARAM_CIPHERTEXT); - } - - internal static Exception InvalidAuthenticationTag() - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidAuthenticationTag), TdsEnums.TCE_PARAM_CIPHERTEXT); - } - #endregion Always Encrypted - Cryptographic Algorithms Error messages - - #region Always Encrypted - Errors from sp_describe_parameter_encryption - internal static Exception UnexpectedDescribeParamFormatParameterMetadata() - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnexpectedDescribeParamFormatParameterMetadata, "sp_describe_parameter_encryption")); - } - - internal static Exception UnexpectedDescribeParamFormatAttestationInfo(string enclaveType) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnexpectedDescribeParamFormatAttestationInfo, "sp_describe_parameter_encryption", enclaveType)); - } - - internal static Exception InvalidEncryptionKeyOrdinalEnclaveMetadata(int ordinal, int maxOrdinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_InvalidEncryptionKeyOrdinalEnclaveMetadata, ordinal, maxOrdinal)); - } - - internal static Exception InvalidEncryptionKeyOrdinalParameterMetadata(int ordinal, int maxOrdinal) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_InvalidEncryptionKeyOrdinalParameterMetadata, ordinal, maxOrdinal)); - } - - public static Exception MultipleRowsReturnedForAttestationInfo() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_MultipleRowsReturnedForAttestationInfo, "sp_describe_parameter_encryption")); - } - - internal static Exception ParamEncryptionMetadataMissing(string paramName, string procedureName) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_ParamEncryptionMetaDataMissing, "sp_describe_parameter_encryption", paramName, procedureName)); - } - - internal static Exception ProcEncryptionMetadataMissing(string procedureName) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_ProcEncryptionMetaDataMissing, "sp_describe_parameter_encryption", procedureName)); - } - - internal static Exception UnableToVerifyColumnMasterKeySignature(Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_UnableToVerifyColumnMasterKeySignature, innerException.Message), innerException); - } - - internal static Exception ColumnMasterKeySignatureVerificationFailed(string cmkPath) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_ColumnMasterKeySignatureVerificationFailed, cmkPath)); - } - - internal static Exception InvalidKeyStoreProviderName(string providerName, List systemProviders, List customProviders) - { - const string valueSeparator = @", "; - string systemProviderStr = string.Join(valueSeparator, Map(systemProviders, static provider => $"'{provider}'")); - string customProviderStr = string.Join(valueSeparator, Map(customProviders, static provider => $"'{provider}'")); - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidKeyStoreProviderName, providerName, systemProviderStr, customProviderStr)); - } - - internal static Exception ParamInvalidForceColumnEncryptionSetting(string paramName, string procedureName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_ParamInvalidForceColumnEncryptionSetting, TdsEnums.TCE_PARAM_FORCE_COLUMN_ENCRYPTION, paramName, procedureName, "SqlParameter")); - } - - internal static Exception ParamUnExpectedEncryptionMetadata(string paramName, string procedureName) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_ParamUnExpectedEncryptionMetadata, paramName, procedureName, TdsEnums.TCE_PARAM_FORCE_COLUMN_ENCRYPTION, "SqlParameter")); - } - - internal static Exception ColumnMasterKeySignatureNotFound(string cmkPath) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_ColumnMasterKeySignatureNotFound, cmkPath)); - } - #endregion Always Encrypted - Errors from sp_describe_parameter_encryption - - #region Always Encrypted - Errors from secure channel Communication - - internal static Exception ExceptionWhenGeneratingEnclavePackage(Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_ExceptionWhenGeneratingEnclavePackage, innerException.Message), innerException); - } - - internal static Exception FailedToEncryptRegisterRulesBytePackage(Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_FailedToEncryptRegisterRulesBytePackage, innerException.Message), innerException); - } - - internal static Exception InvalidKeyIdUnableToCastToUnsignedShort(int keyId, Exception innerException) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidKeyIdUnableToCastToUnsignedShort, keyId, innerException.Message), innerException); - } - - internal static Exception InvalidDatabaseIdUnableToCastToUnsignedInt(int databaseId, Exception innerException) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidDatabaseIdUnableToCastToUnsignedInt, databaseId, innerException.Message), innerException); - } - - internal static Exception InvalidAttestationParameterUnableToConvertToUnsignedInt(string variableName, int intValue, string enclaveType, Exception innerException) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidAttestationParameterUnableToConvertToUnsignedInt, enclaveType, intValue, variableName, innerException.Message), innerException); - } - - internal static Exception OffsetOutOfBounds(string argument, string type, string method) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_OffsetOutOfBounds, type, method)); - } - - internal static Exception InsufficientBuffer(string argument, string type, string method) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InsufficientBuffer, argument, type, method)); - } - - internal static Exception ColumnEncryptionKeysNotFound() - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_ColumnEncryptionKeysNotFound)); - } - - #endregion Always Encrypted - Errors from secure channel Communication - - #region Always Encrypted - Errors when performing attestation - internal static Exception AttestationInfoNotReturnedFromSqlServer(string enclaveType, string enclaveAttestationUrl) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_AttestationInfoNotReturnedFromSQLServer, enclaveType, enclaveAttestationUrl)); - } - - internal static SqlException AttestationFailed(string errorMessage, Exception innerException = null) - { - SqlErrorCollection errors = new(); - errors.Add(new SqlError( - infoNumber: 0, - errorState: 0, - errorClass: 0, - server: null, - errorMessage, - procedure: string.Empty, - lineNumber: 0)); - return SqlException.CreateException(errors, serverVersion: string.Empty, Guid.Empty, innerException); - } - - #endregion Always Encrypted - Errors when performing attestation - - #region Always Encrypted - Errors when establishing secure channel - internal static Exception NullArgumentInConstructorInternal(string argumentName, string objectUnderConstruction) - { - return ADP.ArgumentNull(argumentName, StringsHelper.GetString(Strings.TCE_NullArgumentInConstructorInternal, argumentName, objectUnderConstruction)); - } - - internal static Exception EmptyArgumentInConstructorInternal(string argumentName, string objectUnderConstruction) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_EmptyArgumentInConstructorInternal, argumentName, objectUnderConstruction)); - } - - internal static Exception NullArgumentInternal(string argumentName, string type, string method) - { - return ADP.ArgumentNull(argumentName, StringsHelper.GetString(Strings.TCE_NullArgumentInternal, argumentName, type, method)); - } - - internal static Exception EmptyArgumentInternal(string argumentName, string type, string method) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_EmptyArgumentInternal, argumentName, type, method)); - } - #endregion Always Encrypted - Errors when establishing secure channel - - #region Always Encrypted - Enclave provider/configuration errors - - internal static Exception CannotGetSqlColumnEncryptionEnclaveProviderConfig(Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_CannotGetSqlColumnEncryptionEnclaveProviderConfig, innerException.Message), innerException); - } - - internal static Exception CannotCreateSqlColumnEncryptionEnclaveProvider(string providerName, string type, Exception innerException) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_CannotCreateSqlColumnEncryptionEnclaveProvider, providerName, type, innerException.Message), innerException); - } - - internal static Exception SqlColumnEncryptionEnclaveProviderNameCannotBeEmpty() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_SqlColumnEncryptionEnclaveProviderNameCannotBeEmpty)); - } - - internal static Exception NoAttestationUrlSpecifiedForEnclaveBasedQuerySpDescribe(string enclaveType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_NoAttestationUrlSpecifiedForEnclaveBasedQuerySpDescribe, "sp_describe_parameter_encryption", enclaveType)); - } - - internal static Exception NoAttestationUrlSpecifiedForEnclaveBasedQueryGeneratingEnclavePackage(string enclaveType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_NoAttestationUrlSpecifiedForEnclaveBasedQueryGeneratingEnclavePackage, enclaveType)); - } - - internal static Exception EnclaveTypeNullForEnclaveBasedQuery() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveTypeNullForEnclaveBasedQuery)); - } - - internal static Exception EnclaveProvidersNotConfiguredForEnclaveBasedQuery() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveProvidersNotConfiguredForEnclaveBasedQuery)); - } - - internal static Exception EnclaveProviderNotFound(string enclaveType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveProviderNotFound, enclaveType)); - } - - internal static Exception NullEnclaveSessionReturnedFromProvider(string enclaveType, string attestationUrl) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_NullEnclaveSessionReturnedFromProvider, enclaveType, attestationUrl)); - } - - #endregion Always Encrypted - Enclave provider/configuration errors - - #region Always Encrypted - Generic toplevel failures - - internal static Exception GetExceptionArray(string serverName, string errorMessage, Exception e) - { - // Create and throw an exception array - SqlErrorCollection sqlErs = new SqlErrorCollection(); - Exception exceptionToInclude = (null != e.InnerException) ? e.InnerException : e; - sqlErs.Add(new SqlError(infoNumber: 0, errorState: (byte)0x00, errorClass: (byte)TdsEnums.MIN_ERROR_CLASS, server: serverName, errorMessage: errorMessage, procedure: null, lineNumber: 0)); - - if (e is SqlException) - { - SqlException exThrown = (SqlException)e; - SqlErrorCollection errorList = exThrown.Errors; - for (int i = 0; i < exThrown.Errors.Count; i++) - { - sqlErs.Add(errorList[i]); - } - } - else - { - sqlErs.Add(new SqlError(infoNumber: 0, errorState: (byte)0x00, errorClass: (byte)TdsEnums.MIN_ERROR_CLASS, server: serverName, errorMessage: e.Message, procedure: null, lineNumber: 0)); - } - - return SqlException.CreateException(sqlErs, "", null, exceptionToInclude); - } - - internal static Exception ColumnDecryptionFailed(string columnName, string serverName, Exception e) - { - return GetExceptionArray(serverName, StringsHelper.GetString(Strings.TCE_ColumnDecryptionFailed, columnName), e); - } - - internal static Exception ParamEncryptionFailed(string paramName, string serverName, Exception e) - { - return GetExceptionArray(serverName, StringsHelper.GetString(Strings.TCE_ParamEncryptionFailed, paramName), e); - } - - internal static Exception ParamDecryptionFailed(string paramName, string serverName, Exception e) - { - return GetExceptionArray(serverName, StringsHelper.GetString(Strings.TCE_ParamDecryptionFailed, paramName), e); - } - #endregion Always Encrypted - Generic toplevel failures - - #region Always Encrypted - Client side query processing errors - - internal static Exception UnknownColumnEncryptionAlgorithm(string algorithmName, string supportedAlgorithms) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnknownColumnEncryptionAlgorithm, algorithmName, supportedAlgorithms)); - } - - internal static Exception UnknownColumnEncryptionAlgorithmId(int algoId, string supportAlgorithmIds) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnknownColumnEncryptionAlgorithmId, algoId, supportAlgorithmIds), TdsEnums.TCE_PARAM_CIPHER_ALGORITHM_ID); - } - - internal static Exception UnsupportedNormalizationVersion(byte version) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnsupportedNormalizationVersion, version, "'1'", "SQL Server")); - } - - internal static Exception UnrecognizedKeyStoreProviderName(string providerName, List systemProviders, List customProviders) - { - const string valueSeparator = @", "; - string systemProviderStr = string.Join(valueSeparator, Map(systemProviders, static provider => @"'" + provider + @"'")); - string customProviderStr = string.Join(valueSeparator, Map(customProviders, static provider => @"'" + provider + @"'")); - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnrecognizedKeyStoreProviderName, providerName, systemProviderStr, customProviderStr)); - } - - internal static Exception InvalidDataTypeForEncryptedParameter(string parameterName, int actualDataType, int expectedDataType) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_NullProviderValue, parameterName, actualDataType, expectedDataType)); - } - - internal static Exception KeyDecryptionFailed(string providerName, string keyHex, Exception e) - { - - if (providerName.Equals(SqlColumnEncryptionCertificateStoreProvider.ProviderName)) - { - return GetExceptionArray(null, StringsHelper.GetString(Strings.TCE_KeyDecryptionFailedCertStore, providerName, keyHex), e); - } - else - { - return GetExceptionArray(null, StringsHelper.GetString(Strings.TCE_KeyDecryptionFailed, providerName, keyHex), e); - } - } - - internal static Exception UntrustedKeyPath(string keyPath, string serverName) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UntrustedKeyPath, keyPath, serverName)); - } - - internal static Exception UnsupportedDatatypeEncryption(string dataType) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_UnsupportedDatatype, dataType)); - } - - internal static Exception ThrowDecryptionFailed(string keyStr, string valStr, Exception e) - { - return GetExceptionArray(null, StringsHelper.GetString(Strings.TCE_DecryptionFailed, keyStr, valStr), e); - } - - internal static Exception NullEnclaveSessionDuringQueryExecution(string enclaveType, string enclaveAttestationUrl) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_NullEnclaveSessionDuringQueryExecution, enclaveType, enclaveAttestationUrl)); - } - - internal static Exception NullEnclavePackageForEnclaveBasedQuery(string enclaveType, string enclaveAttestationUrl) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_NullEnclavePackageForEnclaveBasedQuery, enclaveType, enclaveAttestationUrl)); - } - - internal static Exception EnclaveProviderNotFound(string enclaveType, string attestationProtocol) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveProviderNotFound, enclaveType, attestationProtocol)); - } - - internal static Exception EnclaveTypeNotSupported(string enclaveType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveTypeNotSupported, enclaveType)); - } - - internal static Exception AttestationProtocolNotSupportEnclaveType(string attestationProtocolStr, string enclaveType) - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_AttestationProtocolNotSupportEnclaveType, attestationProtocolStr, enclaveType)); - } - - internal static Exception AttestationProtocolNotSpecifiedForGeneratingEnclavePackage() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_AttestationProtocolNotSpecifiedForGeneratingEnclavePackage)); - } - - #endregion Always Encrypted - Client side query processing errors - - #region Always Encrypted - SQL connection related error messages - - internal static Exception TceNotSupported() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_NotSupportedByServer, "SQL Server")); - } - - internal static Exception EnclaveComputationsNotSupported() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveComputationsNotSupported)); - } - - internal static Exception AttestationURLNotSupported() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_AttestationURLNotSupported)); - } - - internal static Exception AttestationProtocolNotSupported() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_AttestationProtocolNotSupported)); - } - - internal static Exception EnclaveTypeNotReturned() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_EnclaveTypeNotReturned)); - } - #endregion Always Encrypted - SQL connection related error messages - - #region Always Encrypted - Extensibility related error messages - - internal static Exception CanOnlyCallOnce() - { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.TCE_CanOnlyCallOnce)); - } - - internal static Exception NullCustomKeyStoreProviderDictionary() - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_CLIENT_KEYSTORE_PROVIDERS, StringsHelper.GetString(Strings.TCE_NullCustomKeyStoreProviderDictionary)); - } - - internal static Exception InvalidCustomKeyStoreProviderName(string providerName, string prefix) - { - return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCustomKeyStoreProviderName, providerName, prefix), TdsEnums.TCE_PARAM_CLIENT_KEYSTORE_PROVIDERS); - } - - internal static Exception NullProviderValue(string providerName) - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_CLIENT_KEYSTORE_PROVIDERS, StringsHelper.GetString(Strings.TCE_NullProviderValue, providerName)); - } - - internal static Exception EmptyProviderName() - { - return ADP.ArgumentNull(TdsEnums.TCE_PARAM_CLIENT_KEYSTORE_PROVIDERS, StringsHelper.GetString(Strings.TCE_EmptyProviderName)); - } - #endregion Always Encrypted - Extensibility related error messages - - #endregion Always Encrypted Errors - - /// - /// gets a message for SNI error (sniError must be valid, non-zero error code) - /// - internal static string GetSNIErrorMessage(int sniError) - { - Debug.Assert(sniError > 0 && sniError <= (int)SNINativeMethodWrapper.SniSpecialErrors.MaxErrorValue, "SNI error is out of range"); - - string errorMessageId = string.Format("SNI_ERROR_{0}", sniError); - return StringsHelper.GetResourceString(errorMessageId); - } - - // Default values for SqlDependency and SqlNotificationRequest - internal const int SqlDependencyTimeoutDefault = 0; - internal const int SqlDependencyServerTimeout = 5 * 24 * 3600; // 5 days - used to compute default TTL of the dependency - internal const string SqlNotificationServiceDefault = "SqlQueryNotificationService"; - internal const string SqlNotificationStoredProcedureDefault = "SqlQueryNotificationStoredProcedure"; - - private static IEnumerable Map(IEnumerable source, Func selector) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (selector == null) - { - throw new ArgumentNullException(nameof(selector)); - } - - foreach (T element in source) - { - yield return selector(element); - } - } - } - - sealed internal class SQLMessage - { - private SQLMessage() { /* prevent utility class from being instantiated*/ } - - // The class SQLMessage defines the error messages that are specific to the SqlDataAdapter - // that are caused by a netlib error. The functions will be called and then return the - // appropriate error message from the resource Framework.txt. The SqlDataAdapter will then - // take the error message and then create a SqlError for the message and then place - // that into a SqlException that is either thrown to the user or cached for throwing at - // a later time. This class is used so that there will be compile time checking of error - // messages. The resource Framework.txt will ensure proper string text based on the appropriate - // locale. - - internal static string CultureIdError() - { - return StringsHelper.GetString(Strings.SQL_CultureIdError); - } - internal static string EncryptionNotSupportedByClient() - { - return StringsHelper.GetString(Strings.SQL_EncryptionNotSupportedByClient); - } - internal static string EncryptionNotSupportedByServer() - { - return StringsHelper.GetString(Strings.SQL_EncryptionNotSupportedByServer); - } - internal static string OperationCancelled() - { - return StringsHelper.GetString(Strings.SQL_OperationCancelled); - } - internal static string SevereError() - { - return StringsHelper.GetString(Strings.SQL_SevereError); - } - internal static string SSPIInitializeError() - { - return StringsHelper.GetString(Strings.SQL_SSPIInitializeError); - } - internal static string SSPIGenerateError() - { - return StringsHelper.GetString(Strings.SQL_SSPIGenerateError); - } - internal static string KerberosTicketMissingError() - { - return StringsHelper.GetString(Strings.SQL_KerberosTicketMissingError); - } - internal static string Timeout() - { - return StringsHelper.GetString(Strings.SQL_Timeout_Execution); - } - internal static string Timeout_PreLogin_Begin() - { - return StringsHelper.GetString(Strings.SQL_Timeout_PreLogin_Begin); - } - internal static string Timeout_PreLogin_InitializeConnection() - { - return StringsHelper.GetString(Strings.SQL_Timeout_PreLogin_InitializeConnection); - } - internal static string Timeout_PreLogin_SendHandshake() - { - return StringsHelper.GetString(Strings.SQL_Timeout_PreLogin_SendHandshake); - } - internal static string Timeout_PreLogin_ConsumeHandshake() - { - return StringsHelper.GetString(Strings.SQL_Timeout_PreLogin_ConsumeHandshake); - } - internal static string Timeout_Login_Begin() - { - return StringsHelper.GetString(Strings.SQL_Timeout_Login_Begin); - } - internal static string Timeout_Login_ProcessConnectionAuth() - { - return StringsHelper.GetString(Strings.SQL_Timeout_Login_ProcessConnectionAuth); - } - internal static string Timeout_PostLogin() - { - return StringsHelper.GetString(Strings.SQL_Timeout_PostLogin); - } - internal static string Timeout_FailoverInfo() - { - return StringsHelper.GetString(Strings.SQL_Timeout_FailoverInfo); - } - internal static string Timeout_RoutingDestination() - { - return StringsHelper.GetString(Strings.SQL_Timeout_RoutingDestinationInfo); - } - internal static string Duration_PreLogin_Begin(long PreLoginBeginDuration) - { - return StringsHelper.GetString(Strings.SQL_Duration_PreLogin_Begin, PreLoginBeginDuration); - } - internal static string Duration_PreLoginHandshake(long PreLoginBeginDuration, long PreLoginHandshakeDuration) - { - return StringsHelper.GetString(Strings.SQL_Duration_PreLoginHandshake, PreLoginBeginDuration, PreLoginHandshakeDuration); - } - internal static string Duration_Login_Begin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration) - { - return StringsHelper.GetString(Strings.SQL_Duration_Login_Begin, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration); - } - internal static string Duration_Login_ProcessConnectionAuth(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration) - { - return StringsHelper.GetString(Strings.SQL_Duration_Login_ProcessConnectionAuth, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration, LoginAuthDuration); - } - internal static string Duration_PostLogin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration, long PostLoginDuration) - { - return StringsHelper.GetString(Strings.SQL_Duration_PostLogin, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration, LoginAuthDuration, PostLoginDuration); - } - internal static string UserInstanceFailure() - { - return StringsHelper.GetString(Strings.SQL_UserInstanceFailure); - } - internal static string PreloginError() - { - return StringsHelper.GetString(Strings.Snix_PreLogin); - } - internal static string ExClientConnectionId() - { - return StringsHelper.GetString(Strings.SQL_ExClientConnectionId); - } - internal static string ExErrorNumberStateClass() - { - return StringsHelper.GetString(Strings.SQL_ExErrorNumberStateClass); - } - internal static string ExOriginalClientConnectionId() - { - return StringsHelper.GetString(Strings.SQL_ExOriginalClientConnectionId); - } - internal static string ExRoutingDestination() - { - return StringsHelper.GetString(Strings.SQL_ExRoutingDestination); - } - } - - /// - /// This class holds helper methods to escape Microsoft SQL Server identifiers, such as table, schema, database or other names - /// - internal static class SqlServerEscapeHelper - { - /// - /// Escapes the identifier with square brackets. The input has to be in unescaped form, like the parts received from MultipartIdentifier.ParseMultipartIdentifier. - /// - /// name of the identifier, in unescaped form - /// escapes the name with [], also escapes the last close bracket with double-bracket - internal static string EscapeIdentifier(string name) - { - Debug.Assert(!string.IsNullOrEmpty(name), "null or empty identifiers are not allowed"); - return "[" + name.Replace("]", "]]") + "]"; - } - - /// - /// Same as above EscapeIdentifier, except that output is written into StringBuilder - /// - internal static void EscapeIdentifier(StringBuilder builder, string name) - { - Debug.Assert(builder != null, "builder cannot be null"); - Debug.Assert(!string.IsNullOrEmpty(name), "null or empty identifiers are not allowed"); - - builder.Append("["); - builder.Append(name.Replace("]", "]]")); - builder.Append("]"); - } - - /// - /// Escape a string to be used inside TSQL literal, such as N'somename' or 'somename' - /// - internal static string EscapeStringAsLiteral(string input) - { - Debug.Assert(input != null, "input string cannot be null"); - return input.Replace("'", "''"); - } - - /// - /// Escape a string as a TSQL literal, wrapping it around with single quotes. - /// Use this method to escape input strings to prevent SQL injection - /// and to get correct behavior for embedded quotes. - /// - /// unescaped string - /// escaped and quoted literal string - internal static string MakeStringLiteral(string input) - { - if (string.IsNullOrEmpty(input)) - { - return "''"; - } - else - { - return "'" + EscapeStringAsLiteral(input) + "'"; - } - } - } - - /// - /// This class holds methods invoked on System.Transactions through reflection for Global Transactions - /// - internal static class SysTxForGlobalTransactions - { - private static readonly Lazy _enlistPromotableSinglePhase = new Lazy(() => - typeof(Transaction).GetMethod("EnlistPromotableSinglePhase", new Type[] { typeof(IPromotableSinglePhaseNotification), typeof(Guid) })); - - private static readonly Lazy _setDistributedTransactionIdentifier = new Lazy(() => - typeof(Transaction).GetMethod("SetDistributedTransactionIdentifier", new Type[] { typeof(IPromotableSinglePhaseNotification), typeof(Guid) })); - - private static readonly Lazy _getPromotedToken = new Lazy(() => - typeof(Transaction).GetMethod("GetPromotedToken")); - - /// - /// Enlists the given IPromotableSinglePhaseNotification and Non-MSDTC Promoter type into a transaction - /// - /// The MethodInfo instance to be invoked. Null if the method doesn't exist - public static MethodInfo EnlistPromotableSinglePhase - { - get - { - return _enlistPromotableSinglePhase.Value; - } - } - - /// - /// Sets the given DistributedTransactionIdentifier for a Transaction instance. - /// Needs to be invoked when using a Non-MSDTC Promoter type - /// - /// The MethodInfo instance to be invoked. Null if the method doesn't exist - public static MethodInfo SetDistributedTransactionIdentifier - { - get - { - return _setDistributedTransactionIdentifier.Value; - } - } - - /// - /// Gets the Promoted Token for a Transaction - /// - /// The MethodInfo instance to be invoked. Null if the method doesn't exist - public static MethodInfo GetPromotedToken - { - get - { - return _getPromotedToken.Value; - } - } - } - -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetCoreApp.cs index d8026b36e3..95dd0d9731 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetCoreApp.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; +using System.Buffers.Binary; namespace Microsoft.Data.SqlClient { @@ -11,9 +12,9 @@ internal sealed partial class TdsParser { internal static void FillGuidBytes(Guid guid, Span buffer) => guid.TryWriteBytes(buffer); - internal static void FillDoubleBytes(double value, Span buffer) => BitConverter.TryWriteBytes(buffer, value); + internal static void FillDoubleBytes(double value, Span buffer) => BinaryPrimitives.TryWriteInt64LittleEndian(buffer, BitConverter.DoubleToInt64Bits(value)); - internal static void FillFloatBytes(float v, Span buffer) => BitConverter.TryWriteBytes(buffer, v); + internal static void FillFloatBytes(float value, Span buffer) => BinaryPrimitives.TryWriteInt32LittleEndian(buffer, BitConverterCompatible.SingleToInt32Bits(value)); internal static Guid ConstructGuid(ReadOnlySpan bytes) { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetStandard.cs deleted file mode 100644 index 72c0b77b19..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetStandard.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Buffers; -using System.Diagnostics; - -namespace Microsoft.Data.SqlClient -{ - internal sealed partial class TdsParser - { - internal static void FillGuidBytes(Guid guid, Span buffer) - { - byte[] bytes = guid.ToByteArray(); - bytes.AsSpan().CopyTo(buffer); - } - - internal static void FillDoubleBytes(double value, Span buffer) - { - byte[] bytes = BitConverter.GetBytes(value); - bytes.AsSpan().CopyTo(buffer); - } - - internal static void FillFloatBytes(float value, Span buffer) - { - byte[] bytes = BitConverter.GetBytes(value); - bytes.AsSpan().CopyTo(buffer); - } - - internal static Guid ConstructGuid(ReadOnlySpan bytes) - { - Debug.Assert(bytes.Length >= 16, "not enough bytes to set guid"); - byte[] temp = ArrayPool.Shared.Rent(16); - bytes.CopyTo(temp.AsSpan()); - Guid retval = new Guid(temp); - ArrayPool.Shared.Return(temp); - return retval; - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.Windows.cs index f7a0363f27..7f15666951 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.Windows.cs @@ -10,8 +10,6 @@ namespace Microsoft.Data.SqlClient { internal sealed partial class TdsParser { - private static volatile bool s_fSSPILoaded = false; // bool to indicate whether library has been loaded - internal void PostReadAsyncForMars() { if (TdsParserStateObjectFactory.UseManagedSNI) @@ -43,37 +41,7 @@ internal void PostReadAsyncForMars() _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj)); ThrowExceptionAndWarning(_physicalStateObj); } - } - - private void LoadSSPILibrary() - { - if (TdsParserStateObjectFactory.UseManagedSNI) - return; - // Outer check so we don't acquire lock once it's loaded. - if (!s_fSSPILoaded) - { - lock (s_tdsParserLock) - { - // re-check inside lock - if (!s_fSSPILoaded) - { - // use local for ref param to defer setting s_maxSSPILength until we know the call succeeded. - uint maxLength = 0; - - if (0 != SNINativeMethodWrapper.SNISecInitPackage(ref maxLength)) - SSPIError(SQLMessage.SSPIInitializeError(), TdsEnums.INIT_SSPI_PACKAGE); - - s_maxSSPILength = maxLength; - s_fSSPILoaded = true; - } - } - } - - if (s_maxSSPILength > int.MaxValue) - { - throw SQL.InvalidSSPIPacketSize(); // SqlBu 332503 - } - } + } private void WaitForSSLHandShakeToComplete(ref uint error, ref int protocolVersion) { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index a2201e5e23..fa05ba5abd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; +using System.Buffers.Binary; using System.Collections.Generic; using System.Data; using System.Data.SqlTypes; @@ -40,9 +41,32 @@ internal struct SNIErrorDetails // and surfacing objects to the user. internal sealed partial class TdsParser { + internal struct ReliabilitySection + { + /// + /// This is a no-op in netcore version. Only needed for merging with netfx codebase. + /// + [Conditional("NETFRAMEWORK")] + internal static void Assert(string message) + { + } + + [Conditional("NETFRAMEWORK")] + internal void Start() + { + } + + [Conditional("NETFRAMEWORK")] + internal void Stop() + { + } + } + private static int _objectTypeCount; // EventSource counter private readonly SqlClientLogger _logger = new SqlClientLogger(); + private SSPIContextProvider _authenticationProvider; + internal readonly int _objectID = Interlocked.Increment(ref _objectTypeCount); internal int ObjectID => _objectID; @@ -134,22 +158,19 @@ internal sealed partial class TdsParser // NIC address caching private static byte[] s_nicAddress; // cache the NIC address from the registry - // SSPI variables - - private volatile static uint s_maxSSPILength = 0; // variable to hold max SSPI data size, keep for token from server - // textptr sequence private static readonly byte[] s_longDataHeader = { 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - private static object s_tdsParserLock = new object(); - - // XML metadata substitute sequence private static readonly byte[] s_xmlMetadataSubstituteSequence = { 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // size of Guid (e.g. _clientConnectionId, ActivityId.Id) private const int GUID_SIZE = 16; + // now data length is 1 byte + // First bit is 1 indicating client support failover partner with readonly intent + private static readonly byte[] s_featureExtDataAzureSQLSupportFeatureRequest = { 0x01 }; + // NOTE: You must take the internal connection's _parserLock before modifying this internal bool _asyncWrite = false; @@ -224,16 +245,16 @@ internal SqlInternalTransaction CurrentTransaction set { Debug.Assert(value == _currentTransaction - || null == _currentTransaction - || null == value - || (null != _currentTransaction && !_currentTransaction.IsLocal), "attempting to change current transaction?"); + || _currentTransaction == null + || value == null + || (_currentTransaction != null && !_currentTransaction.IsLocal), "attempting to change current transaction?"); // If there is currently a transaction active, we don't want to // change it; this can occur when there is a delegated transaction // and the user attempts to do an API begin transaction; in these // cases, it's safe to ignore the set. - if ((null == _currentTransaction && null != value) - || (null != _currentTransaction && null == value)) + if ((_currentTransaction == null && value != null) + || (_currentTransaction != null && value == null)) { _currentTransaction = value; } @@ -286,7 +307,7 @@ internal SqlInternalTransaction PendingTransaction } set { - Debug.Assert(null != value, "setting a non-null PendingTransaction?"); + Debug.Assert(value != null, "setting a non-null PendingTransaction?"); _pendingTransaction = value; } } @@ -410,11 +431,12 @@ internal void Connect( } _sniSpnBuffer = null; + _authenticationProvider = null; // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server if (integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated) { - LoadSSPILibrary(); + _authenticationProvider = _physicalStateObj.CreateSSPIContextProvider(); SqlClientEventSource.Log.TryTraceEvent("TdsParser.Connect | SEC | SSPI or Active Directory Authentication Library loaded for SQL Server based integrated authentication"); } @@ -460,6 +482,8 @@ internal void Connect( hostNameInCertificate, serverCertificateFilename); + _authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this); + if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status) { _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj)); @@ -476,7 +500,7 @@ internal void Connect( _server = serverInfo.ResolvedServerName; - if (null != connHandler.PoolGroupProviderInfo) + if (connHandler.PoolGroupProviderInfo != null) { // If we are pooling, check to see if we were processing an // alias which has changed, which means we need to clean out @@ -498,7 +522,7 @@ internal void Connect( uint result = _physicalStateObj.SniGetConnectionId(ref _connHandler._clientConnectionId); Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId"); - if (null == _connHandler.pendingSQLDNSObject) + if (_connHandler.pendingSQLDNSObject == null) { // for DNS Caching phase 1 _physicalStateObj.AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache, ref _connHandler.pendingSQLDNSObject); @@ -517,14 +541,21 @@ internal void Connect( } SqlClientEventSource.Log.TryTraceEvent(" Sending prelogin handshake"); - // SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); + SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake); _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake); _physicalStateObj.SniContext = SniContext.Snix_PreLogin; SqlClientEventSource.Log.TryTraceEvent(" Consuming prelogin handshake"); - PreLoginHandshakeStatus status = PreLoginHandshakeStatus.Successful; + PreLoginHandshakeStatus status = ConsumePreLoginHandshake( + encrypt, + trustServerCert, + integratedSecurity, + out marsCapable, + out _connHandler._fedAuthRequired, + isTlsFirst, + serverCertificateFilename); if (status == PreLoginHandshakeStatus.InstanceFailure) { @@ -533,7 +564,6 @@ internal void Connect( // On Instance failure re-connect and flush SNI named instance cache. _physicalStateObj.SniContext = SniContext.Snix_Connect; - _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, timeout, out instanceName, @@ -550,6 +580,8 @@ internal void Connect( hostNameInCertificate, serverCertificateFilename); + _authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this); + if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status) { _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj)); @@ -562,13 +594,13 @@ internal void Connect( Debug.Assert(retCode == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId"); SqlClientEventSource.Log.TryTraceEvent(" Sending prelogin handshake"); - if (null == _connHandler.pendingSQLDNSObject) + if (_connHandler.pendingSQLDNSObject == null) { // for DNS Caching phase 1 _physicalStateObj.AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache, ref _connHandler.pendingSQLDNSObject); } - // SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); + SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); status = ConsumePreLoginHandshake( encrypt, trustServerCert, @@ -921,8 +953,8 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( fedAuthRequired = false; bool is2005OrLater = false; Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - bool result = _physicalStateObj.TryReadNetworkPacket(); - if (!result) + TdsOperationStatus result = _physicalStateObj.TryReadNetworkPacket(); + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -935,7 +967,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( ThrowExceptionAndWarning(_physicalStateObj); } - if (!_physicalStateObj.TryProcessHeader()) + if (_physicalStateObj.TryProcessHeader() != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -948,7 +980,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); result = _physicalStateObj.TryReadByteArray(payload, payload.Length); - if (!result) + if (result != TdsOperationStatus.Done) { throw SQL.SynchronousCallMayNotPend(); } @@ -964,6 +996,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( int payloadOffset = 0; int payloadLength = 0; int option = payload[offset++]; + bool serverSupportsEncryption = false; while (option != (byte)PreLoginOptions.LASTOPT) { @@ -987,6 +1020,13 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( break; case (int)PreLoginOptions.ENCRYPT: + if (tlsFirst) + { + // Can skip/ignore this option if we are doing TDS 8. + offset += 4; + break; + } + payloadOffset = payload[offset++] << 8 | payload[offset++]; payloadLength = payload[offset++] << 8 | payload[offset++]; @@ -1000,16 +1040,11 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( LOGIN } */ + // Any response other than NOT_SUP means the server supports encryption. + serverSupportsEncryption = serverOption != EncryptionOptions.NOT_SUP; + switch (_encryptionOption) { - case (EncryptionOptions.ON): - if (serverOption == EncryptionOptions.NOT_SUP) - { - _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0)); - _physicalStateObj.Dispose(); - ThrowExceptionAndWarning(_physicalStateObj); - } - break; case (EncryptionOptions.OFF): if (serverOption == EncryptionOptions.OFF) { @@ -1027,6 +1062,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( case (EncryptionOptions.NOT_SUP): if (!tlsFirst && serverOption == EncryptionOptions.REQ) { + // Server requires encryption, but client does not support it. _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByClient(), "", 0)); _physicalStateObj.Dispose(); ThrowExceptionAndWarning(_physicalStateObj); @@ -1034,23 +1070,16 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( break; default: - Debug.Fail("Invalid client encryption option detected"); + // Any other client option needs encryption + if (serverOption == EncryptionOptions.NOT_SUP) + { + _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0)); + _physicalStateObj.Dispose(); + ThrowExceptionAndWarning(_physicalStateObj); + } break; } - if (_encryptionOption == EncryptionOptions.ON || - _encryptionOption == EncryptionOptions.LOGIN) - { - // Validate Certificate if Trust Server Certificate=false and Encryption forced (EncryptionOptions.ON) from Server. - bool shouldValidateServerCert = (_encryptionOption == EncryptionOptions.ON && !trustServerCert) || - ((_connHandler._accessTokenInBytes != null || _connHandler._accessTokenCallback != null) - && !trustServerCert); - uint info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0) - | (is2005OrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0); - - EnableSsl(info, encrypt, integratedSecurity, serverCert); - } - break; case (int)PreLoginOptions.INSTANCE: @@ -1131,6 +1160,25 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( } } + if (_encryptionOption == EncryptionOptions.ON || + _encryptionOption == EncryptionOptions.LOGIN) + { + if (!serverSupportsEncryption) + { + _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0)); + _physicalStateObj.Dispose(); + ThrowExceptionAndWarning(_physicalStateObj); + } + + // Validate Certificate if Trust Server Certificate=false and Encryption forced (EncryptionOptions.ON) from Server. + bool shouldValidateServerCert = (_encryptionOption == EncryptionOptions.ON && !trustServerCert) || + (_connHandler._accessTokenInBytes != null && !trustServerCert); + uint info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0) + | (is2005OrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0); + + EnableSsl(info, encrypt, integratedSecurity, serverCert); + } + return PreLoginHandshakeStatus.Successful; } @@ -1148,9 +1196,9 @@ internal void Deactivate(bool connectionIsDoomed) _sessionPool.Deactivate(); } - Debug.Assert(connectionIsDoomed || null == _pendingTransaction, "pending transaction at disconnect?"); + Debug.Assert(connectionIsDoomed || _pendingTransaction == null, "pending transaction at disconnect?"); - if (!connectionIsDoomed && null != _physicalStateObj) + if (!connectionIsDoomed && _physicalStateObj != null) { if (_physicalStateObj.HasPendingData) { @@ -1173,10 +1221,10 @@ internal void Deactivate(bool connectionIsDoomed) // transaction manager completes the transaction. SqlInternalTransaction currentTransaction = CurrentTransaction; - if (null != currentTransaction && currentTransaction.HasParentTransaction) + if (currentTransaction != null && currentTransaction.HasParentTransaction) { currentTransaction.CloseFromConnection(); - Debug.Assert(null == CurrentTransaction, "rollback didn't clear current transaction?"); + Debug.Assert(CurrentTransaction == null, "rollback didn't clear current transaction?"); } Statistics = null; // must come after CleanWire or we won't count the stuff that happens there... @@ -1185,7 +1233,7 @@ internal void Deactivate(bool connectionIsDoomed) // Used to close the connection and then free the memory allocated for the netlib connection. internal void Disconnect() { - if (null != _sessionPool) + if (_sessionPool != null) { // MARSOn may be true, but _sessionPool not yet created _sessionPool.Dispose(); @@ -1217,7 +1265,7 @@ internal void Disconnect() } // Not allocated until MARS is actually enabled in SNI. - if (null != _pMarsPhysicalConObj) + if (_pMarsPhysicalConObj != null) { _pMarsPhysicalConObj.Dispose(); } @@ -1236,7 +1284,7 @@ internal void Disconnect() } // Fires a single InfoMessageEvent - private void FireInfoMessageEvent(SqlConnection connection, TdsParserStateObject stateObj, SqlError error) + private void FireInfoMessageEvent(SqlConnection connection, SqlCommand command, TdsParserStateObject stateObj, SqlError error) { string serverVersion = null; @@ -1251,7 +1299,7 @@ private void FireInfoMessageEvent(SqlConnection connection, TdsParserStateObject sqlErs.Add(error); - SqlException exc = SqlException.CreateException(sqlErs, serverVersion, _connHandler); + SqlException exc = SqlException.CreateException(sqlErs, serverVersion, _connHandler, innerException: null, batchCommand: command?.GetCurrentBatchCommand()); bool notified; connection.OnInfoMessage(new SqlInfoMessageEventArgs(exc), out notified); @@ -1278,14 +1326,14 @@ internal void RollbackOrphanedAPITransactions() // Any active, non-distributed transaction must be rolled back. SqlInternalTransaction currentTransaction = CurrentTransaction; - if (null != currentTransaction && currentTransaction.HasParentTransaction && currentTransaction.IsOrphaned) + if (currentTransaction != null && currentTransaction.HasParentTransaction && currentTransaction.IsOrphaned) { currentTransaction.CloseFromConnection(); - Debug.Assert(null == CurrentTransaction, "rollback didn't clear current transaction?"); + Debug.Assert(CurrentTransaction == null, "rollback didn't clear current transaction?"); } } - internal void ThrowExceptionAndWarning(TdsParserStateObject stateObj, bool callerHasConnectionLock = false, bool asyncClose = false) + internal void ThrowExceptionAndWarning(TdsParserStateObject stateObj, SqlCommand command = null, bool callerHasConnectionLock = false, bool asyncClose = false) { Debug.Assert(!callerHasConnectionLock || _connHandler._parserLock.ThreadMayHaveLock(), "Caller claims to have lock, but connection lock is not taken"); @@ -1336,11 +1384,16 @@ internal void ThrowExceptionAndWarning(TdsParserStateObject stateObj, bool calle if (temp.Count == 1 && temp[0].Exception != null) { - exception = SqlException.CreateException(temp, serverVersion, _connHandler, temp[0].Exception); + exception = SqlException.CreateException(temp, serverVersion, _connHandler, temp[0].Exception, command?.GetBatchCommand(temp[0].BatchIndex)); } else { - exception = SqlException.CreateException(temp, serverVersion, _connHandler); + SqlBatchCommand batchCommand = null; + if (temp[0]?.BatchIndex is var index and >= 0 && command is not null) + { + batchCommand = command.GetBatchCommand(index.Value); + } + exception = SqlException.CreateException(temp, serverVersion, _connHandler, innerException: null, batchCommand: batchCommand); } } @@ -1408,7 +1461,7 @@ internal void ThrowExceptionAndWarning(TdsParserStateObject stateObj, bool calle internal SqlError ProcessSNIError(TdsParserStateObject stateObj) { - using (TryEventScope.Create("")) + using (TryEventScope.Create(nameof(TdsParser))) { #if DEBUG // There is an exception here for MARS as its possible that another thread has closed the connection just as we see an error @@ -1469,9 +1522,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) SqlClientEventSource.Log.TryAdvancedTraceEvent(" Empty error message received from SNI. Error Message = {0}", details.errorMessage); } - string sniContextEnumName = TdsEnums.GetSniContextEnumName(stateObj.SniContext); - - string sqlContextInfo = StringsHelper.GetResourceString(sniContextEnumName); + string sqlContextInfo = StringsHelper.GetResourceString(stateObj.SniContext.ToString()); string providerRid = string.Format("SNI_PN{0}", details.provider); string providerName = StringsHelper.GetResourceString(providerRid); Debug.Assert(!string.IsNullOrEmpty(providerName), $"invalid providerResourceId '{providerRid}'"); @@ -1642,7 +1693,7 @@ internal void CheckResetConnection(TdsParserStateObject stateObj) // internal byte[] SerializeShort(int v, TdsParserStateObject stateObj) { - if (null == stateObj._bShortBytes) + if (stateObj._bShortBytes == null) { stateObj._bShortBytes = new byte[2]; } @@ -1701,7 +1752,7 @@ internal void WriteUnsignedInt(uint i, TdsParserStateObject stateObj) // internal byte[] SerializeInt(int v, TdsParserStateObject stateObj) { - if (null == stateObj._bIntBytes) + if (stateObj._bIntBytes == null) { stateObj._bIntBytes = new byte[sizeof(int)]; } @@ -1736,8 +1787,8 @@ internal void WriteInt(int v, TdsParserStateObject stateObj) internal static void WriteInt(Span buffer, int value) { -#if NETCOREAPP - BitConverter.TryWriteBytes(buffer, value); +#if NET6_0_OR_GREATER + BinaryPrimitives.TryWriteInt32LittleEndian(buffer, value); #else buffer[0] = (byte)(value & 0xff); buffer[1] = (byte)((value >> 8) & 0xff); @@ -1756,7 +1807,9 @@ internal byte[] SerializeFloat(float v) throw ADP.ParameterValueOutOfRange(v.ToString()); } - return BitConverter.GetBytes(v); + var bytes = new byte[4]; + BinaryPrimitives.WriteInt32LittleEndian(bytes, BitConverterCompatible.SingleToInt32Bits(v)); + return bytes; } internal void WriteFloat(float v, TdsParserStateObject stateObj) @@ -1772,7 +1825,7 @@ internal void WriteFloat(float v, TdsParserStateObject stateObj) internal byte[] SerializeLong(long v, TdsParserStateObject stateObj) { int current = 0; - if (null == stateObj._bLongBytes) + if (stateObj._bLongBytes == null) { stateObj._bLongBytes = new byte[8]; } @@ -1879,7 +1932,9 @@ internal byte[] SerializeDouble(double v) throw ADP.ParameterValueOutOfRange(v.ToString()); } - return BitConverter.GetBytes(v); + var bytes = new byte[8]; + BinaryPrimitives.WriteInt64LittleEndian(bytes, BitConverter.DoubleToInt64Bits(v)); + return bytes; } internal void WriteDouble(double v, TdsParserStateObject stateObj) @@ -1906,8 +1961,8 @@ internal bool Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader stateObj._syncOverAsync = true; bool dataReady; - bool result = TryRun(runBehavior, cmdHandler, dataStream, bulkCopyHandler, stateObj, out dataReady); - Debug.Assert(result == true, "Should never return false when _syncOverAsync is set"); + TdsOperationStatus result = TryRun(runBehavior, cmdHandler, dataStream, bulkCopyHandler, stateObj, out dataReady); + Debug.Assert(result == TdsOperationStatus.Done, "Should always return Done when _syncOverAsync is set"); return dataReady; } finally @@ -1956,7 +2011,7 @@ internal static bool IsValidTdsToken(byte token) } // Main parse loop for the top-level tds tokens, calls back into the I*Handler interfaces - internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, out bool dataReady) + internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, out bool dataReady) { Debug.Assert((SniContext.Undefined != stateObj.SniContext) && // SniContext must not be Undefined ((stateObj._attentionSent) || ((SniContext.Snix_Execute != stateObj.SniContext) && (SniContext.Snix_SendRows != stateObj.SniContext))), // SniContext should not be Execute or SendRows unless attention was sent (and, therefore, we are looking for an ACK) @@ -1965,9 +2020,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if (TdsParserState.Broken == State || TdsParserState.Closed == State) { dataReady = true; - return true; // Just in case this is called in a loop, expecting data to be returned. + return TdsOperationStatus.Done; // Just in case this is called in a loop, expecting data to be returned. } + TdsOperationStatus result; dataReady = false; do @@ -1996,19 +2052,24 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if ((connection != null) && connection.FireInfoMessageEventOnUserErrors) { foreach (SqlError error in stateObj._pendingInfoEvents) - FireInfoMessageEvent(connection, stateObj, error); + { + FireInfoMessageEvent(connection, cmdHandler, stateObj, error); + } } else foreach (SqlError error in stateObj._pendingInfoEvents) + { stateObj.AddWarning(error); + } } stateObj._pendingInfoEvents = null; } byte token; - if (!stateObj.TryReadByte(out token)) + result = stateObj.TryReadByte(out token); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (!IsValidTdsToken(token)) @@ -2021,9 +2082,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } int tokenLength; - if (!TryGetTokenLength(token, stateObj, out tokenLength)) + result = TryGetTokenLength(token, stateObj, out tokenLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } switch (token) @@ -2037,9 +2099,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } SqlError error; - if (!TryProcessError(token, stateObj, out error)) + result = TryProcessError(token, stateObj, cmdHandler, out error); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (token == TdsEnums.SQLINFO && stateObj._accumulateInfoEvents) @@ -2066,7 +2129,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead (error.Class <= TdsEnums.MAX_USER_CORRECTABLE_ERROR_CLASS)) { // Fire SqlInfoMessage here - FireInfoMessageEvent(connection, stateObj, error); + FireInfoMessageEvent(connection, cmdHandler, stateObj, error); } else { @@ -2088,7 +2151,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead // a reader we need to throw the error but not halt further processing. We used to // halt processing. - if (null != dataStream) + if (dataStream != null) { if (!dataStream.IsInitialized) { @@ -2116,24 +2179,27 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead case TdsEnums.SQLCOLINFO: { - if (null != dataStream) + if (dataStream != null) { _SqlMetaDataSet metaDataSet; - if (!TryProcessColInfo(dataStream.MetaData, dataStream, stateObj, out metaDataSet)) + result = TryProcessColInfo(dataStream.MetaData, dataStream, stateObj, out metaDataSet); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!dataStream.TrySetMetaData(metaDataSet, false)) + result = dataStream.TrySetMetaData(metaDataSet, false); + if (result != TdsOperationStatus.Done) { - return false; + return result; } dataStream.BrowseModeInfoConsumed = true; } else { // no dataStream - if (!stateObj.TrySkipBytes(tokenLength)) + result = stateObj.TrySkipBytes(tokenLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } break; @@ -2144,9 +2210,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead case TdsEnums.SQLDONEINPROC: { // RunBehavior can be modified - if (!TryProcessDone(cmdHandler, dataStream, ref runBehavior, stateObj)) + result = TryProcessDone(cmdHandler, dataStream, ref runBehavior, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if ((token == TdsEnums.SQLDONEPROC) && (cmdHandler != null)) { @@ -2159,7 +2226,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } else { - cmdHandler.OnDoneProc(); + cmdHandler.OnDoneProc(stateObj); } } @@ -2169,72 +2236,11 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead case TdsEnums.SQLORDER: { // don't do anything with the order token so read off the pipe - if (!stateObj.TrySkipBytes(tokenLength)) - { - return false; - } - break; - } - - case TdsEnums.SQLALTMETADATA: - { - stateObj.CloneCleanupAltMetaDataSetArray(); - - if (stateObj._cleanupAltMetaDataSetArray == null) - { - // create object on demand (lazy creation) - stateObj._cleanupAltMetaDataSetArray = new _SqlMetaDataSetCollection(); - } - - _SqlMetaDataSet cleanupAltMetaDataSet; - if (!TryProcessAltMetaData(tokenLength, stateObj, out cleanupAltMetaDataSet)) - { - return false; - } - - stateObj._cleanupAltMetaDataSetArray.SetAltMetaData(cleanupAltMetaDataSet); - if (null != dataStream) - { - byte metadataConsumedByte; - if (!stateObj.TryPeekByte(out metadataConsumedByte)) - { - return false; - } - if (!dataStream.TrySetAltMetaDataSet(cleanupAltMetaDataSet, (TdsEnums.SQLALTMETADATA != metadataConsumedByte))) - { - return false; - } - } - - break; - } - - case TdsEnums.SQLALTROW: - { - if (!stateObj.TryStartNewRow(isNullCompressed: false)) - { // altrows are not currently null compressed - return false; - } - - // read will call run until dataReady. Must not read any data if ReturnImmediately set - if (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior)) + result = stateObj.TrySkipBytes(tokenLength); + if (result != TdsOperationStatus.Done) { - ushort altRowId; - if (!stateObj.TryReadUInt16(out altRowId)) - { // get altRowId - return false; - } - - if (!TrySkipRow(stateObj._cleanupAltMetaDataSetArray.GetAltMetaData(altRowId), stateObj)) - { // skip altRow - return false; - } - } - else - { - dataReady = true; + return result; } - break; } @@ -2244,9 +2250,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead stateObj._syncOverAsync = true; SqlEnvChange env; - if (!TryProcessEnvChange(tokenLength, stateObj, out env)) + result = TryProcessEnvChange(tokenLength, stateObj, out env); + if (result != TdsOperationStatus.Done) { - return false; + return result; } while (env != null) @@ -2262,11 +2269,11 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead // the current transaction, then we store the token in it. // if there isn't a pending transaction, then it's either // a TSQL transaction or a distributed transaction. - Debug.Assert(null == _currentTransaction, "non-null current transaction with an ENV Change"); + Debug.Assert(_currentTransaction == null, "non-null current transaction with an ENV Change"); _currentTransaction = _pendingTransaction; _pendingTransaction = null; - if (null != _currentTransaction) + if (_currentTransaction != null) { _currentTransaction.TransactionId = env._newLongValue; // this is defined as a ULongLong in the server and in the TDS Spec. } @@ -2275,7 +2282,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead TransactionType transactionType = (TdsEnums.ENV_BEGINTRAN == env._type) ? TransactionType.LocalFromTSQL : TransactionType.Distributed; _currentTransaction = new SqlInternalTransaction(_connHandler, transactionType, null, env._newLongValue); } - if (null != _statistics && !_statisticsIsInTransaction) + if (_statistics != null && !_statisticsIsInTransaction) { _statistics.SafeIncrement(ref _statistics._transactions); } @@ -2292,7 +2299,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead case TdsEnums.ENV_ROLLBACKTRAN: // When we get notification of a completed transaction // we null out the current transaction. - if (null != _currentTransaction) + if (_currentTransaction != null) { #if DEBUG // Check null for case where Begin and Rollback obtained in the same message. @@ -2342,9 +2349,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead { SqlClientEventSource.Log.TryTraceEvent(" Received login acknowledgement token"); SqlLoginAck ack; - if (!TryProcessLoginAck(stateObj, out ack)) + result = TryProcessLoginAck(stateObj, out ack); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _connHandler.OnLoginAck(ack); @@ -2352,9 +2360,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } case TdsEnums.SQLFEATUREEXTACK: { - if (!TryProcessFeatureExtAck(stateObj)) + result = TryProcessFeatureExtAck(stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; } @@ -2363,18 +2372,20 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead _connHandler._federatedAuthenticationInfoReceived = true; SqlFedAuthInfo info; - if (!TryProcessFedAuthInfo(stateObj, tokenLength, out info)) + result = TryProcessFedAuthInfo(stateObj, tokenLength, out info); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _connHandler.OnFedAuthInfo(info); break; } case TdsEnums.SQLSESSIONSTATE: { - if (!TryProcessSessionState(stateObj, tokenLength, _connHandler._currentSessionData)) + result = TryProcessSessionState(stateObj, tokenLength, _connHandler._currentSessionData); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; } @@ -2383,9 +2394,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if (tokenLength != TdsEnums.VARNULL) { _SqlMetaDataSet metadata; - if (!TryProcessMetaData(tokenLength, stateObj, out metadata, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting)) + result = TryProcessMetaData(tokenLength, stateObj, out metadata, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); + if (result != TdsOperationStatus.Done) { - return false; + return result; } stateObj._cleanupMetaData = metadata; } @@ -2398,45 +2410,54 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } byte peekedToken; - if (!stateObj.TryPeekByte(out peekedToken)) - { // temporarily cache next byte - return false; + result = stateObj.TryPeekByte(out peekedToken); + if (result != TdsOperationStatus.Done) + { + return result; } if (TdsEnums.SQLDATACLASSIFICATION == peekedToken) { byte dataClassificationToken; - if (!stateObj.TryReadByte(out dataClassificationToken)) + result = stateObj.TryReadByte(out dataClassificationToken); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(TdsEnums.SQLDATACLASSIFICATION == dataClassificationToken); SensitivityClassification sensitivityClassification; - if (!TryProcessDataClassification(stateObj, out sensitivityClassification)) + result = TryProcessDataClassification(stateObj, out sensitivityClassification); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (null != dataStream && !dataStream.TrySetSensitivityClassification(sensitivityClassification)) + if (dataStream != null) { - return false; + result = dataStream.TrySetSensitivityClassification(sensitivityClassification); + if (result != TdsOperationStatus.Done) + { + return result; + } } // update peekedToken - if (!stateObj.TryPeekByte(out peekedToken)) + result = stateObj.TryPeekByte(out peekedToken); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } - if (null != dataStream) + if (dataStream != null) { - if (!dataStream.TrySetMetaData(stateObj._cleanupMetaData, (TdsEnums.SQLTABNAME == peekedToken || TdsEnums.SQLCOLINFO == peekedToken))) + result = dataStream.TrySetMetaData(stateObj._cleanupMetaData, (TdsEnums.SQLTABNAME == peekedToken || TdsEnums.SQLCOLINFO == peekedToken)); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } - else if (null != bulkCopyHandler) + else if (bulkCopyHandler != null) { bulkCopyHandler.SetMetaData(stateObj._cleanupMetaData); } @@ -2449,31 +2470,35 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if (token == TdsEnums.SQLNBCROW) { - if (!stateObj.TryStartNewRow(isNullCompressed: true, nullBitmapColumnsCount: stateObj._cleanupMetaData.Length)) + result = stateObj.TryStartNewRow(isNullCompressed: true, nullBitmapColumnsCount: stateObj._cleanupMetaData.Length); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } else { - if (!stateObj.TryStartNewRow(isNullCompressed: false)) + result = stateObj.TryStartNewRow(isNullCompressed: false); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } - if (null != bulkCopyHandler) + if (bulkCopyHandler != null) { - if (!TryProcessRow(stateObj._cleanupMetaData, bulkCopyHandler.CreateRowBuffer(), bulkCopyHandler.CreateIndexMap(), stateObj)) + result = TryProcessRow(stateObj._cleanupMetaData, bulkCopyHandler.CreateRowBuffer(), bulkCopyHandler.CreateIndexMap(), stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } else if (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior)) { - if (!TrySkipRow(stateObj._cleanupMetaData, stateObj)) - { // skip rows - return false; + result = TrySkipRow(stateObj._cleanupMetaData, stateObj); + if (result != TdsOperationStatus.Done) + { + return result; } } else @@ -2489,9 +2514,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } case TdsEnums.SQLRETURNSTATUS: int status; - if (!stateObj.TryReadInt32(out status)) + result = stateObj.TryReadInt32(out status); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (cmdHandler != null) { @@ -2501,9 +2527,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead case TdsEnums.SQLRETURNVALUE: { SqlReturnValue returnValue; - if (!TryProcessReturnValue(tokenLength, stateObj, out returnValue, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting)) + result = TryProcessReturnValue(tokenLength, stateObj, out returnValue, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (cmdHandler != null) { @@ -2523,32 +2550,104 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead } case TdsEnums.SQLTABNAME: { - if (null != dataStream) + if (dataStream != null) { MultiPartTableName[] tableNames; - if (!TryProcessTableName(tokenLength, stateObj, out tableNames)) + result = TryProcessTableName(tokenLength, stateObj, out tableNames); + if (result != TdsOperationStatus.Done) { - return false; + return result; } dataStream.TableNames = tableNames; } else { - if (!stateObj.TrySkipBytes(tokenLength)) + result = stateObj.TrySkipBytes(tokenLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } break; } case TdsEnums.SQLRESCOLSRCS: { - if (!TryProcessResColSrcs(stateObj, tokenLength)) + result = TryProcessResColSrcs(stateObj, tokenLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; } + + // deprecated + case TdsEnums.SQLALTMETADATA: + { + stateObj.CloneCleanupAltMetaDataSetArray(); + + if (stateObj._cleanupAltMetaDataSetArray == null) + { + // create object on demand (lazy creation) + stateObj._cleanupAltMetaDataSetArray = new _SqlMetaDataSetCollection(); + } + + _SqlMetaDataSet cleanupAltMetaDataSet; + result = TryProcessAltMetaData(tokenLength, stateObj, out cleanupAltMetaDataSet); + if (result != TdsOperationStatus.Done) + { + return result; + } + + stateObj._cleanupAltMetaDataSetArray.SetAltMetaData(cleanupAltMetaDataSet); + if (dataStream != null) + { + byte metadataConsumedByte; + result = stateObj.TryPeekByte(out metadataConsumedByte); + if (result != TdsOperationStatus.Done) + { + return result; + } + result = dataStream.TrySetAltMetaDataSet(cleanupAltMetaDataSet, (TdsEnums.SQLALTMETADATA != metadataConsumedByte)); + if (result != TdsOperationStatus.Done) + { + return result; + } + } + + break; + } + case TdsEnums.SQLALTROW: + { + result = stateObj.TryStartNewRow(isNullCompressed: false); + if (result != TdsOperationStatus.Done) + { + return result; + } + + // read will call run until dataReady. Must not read any data if ReturnImmediately set + if (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior)) + { + ushort altRowId; + result = stateObj.TryReadUInt16(out altRowId); + if (result != TdsOperationStatus.Done) + { + return result; + } + + result = TrySkipRow(stateObj._cleanupAltMetaDataSetArray.GetAltMetaData(altRowId), stateObj); + if (result != TdsOperationStatus.Done) + { + return result; + } + } + else + { + dataReady = true; + } + + break; + } + default: Debug.Fail("Unhandled token: " + token.ToString(CultureInfo.InvariantCulture)); break; @@ -2568,9 +2667,10 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if ((stateObj.HasPendingData) && (!dataReady)) { byte token; - if (!stateObj.TryPeekByte(out token)) + result = stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(IsValidTdsToken(token), $"DataReady is false, but next token is not valid: {token,-2:X2}"); } @@ -2578,7 +2678,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if (!stateObj.HasPendingData) { - if (null != CurrentTransaction) + if (CurrentTransaction != null) { CurrentTransaction.Activate(); } @@ -2602,37 +2702,39 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead if (RunBehavior.Clean != (RunBehavior.Clean & runBehavior) && !stateObj.IsTimeoutStateExpired) { // Add attention error to collection - if not RunBehavior.Clean! - stateObj.AddError(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, _server, SQLMessage.OperationCancelled(), "", 0)); + stateObj.AddError(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, _server, SQLMessage.OperationCancelled(), "", 0, exception: null, batchIndex: cmdHandler?.GetCurrentBatchIndex() ?? -1)); } } } if (stateObj.HasErrorOrWarning) { - ThrowExceptionAndWarning(stateObj); + ThrowExceptionAndWarning(stateObj, cmdHandler); } - return true; + return TdsOperationStatus.Done; } // This is in its own method to avoid always allocating the lambda in TryRun private static void TryRunSetupSpinWaitContinuation(TdsParserStateObject stateObj) => SpinWait.SpinUntil(() => !stateObj._attentionSending); - private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, out SqlEnvChange sqlEnvChange) + private TdsOperationStatus TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, out SqlEnvChange sqlEnvChange) { // There could be multiple environment change messages following this token. byte byteLength; int processedLength = 0; SqlEnvChange head = null; SqlEnvChange tail = null; + TdsOperationStatus result; sqlEnvChange = null; while (tokenLength > processedLength) { SqlEnvChange env = new SqlEnvChange(); - if (!stateObj.TryReadByte(out env._type)) + result = stateObj.TryReadByte(out env._type); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (head is null) @@ -2650,18 +2752,20 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, { case TdsEnums.ENV_DATABASE: case TdsEnums.ENV_LANG: - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; case TdsEnums.ENV_CHARSET: // we copied this behavior directly from luxor - see charset envchange // section from sqlctokn.c - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (env._newValue == TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_STRING) { @@ -2683,7 +2787,7 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, case TdsEnums.ENV_PACKETSIZE: // take care of packet size right here Debug.Assert(stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - if (!TryReadTwoStringFields(env, stateObj)) + if (TryReadTwoStringFields(env, stateObj) != TdsOperationStatus.Done) { // Changing packet size does not support retry, should not pend" throw SQL.SynchronousCallMayNotPend(); @@ -2693,6 +2797,9 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, // to MARS initialization! int packetSize = int.Parse(env._newValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + SqlClientEventSource.Log.TryTraceEvent("{0}.{1} | Info | Server sent env packet size change of {2}, ClientConnectionID {3}", + nameof(TdsParser), nameof(TryProcessEnvChange), packetSize, _connHandler._clientConnectionId); + if (_physicalStateObj.SetPacketSize(packetSize)) { // If packet size changed, we need to release our SNIPackets since @@ -2701,39 +2808,43 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, // Update SNI ConsumerInfo value to be resulting packet size uint unsignedPacketSize = (uint)packetSize; - uint result = _physicalStateObj.SetConnectionBufferSize(ref unsignedPacketSize); - Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SNISetInfo"); + uint bufferSizeResult = _physicalStateObj.SetConnectionBufferSize(ref unsignedPacketSize); + Debug.Assert(bufferSizeResult == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SNISetInfo"); } break; case TdsEnums.ENV_LOCALEID: - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } _defaultLCID = int.Parse(env._newValue, NumberStyles.Integer, CultureInfo.InvariantCulture); break; case TdsEnums.ENV_COMPFLAGS: - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; case TdsEnums.ENV_COLLATION: Debug.Assert(env._newLength == 5 || env._newLength == 0, "Improper length in new collation!"); - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newLength = byteLength; if (env._newLength == 5) { - if (!TryProcessCollation(stateObj, out env._newCollation)) + result = TryProcessCollation(stateObj, out env._newCollation); + if (result != TdsOperationStatus.Done) { - return false; + return result; } // Give the parser the new collation values in case parameters don't specify one @@ -2756,17 +2867,19 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, _defaultLCID = env._newCollation.LCID; } - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._oldLength = byteLength; Debug.Assert(env._oldLength == 5 || env._oldLength == 0, "Improper length in old collation!"); if (env._oldLength == 5) { - if (!TryProcessCollation(stateObj, out env._oldCollation)) + result = TryProcessCollation(stateObj, out env._oldCollation); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } @@ -2779,18 +2892,20 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, case TdsEnums.ENV_ENLISTDTC: case TdsEnums.ENV_DEFECTDTC: case TdsEnums.ENV_TRANSACTIONENDED: - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newLength = byteLength; Debug.Assert(env._newLength == 0 || env._newLength == 8, "Improper length for new transaction id!"); if (env._newLength > 0) { - if (!stateObj.TryReadInt64(out env._newLongValue)) + result = stateObj.TryReadInt64(out env._newLongValue); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(env._newLongValue != SqlInternalTransaction.NullTransactionId, "New transaction id is null?"); // the server guarantees that zero is an invalid transaction id. } @@ -2799,18 +2914,20 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, env._newLongValue = SqlInternalTransaction.NullTransactionId; // the server guarantees that zero is an invalid transaction id. } - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._oldLength = byteLength; Debug.Assert(env._oldLength == 0 || env._oldLength == 8, "Improper length for old transaction id!"); if (env._oldLength > 0) { - if (!stateObj.TryReadInt64(out env._oldLongValue)) + result = stateObj.TryReadInt64(out env._oldLongValue); + if (result != TdsOperationStatus.Done) { - return false; + return result; } Debug.Assert(env._oldLongValue != SqlInternalTransaction.NullTransactionId, "Old transaction id is null?"); // the server guarantees that zero is an invalid transaction id. } @@ -2826,26 +2943,31 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, case TdsEnums.ENV_LOGSHIPNODE: // env.newBinValue is secondary node, env.oldBinValue is witness node // comes before LoginAck so we can't assert this - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; case TdsEnums.ENV_PROMOTETRANSACTION: - if (!stateObj.TryReadInt32(out env._newLength)) - { // new value has 4 byte length - return false; + result = stateObj.TryReadInt32(out env._newLength); + if (result != TdsOperationStatus.Done) + { + return result; } + // read new value with 4 byte length env._newBinValue = new byte[env._newLength]; - if (!stateObj.TryReadByteArray(env._newBinValue, env._newLength)) - { // read new value with 4 byte length - return false; + result = stateObj.TryReadByteArray(env._newBinValue, env._newLength); + if (result != TdsOperationStatus.Done) + { + return result; } - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._oldLength = byteLength; Debug.Assert(0 == env._oldLength, "old length should be zero"); @@ -2856,55 +2978,64 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, case TdsEnums.ENV_TRANSACTIONMANAGERADDRESS: case TdsEnums.ENV_SPRESETCONNECTIONACK: - if (!TryReadTwoBinaryFields(env, stateObj)) + result = TryReadTwoBinaryFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; case TdsEnums.ENV_USERINSTANCE: - if (!TryReadTwoStringFields(env, stateObj)) + result = TryReadTwoStringFields(env, stateObj); + if (result != TdsOperationStatus.Done) { - return false; + return result; } break; case TdsEnums.ENV_ROUTING: ushort newLength; - if (!stateObj.TryReadUInt16(out newLength)) + result = stateObj.TryReadUInt16(out newLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newLength = newLength; byte protocol; - if (!stateObj.TryReadByte(out protocol)) + result = stateObj.TryReadByte(out protocol); + if (result != TdsOperationStatus.Done) { - return false; + return result; } ushort port; - if (!stateObj.TryReadUInt16(out port)) + result = stateObj.TryReadUInt16(out port); + if (result != TdsOperationStatus.Done) { - return false; + return result; } ushort serverLen; - if (!stateObj.TryReadUInt16(out serverLen)) + result = stateObj.TryReadUInt16(out serverLen); + if (result != TdsOperationStatus.Done) { - return false; + return result; } string serverName; - if (!stateObj.TryReadString(serverLen, out serverName)) + result = stateObj.TryReadString(serverLen, out serverName); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newRoutingInfo = new RoutingInfo(protocol, port, serverName); ushort oldLength; - if (!stateObj.TryReadUInt16(out oldLength)) + result = stateObj.TryReadUInt16(out oldLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TrySkipBytes(oldLength)) + result = stateObj.TrySkipBytes(oldLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._length = env._newLength + oldLength + 5; // 5=2*sizeof(UInt16)+sizeof(byte) [token+newLength+oldLength] break; @@ -2917,61 +3048,69 @@ private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, } sqlEnvChange = head; - return true; + return TdsOperationStatus.Done; } - private bool TryReadTwoBinaryFields(SqlEnvChange env, TdsParserStateObject stateObj) + private TdsOperationStatus TryReadTwoBinaryFields(SqlEnvChange env, TdsParserStateObject stateObj) { // Used by ProcessEnvChangeToken byte byteLength; - if (!stateObj.TryReadByte(out byteLength)) + TdsOperationStatus result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newLength = byteLength; env._newBinValue = ArrayPool.Shared.Rent(env._newLength); env._newBinRented = true; - if (!stateObj.TryReadByteArray(env._newBinValue, env._newLength)) + result = stateObj.TryReadByteArray(env._newBinValue, env._newLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadByte(out byteLength)) + result = stateObj.TryReadByte(out byteLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._oldLength = byteLength; env._oldBinValue = ArrayPool.Shared.Rent(env._oldLength); env._oldBinRented = true; - if (!stateObj.TryReadByteArray(env._oldBinValue, env._oldLength)) + result = stateObj.TryReadByteArray(env._oldBinValue, env._oldLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } // env.length includes 1 byte type token env._length = 3 + env._newLength + env._oldLength; - return true; + return TdsOperationStatus.Done; } - private bool TryReadTwoStringFields(SqlEnvChange env, TdsParserStateObject stateObj) + private TdsOperationStatus TryReadTwoStringFields(SqlEnvChange env, TdsParserStateObject stateObj) { // Used by ProcessEnvChangeToken byte newLength, oldLength; string newValue, oldValue; - if (!stateObj.TryReadByte(out newLength)) + TdsOperationStatus result = stateObj.TryReadByte(out newLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadString(newLength, out newValue)) + result = stateObj.TryReadString(newLength, out newValue); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadByte(out oldLength)) + result = stateObj.TryReadByte(out oldLength); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadString(oldLength, out oldValue)) + result = stateObj.TryReadString(oldLength, out oldValue); + if (result != TdsOperationStatus.Done) { - return false; + return result; } env._newLength = newLength; @@ -2981,10 +3120,10 @@ private bool TryReadTwoStringFields(SqlEnvChange env, TdsParserStateObject state // env.length includes 1 byte type token env._length = 3 + env._newLength * 2 + env._oldLength * 2; - return true; + return TdsOperationStatus.Done; } - private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavior run, TdsParserStateObject stateObj) + private TdsOperationStatus TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavior run, TdsParserStateObject stateObj) { ushort curCmd; ushort status; @@ -3000,19 +3139,22 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio // command // rowcount (valid only if DONE_COUNT bit is set) - if (!stateObj.TryReadUInt16(out status)) + TdsOperationStatus result = stateObj.TryReadUInt16(out status); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadUInt16(out curCmd)) + result = stateObj.TryReadUInt16(out curCmd); + if (result != TdsOperationStatus.Done) { - return false; + return result; } long longCount; - if (!stateObj.TryReadInt64(out longCount)) + result = stateObj.TryReadInt64(out longCount); + if (result != TdsOperationStatus.Done) { - return false; + return result; } count = (int)longCount; @@ -3024,7 +3166,7 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio stateObj.HasReceivedAttention = true; Debug.Assert(stateObj._inBytesUsed == stateObj._inBytesRead && stateObj._inBytesPacket == 0, "DONE_ATTN received with more data left on wire"); } - if ((null != cmd) && (TdsEnums.DONE_COUNT == (status & TdsEnums.DONE_COUNT))) + if (cmd != null && (TdsEnums.DONE_COUNT == (status & TdsEnums.DONE_COUNT))) { if (curCmd != TdsEnums.SELECT) { @@ -3056,9 +3198,9 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio if ((TdsEnums.DONE_ERROR == (TdsEnums.DONE_ERROR & status)) && stateObj.ErrorCount == 0 && stateObj.HasReceivedError == false && (RunBehavior.Clean != (RunBehavior.Clean & run))) { - stateObj.AddError(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, _server, SQLMessage.SevereError(), "", 0)); + stateObj.AddError(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, _server, SQLMessage.SevereError(), "", 0, exception: null, batchIndex: cmd?.GetCurrentBatchIndex() ?? -1)); - if (null != reader) + if (reader != null) { if (!reader.IsInitialized) { @@ -3072,9 +3214,9 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio // The server will always break the connection in this case. if ((TdsEnums.DONE_SRVERROR == (TdsEnums.DONE_SRVERROR & status)) && (RunBehavior.Clean != (RunBehavior.Clean & run))) { - stateObj.AddError(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.SevereError(), "", 0)); + stateObj.AddError(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.SevereError(), "", 0, exception: null, batchIndex: cmd?.GetCurrentBatchIndex() ?? -1)); - if (null != reader) + if (reader != null) { if (!reader.IsInitialized) { @@ -3110,14 +3252,14 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio stateObj.DecrementOpenResultCount(); } - return true; + return TdsOperationStatus.Done; } private void ProcessSqlStatistics(ushort curCmd, ushort status, int count) { // SqlStatistics bookkeeping stuff // - if (null != _statistics) + if (_statistics != null) { // any done after row(s) counts as a resultset if (_statistics.WaitForDoneAfterRow) @@ -3189,29 +3331,32 @@ private void ProcessSqlStatistics(ushort curCmd, ushort status, int count) } } - private bool TryProcessFeatureExtAck(TdsParserStateObject stateObj) + private TdsOperationStatus TryProcessFeatureExtAck(TdsParserStateObject stateObj) { // read feature ID byte featureId; do { - if (!stateObj.TryReadByte(out featureId)) + TdsOperationStatus result = stateObj.TryReadByte(out featureId); + if (result != TdsOperationStatus.Done) { - return false; + return result; } if (featureId != TdsEnums.FEATUREEXT_TERMINATOR) { uint dataLen; - if (!stateObj.TryReadUInt32(out dataLen)) + result = stateObj.TryReadUInt32(out dataLen); + if (result != TdsOperationStatus.Done) { - return false; + return result; } byte[] data = new byte[dataLen]; if (dataLen > 0) { - if (!stateObj.TryReadByteArray(data, checked((int)dataLen))) + result = stateObj.TryReadByteArray(data, checked((int)dataLen)); + if (result != TdsOperationStatus.Done) { - return false; + return result; } } _connHandler.OnFeatureExtAck(featureId, data); @@ -3280,7 +3425,7 @@ private bool TryProcessFeatureExtAck(TdsParserStateObject stateObj) } } - return true; + return TdsOperationStatus.Done; } private bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType) @@ -3324,61 +3469,67 @@ private bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol attesta return true; } - private bool TryReadByteString(TdsParserStateObject stateObj, out string value) + private TdsOperationStatus TryReadByteString(TdsParserStateObject stateObj, out string value) { value = string.Empty; byte byteLen; - if (!stateObj.TryReadByte(out byteLen)) + TdsOperationStatus result = stateObj.TryReadByte(out byteLen); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!stateObj.TryReadString(byteLen, out value)) + result = stateObj.TryReadString(byteLen, out value); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - return true; + return TdsOperationStatus.Done; } - private bool TryReadSensitivityLabel(TdsParserStateObject stateObj, out string label, out string id) + private TdsOperationStatus TryReadSensitivityLabel(TdsParserStateObject stateObj, out string label, out string id) { label = string.Empty; id = string.Empty; - if (!TryReadByteString(stateObj, out label)) + TdsOperationStatus result = TryReadByteString(stateObj, out label); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!TryReadByteString(stateObj, out id)) + result = TryReadByteString(stateObj, out id); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - return true; + return TdsOperationStatus.Done; } - private bool TryReadSensitivityInformationType(TdsParserStateObject stateObj, out string informationType, out string id) + private TdsOperationStatus TryReadSensitivityInformationType(TdsParserStateObject stateObj, out string informationType, out string id) { informationType = string.Empty; id = string.Empty; - if (!TryReadByteString(stateObj, out informationType)) + TdsOperationStatus result = TryReadByteString(stateObj, out informationType); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - if (!TryReadByteString(stateObj, out id)) + result = TryReadByteString(stateObj, out id); + if (result != TdsOperationStatus.Done) { - return false; + return result; } - return true; + return TdsOperationStatus.Done; } - private bool TryProcessDataClassification(TdsParserStateObject stateObj, out SensitivityClassification sensitivityClassification) + private TdsOperationStatus TryProcessDataClassification(TdsParserStateObject stateObj, out SensitivityClassification sensitivityClassification) { if (DataClassificationVersion == 0) { @@ -3388,31 +3539,35 @@ private bool TryProcessDataClassification(TdsParserStateObject stateObj, out Sen sensitivityClassification = null; // get the labels - if (!stateObj.TryReadUInt16(out ushort numLabels)) + TdsOperationStatus result = stateObj.TryReadUInt16(out ushort numLabels); + if (result != TdsOperationStatus.Done) { - return false; + return result; } List