Skip to content

Commit

Permalink
Merge pull request #54 from Avanade/v3.0.2
Browse files Browse the repository at this point in the history
v3.0.2
  • Loading branch information
chullybun authored Nov 25, 2024
2 parents e3df44a + b3a112b commit 0f8a5e5
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 8 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

Represents the **NuGet** versions.

## v3.0.2
- *Fixed:* The completion stage was incorrectly using the `EntityKey` versus `TableKey` (where using global identifiers) for the version hashing resulting in re-publishing where not required; code-generation template corrected and is required for fix.

## V3.0.1
- *Fixed:* Generated `ExecuteBatch.sql` fixed to not invoke `sys.fn_cdc_get_min_lsn` twice but use returned result as intended.
- *Fixed:* Generated `ExecuteBatch.sql` fixed to not invoke `sys.fn_cdc_get_min_lsn` twice but use returned result as intended.

## v3.0.0
- *Enhancement:* Major **"Sidecar"** feature added based on feedback from the community.
Expand Down
2 changes: 1 addition & 1 deletion Common.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.0.1</Version>
<Version>3.0.2</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>NTangle Developers</Authors>
<Company>Avanade</Company>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ BEGIN
LEFT OUTER JOIN [Legacy].[ContactMapping] AS [cm] ON ([cm].[ContactId] = [c].[ContactId])
LEFT OUTER JOIN [NTangle].[IdentifierMapping] AS [_im] ON ([_im].[Schema] = N'Legacy' AND [_im].[Table] = N'Contact' AND [_im].[Key] = CAST([_chg].[ContactId] AS NVARCHAR(128)))
LEFT OUTER JOIN [NTangle].[IdentifierMapping] AS [_im1] ON ([_im1].[Schema] = 'Legacy' AND [_im1].[Table] = 'Contact' AND [_im1].[Key] = CAST([c].[AlternateContactId] AS NVARCHAR(128)))
LEFT OUTER JOIN [NTangle].[VersionTracking] AS [_vt] ON ([_vt].[Schema] = N'Legacy' AND [_vt].[Table] = N'Contact' AND [_vt].[Key] = _im.GlobalId)
LEFT OUTER JOIN [NTangle].[VersionTracking] AS [_vt] ON ([_vt].[Schema] = N'Legacy' AND [_vt].[Table] = N'Contact' AND [_vt].[Key] = CAST([_chg].[ContactId] AS NVARCHAR(128)))
ORDER BY [_Lsn] ASC

-- Related table: '[Legacy].[Address]' - unique name 'Address' - only use INNER JOINS to get what is actually there right now (where applicable).
Expand Down
40 changes: 40 additions & 0 deletions samples/SqlServerDemo/SqlServerDemo.Test/ContactTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,45 @@ public async Task UsePreassignedIdentifiers()
ClassicAssert.NotNull(c.Address?.GlobalId);
ClassicAssert.AreEqual("C88", c.Address?.GlobalAlternateAddressId);
}

