You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/relational-databases/clr-integration-database-objects-user-defined-functions/clr-user-defined-aggregate-invoking-functions.md
description: In SQL Server CLR integration, use Transact-SQL SELECT to invoke CLR user-defined aggregates, subject to the rules that apply to system aggregate functions.
4
4
author: rwestMSFT
5
5
ms.author: randolphwest
6
-
ms.date: 12/27/2024
6
+
ms.date: 03/19/2026
7
7
ms.service: sql
8
8
ms.subservice: clr
9
9
ms.topic: "reference"
@@ -26,7 +26,7 @@ The following additional rules apply:
26
26
27
27
- The current user must have `EXECUTE` permission on the user-defined aggregate.
28
28
29
-
- User-defined aggregates must be invoked using a two-part name in the form of <schema_name>.<udagg_name>.
29
+
- User-defined aggregates must be invoked by using a two-part name in the form of <schema_name>.<udagg_name>.
30
30
31
31
- The argument type of the user-defined aggregate must match or be implicitly convertible to the *input_type* of the aggregate, as defined in the `CREATE AGGREGATE` statement.
> Visual C++ database objects, such as scalar-valued functions, that have been compiled with the `/clr:pure` compiler option aren't supported for execution in [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)].
212
212
213
-
As with most aggregates, the bulk of the logic is in the `Accumulate` method. Here, the string that is passed in as a parameter to the `Accumulate` method is appended to the `StringBuilder` object that was initialized in the `Init` method. Assuming that the `Accumulate` method wasn't already called, a comma is also appended to the `StringBuilder` before appending the passed-in string. At the conclusion of the computational tasks, the `Terminate` method is called, which returns the `StringBuilder` as a string.
213
+
As with most aggregates, the bulk of the logic is in the `Accumulate` method. Here, the string that is passed in as a parameter to the `Accumulate` method is appended to the `StringBuilder` object that was initialized in the `Init` method. Assuming that the `Accumulate` method wasn't already called, a comma is also appended to the `StringBuilder` before appending the passed-in string. When computation finishes, the `Terminate` method is called, which returns the `StringBuilder` as a string.
214
214
215
215
For example, consider a table with the following schema:
216
216
@@ -258,7 +258,6 @@ The following sample shows an aggregate that has two parameters on the `Accumula
258
258
```csharp
259
259
usingSystem;
260
260
usingSystem.Data;
261
-
usingSystem.Data.SqlClient;
262
261
usingSystem.Data.SqlTypes;
263
262
usingMicrosoft.SqlServer.Server;
264
263
@@ -339,7 +338,6 @@ public struct WeightedAvg
339
338
```vb
340
339
ImportsSystem
341
340
ImportsSystem.Data
342
-
ImportsSystem.Data.SqlClient
343
341
ImportsSystem.Data.SqlTypes
344
342
ImportsMicrosoft.SqlServer.Server
345
343
ImportsSystem.Runtime.InteropServices
@@ -411,7 +409,7 @@ End Class
411
409
412
410
---
413
411
414
-
After you compile the [!INCLUDE [c-sharp-md](../../includes/c-sharp-md.md)] or [!INCLUDE [visual-basic-md](../../includes/visual-basic-md.md)] .NET source code, run the following [!INCLUDE [tsql](../../includes/tsql-md.md)]. This script assumes that the DLL is called WghtAvg.dll and is in the root directory of your C drive. A database called test is also assumed.
412
+
After you compile the [!INCLUDE [c-sharp-md](../../includes/c-sharp-md.md)] or [!INCLUDE [visual-basic-md](../../includes/visual-basic-md.md)] .NET source code, run the following [!INCLUDE [tsql](../../includes/tsql-md.md)]. This script assumes that the DLL is called WghtAvg.dll and is in the root directory of your C drive. It also assumes a database called test exists.
Copy file name to clipboardExpand all lines: docs/relational-databases/clr-integration-database-objects-user-defined-types/accessing-user-defined-types-in-ado-net.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ title: "Accessing User-Defined Types in ADO.NET"
3
3
description: UDTs, written in .NET Framework CLR languages, allow a SQL Server database to store objects and custom data structures. In ADO.NET, a provider exposes UDTs.
4
4
author: rwestMSFT
5
5
ms.author: randolphwest
6
-
ms.date: 12/27/2024
6
+
ms.date: 03/19/2026
7
7
ms.service: sql
8
8
ms.subservice: clr
9
9
ms.topic: "reference"
@@ -20,11 +20,11 @@ User-defined types (UDTs) are written using any of the languages supported by th
20
20
21
21
The data is exposed as public members of a .NET Framework class or structure, and behaviors are defined by methods of the class or structure. A UDT can be used as the column definition of a table, as a variable in a [!INCLUDE [tsql](../../includes/tsql-md.md)] batch, or as an argument of a [!INCLUDE [tsql](../../includes/tsql-md.md)] function or stored procedure.
22
22
23
-
In ADO.NET, the `System.Data.SqlClient` provider exposes UDTs in the following ways:
23
+
In ADO.NET, the `Microsoft.Data.SqlClient` provider exposes UDTs in the following ways:
24
24
25
-
- Through the `System.Data.SqlClient.SqlDataReader` as an object.
25
+
- Through the `Microsoft.Data.SqlClient.SqlDataReader` as an object.
26
26
- Through the `SqlDataReader` as raw bytes.
27
-
- As a parameter of a `System.Data.SqlClient.SqlParameter` object.
27
+
- As a parameter of a `Microsoft.Data.SqlClient.SqlParameter` object.
Copy file name to clipboardExpand all lines: docs/relational-databases/clr-integration-database-objects-user-defined-types/accessing-user-defined-types-retrieving-udt-data.md
+28-30Lines changed: 28 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ title: "Retrieving UDT Data"
3
3
description: This article describes how to access UDTs in a SQL Server database.
In order to create a user-defined type (UDT) on the client, the assembly that was registered as a UDT in a [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] database must be available to the client application. The UDT assembly can be placed in the same directory with the application, or in the Global Assembly Cache (GAC). You can also set a reference to the assembly in your project.
28
+
To create a user-defined type (UDT) on the client, the assembly registered as a UDT in a [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] database must be available to the client application. The UDT assembly can be placed in the same directory with the application, or in the Global Assembly Cache (GAC). You can also set a reference to the assembly in your project.
29
29
30
30
## Requirements for using UDTs in ADO.NET
31
31
32
-
The assembly loaded in [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] and the assembly on the client must be compatible in order for the UDT to be created on the client. For UDTs defined with the `Native` serialization format, the assemblies must be structurally compatible. For assemblies defined with the `UserDefined` format, the assembly must be available on the client.
32
+
The assembly loaded in [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] and the assembly on the client must be compatible for the UDT to be created on the client. For UDTs defined with the `Native` serialization format, the assemblies must be structurally compatible. For assemblies defined with the `UserDefined` format, the assembly must be available on the client.
33
33
34
-
You don't need a copy of the UDT assembly on the client in order to retrieve the raw data from a UDT column in a table.
34
+
You don't need a copy of the UDT assembly on the client to retrieve the raw data from a UDT column in a table.
35
35
36
36
> [!NOTE]
37
-
> `SqlClient` might fail to load a UDT in the event of mismatched UDT versions or other problems. In this case, use regular troubleshooting mechanisms to determine why the assembly containing the UDT can't be found by the calling application. For more information, see [Diagnose Errors with Managed Debugging Assistants](/dotnet/framework/debug-trace-profile/diagnosing-errors-with-managed-debugging-assistants).
37
+
> `SqlClient` might fail to load a UDT if UDT versions are mismatched or other problems occur. In this case, use regular troubleshooting mechanisms to determine why the assembly containing the UDT can't be found by the calling application. For more information, see [Diagnose Errors with Managed Debugging Assistants](/dotnet/framework/debug-trace-profile/diagnosing-errors-with-managed-debugging-assistants).
38
+
39
+
The code examples in this article use `Microsoft.Data.SqlClient`, which is available as a NuGet package. To add this dependency to your project, run the following command:
40
+
41
+
```dotnetcli
42
+
dotnet add package Microsoft.Data.SqlClient
43
+
```
38
44
39
45
## Access UDTs with a SqlDataReader
40
46
41
-
A `System.Data.SqlClient.SqlDataReader` can be used from client code to retrieve a result set that contains a UDT column, which is exposed as an instance of the object.
47
+
Use a `Microsoft.Data.SqlClient.SqlDataReader` from client code to retrieve a result set that contains a UDT column, which is exposed as an instance of the object.
42
48
43
49
### Example
44
50
@@ -50,11 +56,11 @@ This example shows how to use the `Main` method to create a new `SqlDataReader`
50
56
51
57
1. The UDT defines a `Distance` method and a `GetDistanceFromXY` method.
52
58
53
-
1. The sample code retrieves the values of the primary key and UDT columns in order to demonstrate the capabilities of the UDT.
59
+
1. The sample code retrieves the values of the primary key and UDT columns to demonstrate the capabilities of the UDT.
54
60
55
61
1. The sample code calls the `Point.Distance` and `Point.GetDistanceFromXY` methods.
56
62
57
-
1. The results are displayed in the console window.
63
+
1. The results display in the console window.
58
64
59
65
> [!NOTE]
60
66
> The application must already have a reference to the UDT assembly.
@@ -63,8 +69,7 @@ This example shows how to use the `Main` method to create a new `SqlDataReader`
63
69
64
70
```csharp
65
71
usingSystem;
66
-
usingSystem.Data.Sql;
67
-
usingSystem.Data.SqlClient;
72
+
usingMicrosoft.Data.SqlClient;
68
73
69
74
namespaceMicrosoft.Samples.SqlServer
70
75
{
@@ -118,8 +123,7 @@ Option Explicit On
118
123
Option StrictOn
119
124
120
125
ImportsSystem
121
-
ImportsSystem.Data.Sql
122
-
ImportsSystem.Data.SqlClient
126
+
ImportsMicrosoft.Data.SqlClient
123
127
124
128
ModuleReadPoints
125
129
SubMain()
@@ -164,18 +168,17 @@ End Module
164
168
165
169
## Bind UDTs as bytes
166
170
167
-
In some situations, you might want to retrieve the raw data from the UDT column. Perhaps the type isn't available locally, or you don't wish to instantiate an instance of the UDT. You can read the raw bytes into a byte array using the `GetBytes` method of a `SqlDataReader`. This method reads a stream of bytes from the specified column offset into the buffer of an array starting at a specified buffer offset. Another option is to use one of the `GetSqlBytes` or `GetSqlBinary` methods and read all of the contents in a single operation. In either case, the UDT object is never instantiated, so you don't need to set a reference to the UDT in the client assembly.
171
+
In some situations, you might want to retrieve the raw data from the UDT column. Perhaps the type isn't available locally, or you don't want to instantiate an instance of the UDT. You can read the raw bytes into a byte array by using the `GetBytes` method of a `SqlDataReader`. This method reads a stream of bytes from the specified column offset into the buffer of an array starting at a specified buffer offset. Another option is to use one of the `GetSqlBytes` or `GetSqlBinary` methods and read all of the contents in a single operation. In either case, the UDT object is never instantiated, so you don't need to set a reference to the UDT in the client assembly.
168
172
169
173
### Example
170
174
171
-
This example shows how to retrieve the `Point` data as raw bytes into a byte array using a `SqlDataReader`. The code uses a `System.Text.StringBuilder` to convert the raw bytes to a string representation to be displayed in the console window.
175
+
This example shows how to retrieve the `Point` data as raw bytes into a byte array by using a `SqlDataReader`. The code uses a `System.Text.StringBuilder` to convert the raw bytes to a string representation to be displayed in the console window.
172
176
173
177
### [C#](#tab/csharp)
174
178
175
179
```csharp
176
180
usingSystem;
177
-
usingSystem.Data.Sql;
178
-
usingSystem.Data.SqlClient;
181
+
usingMicrosoft.Data.SqlClient;
179
182
usingSystem.Data.SqlTypes;
180
183
usingSystem.Text;
181
184
@@ -228,8 +231,7 @@ Option Explicit On
228
231
Option StrictOn
229
232
230
233
ImportsSystem
231
-
ImportsSystem.Data.Sql
232
-
ImportsSystem.Data.SqlClient
234
+
ImportsMicrosoft.Data.SqlClient
233
235
ImportsSystem.Data.SqlTypes
234
236
ImportsSystem.Text
235
237
@@ -281,14 +283,13 @@ End Module
281
283
282
284
### Example using GetSqlBytes
283
285
284
-
This example shows how to retrieve the `Point` data as raw bytes in a single operation using the `GetSqlBytes` method. The code uses a `StringBuilder` to convert the raw bytes to a string representation to be displayed in the console window.
286
+
This example shows how to retrieve the `Point` data as raw bytes in a single operation by using the `GetSqlBytes` method. The code uses a `StringBuilder` to convert the raw bytes to a string representation to be displayed in the console window.
285
287
286
288
### [C#](#tab/csharp)
287
289
288
290
```csharp
289
291
usingSystem;
290
-
usingSystem.Data.Sql;
291
-
usingSystem.Data.SqlClient;
292
+
usingMicrosoft.Data.SqlClient;
292
293
usingSystem.Data.SqlTypes;
293
294
usingSystem.Text;
294
295
@@ -342,8 +343,7 @@ Option Explicit On
342
343
Option StrictOn
343
344
344
345
ImportsSystem
345
-
ImportsSystem.Data.Sql
346
-
ImportsSystem.Data.SqlClient
346
+
ImportsMicrosoft.Data.SqlClient
347
347
ImportsSystem.Data.SqlTypes
348
348
ImportsSystem.Text
349
349
@@ -393,11 +393,11 @@ End Module
393
393
394
394
## Work with UDT parameters
395
395
396
-
UDTs can be used as both input and output parameters in your ADO.NET code.
396
+
You can use UDTs as both input and output parameters in your ADO.NET code.
397
397
398
398
## Use UDTs in query parameters
399
399
400
-
UDTs can be used as parameter values when setting up a `SqlParameter` for a `System.Data.SqlClient.SqlCommand` object. The `SqlDbType.Udt` enumeration of a `SqlParameter` object is used to indicate that the parameter is a UDT when calling the `Add` method to the `Parameters` collection. The `UdtTypeName` property of a `SqlCommand` object is used to specify the fully qualified name of the UDT in the database using the `<database>.<schema_name>.<object_name>` syntax. You should use the fully qualified name to avoid ambiguity in your code.
400
+
You can use UDTs as parameter values when you set up a `SqlParameter` for a `Microsoft.Data.SqlClient.SqlCommand` object. The `SqlDbType.Udt` enumeration of a `SqlParameter` object indicates that the parameter is a UDT when calling the `Add` method to the `Parameters` collection. The `UdtTypeName` property of a `SqlCommand` object specifies the fully qualified name of the UDT in the database by using the `<database>.<schema_name>.<object_name>` syntax. Use the fully qualified name to avoid ambiguity in your code.
401
401
402
402
A local copy of the UDT assembly must be available to the client project.
403
403
@@ -410,8 +410,7 @@ The code in this example creates `SqlCommand` and `SqlParameter` objects to inse
Copy file name to clipboardExpand all lines: docs/relational-databases/clr-integration-database-objects-user-defined-types/accessing-user-defined-types-updating-udt-columns-with-dataadapters.md
+14-8Lines changed: 14 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,9 @@
1
1
---
2
2
title: "Updating UDT Columns With DataAdapters"
3
-
description: UDTs in a SQL Server database are supported by using System.Data.DataSet and System.Data.SqlClient.SqlDataAdapter to retrieve and modify data.
3
+
description: UDTs in a SQL Server database are supported by using System.Data.DataSet and Microsoft.Data.SqlClient.SqlDataAdapter to retrieve and modify data.
User-defined types (UDTs) are supported by using a `System.Data.DataSet` and a `System.Data.SqlClient.SqlDataAdapter` to retrieve and modify data.
29
+
You can retrieve and modify user-defined types (UDTs) by using a `System.Data.DataSet` and a `Microsoft.Data.SqlClient.SqlDataAdapter`.
30
+
31
+
The code examples in this article use `Microsoft.Data.SqlClient`, which is available as a NuGet package. To add this dependency to your project, run the following command:
32
+
33
+
```dotnetcli
34
+
dotnet add package Microsoft.Data.SqlClient
35
+
```
30
36
31
37
## Populate a dataset
32
38
33
-
You can use a [!INCLUDE [tsql](../../includes/tsql-md.md)]`SELECT` statement to select UDT column values to populate a dataset using a data adapter. The following example assumes that you have a `Points` table defined with the following structure and some sample data. The following [!INCLUDE [tsql](../../includes/tsql-md.md)] statements create the `Points` table and insert a few rows.
39
+
Use a [!INCLUDE [tsql](../../includes/tsql-md.md)]`SELECT` statement to select UDT column values to populate a dataset by using a data adapter. The following example assumes that you have a `Points` table defined with the following structure and some sample data. The following [!INCLUDE [tsql](../../includes/tsql-md.md)] statements create the `Points` table and insert a few rows.
34
40
35
41
```sql
36
42
CREATETABLEdbo.Points
@@ -81,7 +87,7 @@ You can use two methods to update a UDT column in a `DataSet`:
81
87
82
88
- Provide custom `InsertCommand`, `UpdateCommand`, and `DeleteCommand` objects for a `SqlDataAdapter` object.
83
89
84
-
- Use the command builder (`System.Data.SqlClient.SqlCommandBuilder`) to create automatically the `INSERT`, `UPDATE`, and `DELETE` commands for you. In order to have conflict detection, add a **timestamp** column (alias **rowversion**) to the [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] table that contains the UDT. The **timestamp** data type allows you to version-stamp the rows in a table, and is guaranteed to be unique within a database. When a value in the table is changed, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] automatically updates the 8-byte binary number for the row affected by the change.
90
+
- Use the command builder (`Microsoft.Data.SqlClient.SqlCommandBuilder`) to create automatically the `INSERT`, `UPDATE`, and `DELETE` commands for you. To enable conflict detection, add a **timestamp** column (alias **rowversion**) to the [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] table that contains the UDT. The **timestamp** data type allows you to version-stamp the rows in a table, and is guaranteed to be unique within a database. When a value in the table is changed, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] automatically updates the 8-byte binary number for the row affected by the change.
85
91
86
92
The `SqlCommandBuilder` doesn't consider the UDT for conflict detection unless there's a **timestamp** column in the underlying table. UDTs might or might not be comparable, so they aren't included in the `WHERE` clause when the "compare original values" option is used to generate a command.
-`UserProvidedCommands`, which demonstrates how to supply `InsertCommand`, `UpdateCommand`, and `DeleteCommand` objects for updating the `Point` UDT in the `Points` table (which doesn't contain a **timestamp** column).
121
+
-`UserProvidedCommands`, which demonstrates how to supply `InsertCommand`, `UpdateCommand`, and `DeleteCommand` objects for updating the `Point` UDT in the `Points` table (without a **timestamp** column).
116
122
117
123
-`CommandBuilder`, which demonstrates how to use a `SqlCommandBuilder` in the `Points_ts` table that contains the **timestamp** column.
118
124
@@ -121,7 +127,7 @@ The following ADO.NET example has two methods:
0 commit comments