Skip to content

Commit 54591b1

Browse files
authored
v2.6.0 (#59)
* v2.6.0 - *Enhancement:* Added a `DbColumnSchema.SqlType2` that does _not_ include nullability. - *Enhancement:* The `SqlServerSchemaScript.SupportsReplace` is enabled where a `CREATE OR ALTER` is specified. - *Enhancement:* The SQL Server [Event Outbox](https://github.com/Avanade/CoreEx/blob/main/src/CoreEx.Database.SqlServer/Outbox/EventOutboxEnqueueBase.cs) (_CoreEx_ `v3.26.0`) capabilities now support events as JSON versus existing TVP removing database dependency on a UDT (user-defined type). - *Fixed:* The logic for finding file-based SQL schema scripts has been corrected.
1 parent f9162fb commit 54591b1

28 files changed

+136
-90
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Represents the **NuGet** versions.
44

5+
## v2.6.0
6+
- *Enhancement:* Added a `DbColumnSchema.SqlType2` that does _not_ include nullability.
7+
- *Enhancement:* The `SqlServerSchemaScript.SupportsReplace` is enabled where a `CREATE OR ALTER` is specified.
8+
- *Enhancement:* The SQL Server [Event Outbox](https://github.com/Avanade/CoreEx/blob/main/src/CoreEx.Database.SqlServer/Outbox/EventOutboxEnqueueBase.cs) (_CoreEx_ `v3.26.0`) capabilities now support events as JSON versus existing TVP removing database dependency on a UDT (user-defined type).
9+
- *Fixed:* The logic for finding file-based SQL schema scripts has been corrected.
10+
511
## v2.5.9
612
- *Fixed:* All related package dependencies updated to latest.
713

Common.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>2.5.9</Version>
3+
<Version>2.6.0</Version>
44
<LangVersion>preview</LangVersion>
55
<Authors>Avanade</Authors>
66
<Company>Avanade</Company>

src/DbEx.MySql/DbEx.MySql.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</ItemGroup>
4242

4343
<ItemGroup>
44-
<PackageReference Include="CoreEx.Database.MySql" Version="3.23.0" />
44+
<PackageReference Include="CoreEx.Database.MySql" Version="3.25.6" />
4545
<PackageReference Include="dbup-mysql" Version="5.0.44" />
4646
</ItemGroup>
4747

src/DbEx.MySql/Migration/MySqlMigration.cs

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public MySqlMigration(MigrationArgsBase args) : base(args)
5050
if (SchemaObjectTypes.Length == 0)
5151
SchemaObjectTypes = ["FUNCTION", "VIEW", "PROCEDURE"];
5252

53+
// MySql will require all schema objects to be dropped as replacements are not currently supported.
54+
if (MustDropSchemaObjectTypes.Length == 0)
55+
MustDropSchemaObjectTypes = ["FUNCTION", "VIEW", "PROCEDURE"];
56+
5357
// Add/set standard parameters.
5458
Args.AddParameter(MigrationArgsBase.DatabaseNameParamName, _databaseName, true);
5559
Args.AddParameter(MigrationArgsBase.JournalSchemaParamName, null, true);

src/DbEx.Postgres/DbEx.Postgres.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
</ItemGroup>
4343

4444
<ItemGroup>
45-
<PackageReference Include="CoreEx.Database.Postgres" Version="3.23.0" />
45+
<PackageReference Include="CoreEx.Database.Postgres" Version="3.25.6" />
4646
<PackageReference Include="dbup-postgresql" Version="5.0.40" />
4747
</ItemGroup>
4848

src/DbEx.Postgres/Migration/PostgresSchemaScript.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static PostgresSchemaScript Create(DatabaseMigrationScript migrationScrip
3636
{
3737
if (string.Compare(tokens[i + 1], "or", StringComparison.OrdinalIgnoreCase) == 0 && string.Compare(tokens[i + 2], "replace", StringComparison.OrdinalIgnoreCase) == 0)
3838
{
39-
i = +2;
39+
i =+ 2;
4040
script.SupportsReplace = true;
4141
}
4242

src/DbEx.SqlServer/DbEx.SqlServer.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
</ItemGroup>
3333

3434
<ItemGroup>
35-
<PackageReference Include="CoreEx.Database.SqlServer" Version="3.23.0" />
35+
<PackageReference Include="CoreEx.Database.SqlServer" Version="3.25.6" />
3636
<PackageReference Include="dbup-sqlserver" Version="5.0.41" />
37+
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
3738
</ItemGroup>
3839

3940
<ItemGroup>

src/DbEx.SqlServer/Migration/SqlServerMigration.cs

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ public SqlServerMigration(MigrationArgsBase args) : base(args)
5454
if (SchemaObjectTypes.Length == 0)
5555
SchemaObjectTypes = ["TYPE", "FUNCTION", "VIEW", "PROCEDURE", "PROC"];
5656

57+
// A schema object type that is a user-defined type will require all schema objects to be dropped (as it may be referenced).
58+
if (MustDropSchemaObjectTypes.Length == 0)
59+
MustDropSchemaObjectTypes = ["TYPE"];
60+
5761
// Always add the dbo schema _first_ unless already specified.
5862
if (!Args.SchemaOrder.Contains(SchemaConfig.DefaultSchema))
5963
Args.SchemaOrder.Insert(0, SchemaConfig.DefaultSchema);

src/DbEx.SqlServer/Migration/SqlServerSchemaScript.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ public static SqlServerSchemaScript Create(DatabaseMigrationScript migrationScri
3232
if (string.Compare(tokens[i], "create", StringComparison.OrdinalIgnoreCase) != 0)
3333
continue;
3434

35-
if (i + 2 < tokens.Length)
35+
if (i + 4 < tokens.Length)
3636
{
37+
if (string.Compare(tokens[i + 1], "or", StringComparison.OrdinalIgnoreCase) == 0 && string.Compare(tokens[i + 2], "alter", StringComparison.OrdinalIgnoreCase) == 0)
38+
{
39+
i = +2;
40+
script.SupportsReplace = true;
41+
}
42+
3743
script.Type = tokens[i + 1];
3844
script.FullyQualifiedName = tokens[i + 2];
3945

@@ -67,7 +73,7 @@ private SqlServerSchemaScript(DatabaseMigrationScript migrationScript) : base(mi
6773
public override string SqlDropStatement => $"DROP {Type.ToUpperInvariant()} IF EXISTS [{Schema}].[{Name}]";
6874

6975
/// <inheritdoc/>
70-
public override string SqlCreateStatement => $"CREATE {Type.ToUpperInvariant()} [{Schema}].[{Name}]";
76+
public override string SqlCreateStatement => $"CREATE {(SupportsReplace ? "OR ALTER " : "")}{Type.ToUpperInvariant()} [{Schema}].[{Name}]";
7177

7278
private class SqlCommandTokenizer(string sqlText) : SqlCommandReader(sqlText)
7379
{
@@ -93,7 +99,7 @@ public string[] ReadAllTokens()
9399
sb.Clear();
94100
break;
95101
}
96-
else if (new char[] { '(', ')', ';', ',', '=' }.Contains(c))
102+
else if (delimiters.Contains(c))
97103
{
98104
if (sb.Length > 0)
99105
words.Add(sb.ToString());

src/DbEx.SqlServer/Templates/EventOutboxEnqueue_cs.hbs

-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ namespace {{NamespaceOutbox}}.Data;
1717
/// <param name="logger">The <see cref="ILogger"/>.</param>
1818
public sealed class EventOutboxEnqueue(IDatabase database, ILogger<EventOutboxEnqueue> logger) : EventOutboxEnqueueBase(database, logger)
1919
{
20-
/// <inheritdoc/>
21-
protected override string DbTvpTypeName => "[{{OutboxSchema}}].[udt{{OutboxTable}}List]";
22-
2320
/// <inheritdoc/>
2421
protected override string EnqueueStoredProcedure => "[{{OutboxSchema}}].[{{OutboxEnqueueStoredProcedure}}]";
2522
}{{#if Root.PreprocessorDirectives}}

src/DbEx.SqlServer/Templates/SpEventOutboxDequeue_sql.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{! Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/NTangle }}
2-
CREATE PROCEDURE [{{OutboxSchema}}].[sp{{OutboxTable}}Dequeue]
2+
CREATE OR ALTER PROCEDURE [{{OutboxSchema}}].[sp{{OutboxTable}}Dequeue]
33
@MaxDequeueSize INT = 10, -- Maximum number of events to dequeue.
44
@PartitionKey NVARCHAR(127) NULL = NULL, -- Partition key; null indicates all.
55
@Destination NVARCHAR(127) NULL = NULL -- Destination (queue or topic); null indicates all.

src/DbEx.SqlServer/Templates/SpEventOutboxEnqueue_sql.hbs

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{{! Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/NTangle }}
2-
CREATE PROCEDURE [{{OutboxSchema}}].[sp{{OutboxTable}}Enqueue]
2+
CREATE OR ALTER PROCEDURE [{{OutboxSchema}}].[sp{{OutboxTable}}Enqueue]
33
@SetEventsAsDequeued AS BIT = 0,
4-
@EventList AS [{{OutboxSchema}}].[udt{{OutboxTable}}List] READONLY
4+
@EventList AS NVARCHAR(MAX)
55
AS
66
BEGIN
77
/*
@@ -25,6 +25,24 @@ BEGIN
2525
-- Enqueued outbox resultant identifier.
2626
DECLARE @enqueuedId TABLE([{{OutboxTable}}Id] BIGINT)
2727

28+
-- Convert the JSON to a temporary table.
29+
SELECT * INTO #eventList FROM OPENJSON(@EventList) WITH (
30+
[EventId] NVARCHAR(127) '$.EventId',
31+
[EventDequeued] BIT '$.EventDequeued',
32+
[Destination] NVARCHAR(127) '$.Destination',
33+
[Subject] NVARCHAR(511) '$.Subject',
34+
[Action] NVARCHAR(255) '$.Action',
35+
[Type] NVARCHAR(1023) '$.Type',
36+
[Source] NVARCHAR(1023) '$.Source',
37+
[Timestamp] DATETIMEOFFSET '$.Timestamp',
38+
[CorrelationId] NVARCHAR(127) '$.CorrelationId',
39+
[Key] NVARCHAR(1023) '$.Key',
40+
[TenantId] NVARCHAR(127) '$.TenantId',
41+
[PartitionKey] NVARCHAR(127) '$.PartitionKey',
42+
[ETag] NVARCHAR(127) '$.ETag',
43+
[Attributes] VARBINARY(MAX) '$.Attributes',
44+
[Data] VARBINARY(MAX) '$.Data')
45+
2846
-- Cursor output variables.
2947
DECLARE @eventId NVARCHAR(127),
3048
@eventDequeued BIT,
@@ -44,7 +62,7 @@ BEGIN
4462

4563
-- Declare, open, and fetch first event from cursor.
4664
DECLARE c CURSOR FORWARD_ONLY
47-
FOR SELECT [EventId], [EventDequeued], [Destination], [Subject], [Action], [Type], [Source], [Timestamp], [CorrelationId], [Key], [TenantId], [PartitionKey], [ETag], [Attributes], [Data] FROM @EventList
65+
FOR SELECT [EventId], [EventDequeued], [Destination], [Subject], [Action], [Type], [Source], [Timestamp], [CorrelationId], [Key], [TenantId], [PartitionKey], [ETag], [Attributes], [Data] FROM #eventList
4866

4967
OPEN c
5068
FETCH NEXT FROM c INTO @eventId, @eventDequeued, @destination, @subject, @action, @type, @source, @timestamp, @correlationId, @key, @tenantId, @partitionKey, @etag, @attributes, @data

src/DbEx.SqlServer/Templates/UdtEventOutbox_sql.hbs

-22
This file was deleted.

src/DbEx/DbEx.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
</ItemGroup>
2121

2222
<ItemGroup>
23-
<PackageReference Include="CoreEx.Database" Version="3.23.0" />
24-
<PackageReference Include="OnRamp" Version="2.2.1" />
23+
<PackageReference Include="CoreEx.Database" Version="3.25.6" />
24+
<PackageReference Include="OnRamp" Version="2.2.2" />
2525
</ItemGroup>
2626

2727
<Import Project="..\..\Common.targets" />

src/DbEx/DbSchema/DbColumnSchema.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class DbColumnSchema(DbTableSchema dbTable, string name, string type, str
2020
private string? _dotNetName = dotNetNameOverride;
2121
private string? _dotNetCleanedName;
2222
private string? _sqlType;
23+
private string? _sqlType2;
2324

2425
/// <summary>
2526
/// Gets the owning (parent) <see cref="DbTable"/>.
@@ -177,10 +178,15 @@ public class DbColumnSchema(DbTableSchema dbTable, string name, string type, str
177178
public string DotNetCleanedName { get => _dotNetCleanedName ?? DotNetName; set => _dotNetCleanedName = value; }
178179

179180
/// <summary>
180-
/// Gets the fully defined SQL type.
181+
/// Gets the fully defined SQL type (includes nullability).
181182
/// </summary>
182183
public string SqlType => _sqlType ??= DbTable?.Migration.SchemaConfig.ToFormattedSqlType(this) ?? throw new InvalidOperationException($"The {nameof(DbTable)} must be set before the {nameof(SqlType)} property can be accessed.");
183184

185+
/// <summary>
186+
/// Gets the fully defined SQL type (excludes nullability).
187+
/// </summary>
188+
public string SqlType2 => _sqlType2 ??= DbTable?.Migration.SchemaConfig.ToFormattedSqlType(this, false) ?? throw new InvalidOperationException($"The {nameof(DbTable)} must be set before the {nameof(SqlType)} property can be accessed.");
189+
184190
#if NET7_0_OR_GREATER
185191
/// <summary>
186192
/// Indicates that the type can be expressed as a <see cref="DateOnly"/> .NET type.

src/DbEx/Migration/DatabaseMigrationBase.cs

+28-14
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,12 @@ protected DatabaseMigrationBase(MigrationArgsBase args)
126126
/// </summary>
127127
/// <remarks>The objects will be added in the order specified, and removed in the reverse order. This is to allow for potential dependencies between the object types.
128128
/// <para>Where none are specified then the <see cref="MigrationCommand.Schema"/> phase will be skipped.</para></remarks>
129-
public string[] SchemaObjectTypes { get; set; }
129+
public string[] SchemaObjectTypes { get; set; } = [];
130+
131+
/// <summary>
132+
/// Gets or sets the list of schema object types that where found must result in all schema objects being dropped and then recreated.
133+
/// </summary>
134+
public string[] MustDropSchemaObjectTypes { get; set; } = [];
130135

131136
/// <summary>
132137
/// Gets the assemblies used for probing the requisite artefact resources (used for providing the underlying requisite database statements for the specified <see cref="Provider"/>).
@@ -513,16 +518,17 @@ private async Task<bool> DatabaseSchemaAsync(CancellationToken cancellationToken
513518
var scripts = new List<DatabaseMigrationScript>();
514519

515520
// See if there are any files out there that should take precedence over embedded resources.
516-
if (Args.OutputDirectory != null)
521+
var dir = new DirectoryInfo(CodeGenConsole.GetBaseExeDirectory());
522+
if (dir != null && dir.Exists)
517523
{
518-
var di = new DirectoryInfo(Path.Combine(Args.OutputDirectory.FullName, SchemaNamespace));
524+
var di = new DirectoryInfo(Path.Combine(dir.FullName, SchemaNamespace));
519525
Logger.LogInformation("{Content}", $" Probing for files (recursively): {Path.Combine(di.FullName, "*", "*.sql")}");
520526

521527
if (di.Exists)
522528
{
523529
foreach (var fi in di.GetFiles("*.sql", SearchOption.AllDirectories))
524530
{
525-
var rn = $"{fi.FullName[((Args.OutputDirectory?.Parent?.FullName.Length + 1) ?? 0)..]}".Replace(' ', '_').Replace('-', '_').Replace('\\', '.').Replace('/', '.');
531+
var rn = $"{fi.FullName[((dir.Parent?.FullName.Length + 1) ?? 0)..]}".Replace(' ', '_').Replace('-', '_').Replace('\\', '.').Replace('/', '.');
526532
scripts.Add(new DatabaseMigrationScript(this, fi, rn));
527533
}
528534
}
@@ -573,27 +579,35 @@ protected virtual async Task<bool> DatabaseSchemaAsync(List<DatabaseMigrationScr
573579
var script = ValidateAndReadySchemaScript(CreateSchemaScript(migrationScript));
574580
if (script.HasError)
575581
{
576-
Logger.LogError("{Message}", $"SQL script '{migrationScript.Name}' is not valid: {script.ErrorMessage}");
582+
Logger.LogError("{Content}", $"SQL script '{migrationScript.Name}' is not valid: {script.ErrorMessage}");
577583
return false;
578584
}
579585

580586
list.Add(script);
581587
}
582588

583589
// Drop all existing (in reverse order).
584-
int i = 0;
585-
var ss = new List<DatabaseMigrationScript>();
586590
Logger.LogInformation("{Content}", string.Empty);
587591
Logger.LogInformation("{Content}", " Drop known schema objects...");
588-
foreach (var sor in list.Where(x => !x.SupportsReplace).OrderByDescending(x => x.SchemaOrder).ThenByDescending(x => x.TypeOrder).ThenByDescending(x => x.Schema).ThenByDescending(x => x.Name))
592+
593+
var fullDrop = Args.DropSchemaObjects;
594+
if (!fullDrop && MustDropSchemaObjectTypes.Length > 0)
595+
fullDrop = list.Where(x => MustDropSchemaObjectTypes.Contains(x.Type, StringComparer.OrdinalIgnoreCase)).Any();
596+
597+
int i = 0;
598+
var ss = new List<DatabaseMigrationScript>();
599+
if (fullDrop || list.Where(x => !x.SupportsReplace).Any())
589600
{
590-
ss.Add(new DatabaseMigrationScript(this, sor.SqlDropStatement, sor.SqlDropStatement) { GroupOrder = i++, RunAlways = true });
591-
}
601+
foreach (var sor in list.Where(x => fullDrop || !x.SupportsReplace).OrderByDescending(x => x.SchemaOrder).ThenByDescending(x => x.TypeOrder).ThenByDescending(x => x.Schema).ThenByDescending(x => x.Name))
602+
{
603+
ss.Add(new DatabaseMigrationScript(this, sor.SqlDropStatement, sor.SqlDropStatement) { GroupOrder = i++, RunAlways = true });
604+
}
592605

593-
if (i == 0)
594-
Logger.LogInformation("{Content}", " None.");
595-
else if (!await ExecuteScriptsAsync(ss, true, cancellationToken).ConfigureAwait(false))
596-
return false;
606+
if (!await ExecuteScriptsAsync(ss, true, cancellationToken).ConfigureAwait(false))
607+
return false;
608+
}
609+
else
610+
Logger.LogInformation("{Content}", " ** Note: All schema objects implement replace functionality and therefore there is no need to drop existing. **");
597611

598612
// Execute each migration script proper (i.e. create 'em as scripted).
599613
i = 0;

src/DbEx/Migration/DatabaseSchemaScriptBase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public abstract class DatabaseSchemaScriptBase(DatabaseMigrationScript migration
7474
public bool HasError => ErrorMessage != null;
7575

7676
/// <summary>
77-
/// Indicates whether the schema script supports a create or replace; i.e. does not require a drop and create as two separate operations.
77+
/// Indicates whether the schema script supports a create or replace/alter; i.e. does not require a drop and create as two separate operations.
7878
/// </summary>
7979
public bool SupportsReplace { get; protected set; }
8080

src/DbEx/Migration/MigrationArgsBase.cs

+5
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ public abstract class MigrationArgsBase : OnRamp.CodeGeneratorDbArgsBase
167167
/// </summary>
168168
public bool AcceptPrompts { get; set; }
169169

170+
/// <summary>
171+
/// Indicates whether to drop all the known schema objects before creating them.
172+
/// </summary>
173+
public bool DropSchemaObjects { get; set; }
174+
170175
/// <summary>
171176
/// Gets or sets the <see cref="MigrationCommand.Reset"/> table filtering predicate.
172177
/// </summary>

tests/DbEx.Test.Console/Properties/launchSettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"DbEx.Test.Console": {
44
"commandName": "Project",
5-
"commandLineArgs": "dropandall"
5+
"commandLineArgs": "all"
66
}
77
}
88
}

tests/DbEx.Test.Console/Schema/spGetContact.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CREATE PROCEDURE Test.spGetContact
1+
CREATE OR ALTER PROCEDURE Test.spGetContact
22
@ContactId AS INT /* this is a comment */
33
AS
44
BEGIN

tests/DbEx.Test.Console/Schema/spGetContact2.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CREATE PROCEDURE [Test].[spGetContact2]
1+
CREATE OR ALTER PROCEDURE [Test].[spGetContact2]
22
@ContactId AS INT /* this is a comment */
33
AS
44
BEGIN

tests/DbEx.Test.OutboxConsole/DbEx.Test.OutboxConsole.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
<ItemGroup>
3030
<Folder Include="Generated\" />
3131
<Folder Include="Migrations\" />
32-
<Folder Include="Schema\" />
3332
</ItemGroup>
3433

3534
</Project>

tests/DbEx.Test.OutboxConsole/Generated/EventOutboxEnqueue.cs

-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ namespace DbEx.Test.OutboxConsole.Data;
1111
/// <param name="logger">The <see cref="ILogger"/>.</param>
1212
public sealed class EventOutboxEnqueue(IDatabase database, ILogger<EventOutboxEnqueue> logger) : EventOutboxEnqueueBase(database, logger)
1313
{
14-
/// <inheritdoc/>
15-
protected override string DbTvpTypeName => "[Outbox].[udtEventOutboxList]";
16-
1714
/// <inheritdoc/>
1815
protected override string EnqueueStoredProcedure => "[Outbox].[spEventOutboxEnqueue]";
1916
}

tests/DbEx.Test.OutboxConsole/Schema/Outbox/Stored Procedures/Generated/spEventOutboxDequeue.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CREATE PROCEDURE [Outbox].[spEventOutboxDequeue]
1+
CREATE OR ALTER PROCEDURE [Outbox].[spEventOutboxDequeue]
22
@MaxDequeueSize INT = 10, -- Maximum number of events to dequeue.
33
@PartitionKey NVARCHAR(127) NULL = NULL, -- Partition key; null indicates all.
44
@Destination NVARCHAR(127) NULL = NULL -- Destination (queue or topic); null indicates all.

0 commit comments

Comments
 (0)