[Test]
public async Task NoPublishSameHash()
{
using var db = SqlServerUnitTest.GetDatabase();
var logger = UnitTest.GetLogger<ContactOrchestrator>();

// Update contact 1.
var script = "UPDATE [Legacy].[Contact] SET [Phone] = '8888' WHERE [ContactId] = 1";
await db.SqlStatement(script).NonQueryAsync().ConfigureAwait(false);
await UnitTest.Delay().ConfigureAwait(false);

var imp = new InMemoryPublisher(logger);
var cdc = new ContactOrchestrator(db, imp, JsonSerializer.Default, UnitTest.GetSettings(), logger, new IdentifierGenerator());
var cdcr = await cdc.ExecuteAsync().ConfigureAwait(false);
UnitTest.WriteResult(cdcr, imp);

// Assert/verify the results.
ClassicAssert.NotNull(cdcr);
ClassicAssert.IsTrue(cdcr.IsSuccessful);

var events = imp.GetEvents();
ClassicAssert.AreEqual(1, events.Length);

// Update contact 1 again with same value.
await db.SqlStatement("UPDATE [Legacy].[Contact] SET [Phone] = '7777' WHERE [ContactId] = 1").NonQueryAsync().ConfigureAwait(false);
await db.SqlStatement("UPDATE [Legacy].[Contact] SET [Phone] = '8888' WHERE [ContactId] = 1").NonQueryAsync().ConfigureAwait(false);
await UnitTest.Delay().ConfigureAwait(false);

imp.Reset();
cdcr = await cdc.ExecuteAsync().ConfigureAwait(false);
UnitTest.WriteResult(cdcr, imp);

// Assert/verify the results.
ClassicAssert.NotNull(cdcr);
ClassicAssert.IsTrue(cdcr.IsSuccessful);

events = imp.GetEvents();
ClassicAssert.AreEqual(0, events.Length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,47 @@ public async Task GenerateAllIdentifiers()
ClassicAssert.AreEqual(c.Address?.GlobalAlternateAddressId, c2.Address?.GlobalAlternateAddressId);
}

[Test]
public async Task NoPublishSameHash()
{
using var db = SqlServerSidecarUnitTest.GetDatabase();
using var sdb = SqlServerSidecarUnitTest.GetSidecarDatabase();
var logger = UnitTest.GetLogger<ContactOrchestrator>();

// Update contact 1.
var script = "UPDATE [Legacy].[Contact] SET [Phone] = '8888' WHERE [ContactId] = 1";
await db.SqlStatement(script).NonQueryAsync().ConfigureAwait(false);
await UnitTest.Delay().ConfigureAwait(false);

var imp = new InMemoryPublisher(logger);
var cdc = new ContactOrchestrator(db, sdb, imp, JsonSerializer.Default, UnitTest.GetSettings(), logger, new IdentifierGenerator());
var cdcr = await cdc.ExecuteAsync().ConfigureAwait(false);
UnitTest.WriteResult(cdcr, imp);

// Assert/verify the results.
ClassicAssert.NotNull(cdcr);
ClassicAssert.IsTrue(cdcr.IsSuccessful);

var events = imp.GetEvents();
ClassicAssert.AreEqual(1, events.Length);

// Update contact 1 again with same value.
await db.SqlStatement("UPDATE [Legacy].[Contact] SET [Phone] = '7777' WHERE [ContactId] = 1").NonQueryAsync().ConfigureAwait(false);
await db.SqlStatement("UPDATE [Legacy].[Contact] SET [Phone] = '8888' WHERE [ContactId] = 1").NonQueryAsync().ConfigureAwait(false);
await UnitTest.Delay().ConfigureAwait(false);

imp.Reset();
cdcr = await cdc.ExecuteAsync().ConfigureAwait(false);
UnitTest.WriteResult(cdcr, imp);

// Assert/verify the results.
ClassicAssert.NotNull(cdcr);
ClassicAssert.IsTrue(cdcr.IsSuccessful);

events = imp.GetEvents();
ClassicAssert.AreEqual(0, events.Length);
}

[Test]
public async Task UsePreassignedIdentifiers()
{
Expand Down
4 changes: 2 additions & 2 deletions src/NTangle/Cdc/EntityOrchestratorCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ protected internal Task ConsolidateAsync(EntityOrchestratorResult<TEntityEnvelop

// Consolidate the results.
var coll = new TEntityEnvelopeColl();
foreach (var grp in result.Result.GroupBy(x => new { x.EntityKey }))
foreach (var grp in result.Result.GroupBy(x => new { Key = x is IGlobalIdentifier gi ? gi.TableKey : x.EntityKey }))
{
// Find delete and use.
var item = grp.Where(x => x.DatabaseOperationType == CdcOperationType.Delete).FirstOrDefault();
Expand Down Expand Up @@ -407,7 +407,7 @@ protected internal async Task<List<VersionTracker>> VersionAsync(EntityOrchestra
if ((result.IsExplicitExecution && result.ExplicitOptions!.AlwaysPublishEvents) || item.DatabaseTrackingHash == null || item.DatabaseTrackingHash != entity.ETag)
{
coll.Add(item);
tracking.Add(new VersionTracker { Key = entity.EntityKey.ToString(), Hash = entity.ETag });
tracking.Add(new VersionTracker { Key = entity is IGlobalIdentifier gi ? gi.TableKey.ToString() : entity.EntityKey.ToString(), Hash = entity.ETag });
}

// Clear ETag where delete; i.e. non sensical.
Expand Down
2 changes: 1 addition & 1 deletion tools/NTangle.CodeGen/Templates/SpExecuteBatch_sql.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ BEGIN
LEFT OUTER JOIN [{{Root.CdcSchema}}].[{{Root.IdentifierMappingTable}}] AS [{{IdentifierMappingAlias}}] ON ([{{IdentifierMappingAlias}}].[Schema] = '{{IdentifierMappingSchema}}' AND [{{IdentifierMappingAlias}}].[Table] = '{{IdentifierMappingTable}}' AND [{{IdentifierMappingAlias}}].[Key] = CAST([{{IdentifierMappingParent.Parent.Alias}}].[{{IdentifierMappingParent.Name}}] AS NVARCHAR(128)))
{{/ifval}}
{{/each}}
LEFT OUTER JOIN [{{Root.CdcSchema}}].[{{Root.VersionTrackingTable}}] AS [_vt] ON ([_vt].[Schema] = N'{{Schema}}' AND [_vt].[Table] = N'{{Table}}' AND [_vt].[Key] = {{#if IdentifierMapping}}_im.GlobalId){{else}}{{#ifeq PrimaryKeyColumns.Count 1}}{{#each PrimaryKeyColumns}}CAST([_chg].[{{Name}}] AS NVARCHAR(128))){{/each}}{{else}}CONCAT({{#each PrimaryKeyColumns}}CAST([_chg].[{{Name}}] AS NVARCHAR(128))){{#unless @last}}, ',', {{/unless}}{{/each}}){{/ifeq}}{{/if}}
LEFT OUTER JOIN [{{Root.CdcSchema}}].[{{Root.VersionTrackingTable}}] AS [_vt] ON ([_vt].[Schema] = N'{{Schema}}' AND [_vt].[Table] = N'{{Table}}' AND [_vt].[Key] = {{#ifeq PrimaryKeyColumns.Count 1}}{{#each PrimaryKeyColumns}}CAST([_chg].[{{Name}}] AS NVARCHAR(128))){{/each}}{{else}}CONCAT({{#each PrimaryKeyColumns}}CAST([_chg].[{{Name}}] AS NVARCHAR(128))){{#unless @last}}, ',', {{/unless}}{{/each}}){{/ifeq}}
ORDER BY [_Lsn] ASC

{{#each CdcJoins}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NTangle.CodeGen" Version="3.0.1" />
<PackageReference Include="NTangle.CodeGen" Version="3.0.2" />
</ItemGroup>
<ItemGroup>
<None Update="ntangle.yaml">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<EmbeddedResource Include="Resources\**\*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NTangle" Version="3.0.1" />
<PackageReference Include="NTangle" Version="3.0.2" />
<PackageReference Include="CoreEx.Azure" Version="3.30.0" />
<!--#if (implement_publisher_console) -->
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
Expand Down

0 comments on commit 0f8a5e5

Please sign in to comment.