-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stored json gets corrupted on SqlServer after an update with a smalle…
…r sized payload (#1332) * Stored json gets corrupted on SqlServer after an update with a smaller sized payload (#1331) * Fix issue where sql parameter optimalisation was applied for INSERT/UPDATE. Now only applied for `ExecuteReaderAsync` and `ExecuteReaderAsync`. * Fix failing CI tests due to new test using incorrect table for testing * Updated the test name to better express its intent * Version still supports NETFRAMEWORK and await using isn't supported in NETFX
- Loading branch information
1 parent
bb6a57a
commit b610ee0
Showing
4 changed files
with
123 additions
and
12 deletions.
There are no files selected for viewing
96 changes: 96 additions & 0 deletions
96
src/SqlPersistence.PersistenceTests/When_updating_saga_with_smaller_state.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
namespace NServiceBus.PersistenceTesting.Sagas | ||
{ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using NUnit.Framework; | ||
|
||
public class When_updating_saga_with_smaller_state : SagaPersisterTests | ||
{ | ||
[Test] | ||
public async Task It_should_truncate_the_stored_state() | ||
{ | ||
// When updating an existing saga where the serialized state is smaller in length than the previous the column value should not have any left over data from the previous value. | ||
// The deserializer ignores any trailing | ||
|
||
var sqlVariant = (SqlTestVariant)param.Values[0]; | ||
|
||
if (sqlVariant.Dialect is not SqlDialect.MsSqlServer) | ||
{ | ||
Assert.Ignore("Only relevant for SQL Server"); | ||
return; // Satisfy compiler | ||
} | ||
|
||
var sagaData = new SagaWithCorrelationPropertyData | ||
{ | ||
CorrelatedProperty = Guid.NewGuid().ToString(), | ||
Payload = "very long state" | ||
}; | ||
|
||
await SaveSaga(sagaData); | ||
|
||
SagaWithCorrelationPropertyData retrieved; | ||
var context = configuration.GetContextBagForSagaStorage(); | ||
var persister = configuration.SagaStorage; | ||
|
||
using (var completeSession = configuration.CreateStorageSession()) | ||
{ | ||
await completeSession.Open(context); | ||
|
||
retrieved = await persister.Get<SagaWithCorrelationPropertyData>(nameof(sagaData.CorrelatedProperty), sagaData.CorrelatedProperty, completeSession, context); | ||
|
||
retrieved.Payload = "short"; | ||
|
||
await persister.Update(retrieved, completeSession, context); | ||
await completeSession.CompleteAsync(); | ||
} | ||
|
||
var retrieved2 = await GetById<SagaWithCorrelationPropertyData>(sagaData.Id); | ||
|
||
Assert.LessOrEqual(retrieved.Payload, sagaData.Payload); // No real need, but here to prevent accidental updates | ||
Assert.AreEqual(retrieved.Payload, retrieved2.Payload); | ||
#if NETFRAMEWORK | ||
using var con = sqlVariant.Open(); | ||
#else | ||
await using var con = sqlVariant.Open(); | ||
#endif | ||
await con.OpenAsync(); | ||
var cmd = con.CreateCommand(); | ||
cmd.CommandText = $"SELECT Data FROM [PersistenceTests_SWCP] WHERE Id = '{retrieved.Id}'"; | ||
var data = (string)await cmd.ExecuteScalarAsync(); | ||
|
||
// Payload should only have a single closing bracket, if there are more that means there is trailing data | ||
var countClosingBrackets = data.ToCharArray().Count(x => x == '}'); | ||
|
||
Assert.AreEqual(1, countClosingBrackets); | ||
} | ||
|
||
public class SagaWithCorrelationProperty : Saga<SagaWithCorrelationPropertyData>, IAmStartedByMessages<StartMessage> | ||
{ | ||
public Task Handle(StartMessage message, IMessageHandlerContext context) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<SagaWithCorrelationPropertyData> mapper) | ||
{ | ||
mapper.ConfigureMapping<StartMessage>(msg => msg.SomeId).ToSaga(saga => saga.CorrelatedProperty); | ||
} | ||
} | ||
|
||
public class SagaWithCorrelationPropertyData : ContainSagaData | ||
{ | ||
public string CorrelatedProperty { get; set; } | ||
public string Payload { get; set; } | ||
} | ||
|
||
public class StartMessage | ||
{ | ||
public string SomeId { get; set; } | ||
} | ||
|
||
public When_updating_saga_with_smaller_state(TestVariant param) : base(param) | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters