Skip to content

Instantly share code, notes, and snippets.

@SzymonPobiega
Created June 21, 2019 10:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SzymonPobiega/6730b2275847b0fb7b90339e7e751bb9 to your computer and use it in GitHub Desktop.
Save SzymonPobiega/6730b2275847b0fb7b90339e7e751bb9 to your computer and use it in GitHub Desktop.
namespace NServiceBus.AcceptanceTests.Sagas
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EndpointTemplates;
using AcceptanceTesting;
using global::NHibernate.Cfg;
using global::NHibernate.Dialect;
using global::NHibernate.Driver;
using global::NHibernate.Mapping.ByCode;
using global::NHibernate.Mapping.ByCode.Conformist;
using NUnit.Framework;
using Persistence;
using Environment = global::NHibernate.Cfg.Environment;
public class When_saga_contains_polymorphic_collection : NServiceBusAcceptanceTest
{
[Test]
public async Task Should_persist_correctly()
{
var result = await Scenario.Define<Context>(c => c.Id = Guid.NewGuid())
.WithEndpoint<NHNestedCollectionEndpoint>(b => b.When(async (bus, context) =>
{
await bus.SendLocal(new Message1
{
SomeId = context.Id
}).ConfigureAwait(false);
}))
.Done(c => c.Done)
.Run();
Assert.IsTrue(result.Done);
Assert.AreEqual(5, result.CircleDiameter);
Assert.AreEqual(7, result.SquareSideLength);
}
public class Context : ScenarioContext
{
public Guid Id { get; set; }
public bool Done { get; set; }
public decimal SquareSideLength { get; set; }
public decimal CircleDiameter { get; set; }
}
public class NHNestedCollectionEndpoint : EndpointConfigurationBuilder
{
public NHNestedCollectionEndpoint()
{
EndpointSetup<DefaultServer>(c =>
{
var cfg = new Configuration();
cfg.SetProperty(Environment.Dialect, typeof(MsSql2012Dialect).FullName);
cfg.SetProperty(Environment.ConnectionDriver, typeof(Sql2008ClientDriver).FullName);
cfg.SetProperty(Environment.ConnectionString, EndpointConfigurer.ConnectionString);
var mapper = new ModelMapper();
mapper.AddMapping(typeof(ShapeElementMap));
mapper.AddMapping(typeof(ShapeElementMap.CircleElementMap));
mapper.AddMapping(typeof(ShapeElementMap.SquareElementMap));
mapper.AddMapping(typeof(PolymorphicCollectionSagaDataMap));
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
c.UsePersistence<NHibernatePersistence>().UseConfiguration(cfg);
c.LimitMessageProcessingConcurrencyTo(1);
});
}
public class NHNestedCollectionSaga : Saga<PolymorphicCollectionSagaData>, IHandleMessages<Message2>, IAmStartedByMessages<Message1>
{
public Context ScenarioContext { get; set; }
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<PolymorphicCollectionSagaData> mapper)
{
mapper.ConfigureMapping<Message2>(m => m.SomeId).ToSaga(s => s.SomeId);
mapper.ConfigureMapping<Message1>(m => m.SomeId).ToSaga(s => s.SomeId);
}
public Task Handle(Message1 message, IMessageHandlerContext context)
{
Data.SomeId = message.SomeId;
Data.RelatedData.Add(new CircleElement
{
Diameter = 5,
});
Data.RelatedData.Add(new SquareElement
{
SideLength = 7,
});
return context.SendLocal(new Message2
{
SomeId = message.SomeId
});
}
public Task Handle(Message2 message, IMessageHandlerContext context)
{
var square = Data.RelatedData.OfType<SquareElement>().First();
ScenarioContext.SquareSideLength = square.SideLength;
var circle = Data.RelatedData.OfType<CircleElement>().First();
ScenarioContext.CircleDiameter = circle.Diameter;
ScenarioContext.Done = true;
return Task.CompletedTask;
}
}
}
public class PolymorphicCollectionSagaData : IContainSagaData
{
public virtual Guid Id { get; set; }
public virtual string Originator { get; set; }
public virtual string OriginalMessageId { get; set; }
public virtual Guid SomeId { get; set; }
public virtual IList<ShapeElement> RelatedData { get; set; } = new List<ShapeElement>();
}
public class Message2 : IMessage
{
public Guid SomeId { get; set; }
}
public class Message1 : IMessage
{
public Guid SomeId { get; set; }
}
public class PolymorphicCollectionSagaDataMap : ClassMapping<PolymorphicCollectionSagaData>
{
public PolymorphicCollectionSagaDataMap()
{
Id(x => x.Id, m => m.Generator(Generators.Assigned));
Table("PolymorphicCollectionSagaData");
Property(x => x.Originator);
Property(x => x.OriginalMessageId);
Property(x => x.SomeId);
Bag(x => x.RelatedData, m =>
{
m.Cascade(Cascade.All);
}, m => m.OneToMany());
}
}
public class ShapeElementMap : ClassMapping<ShapeElement>
{
public ShapeElementMap()
{
Id(x => x.Id, m => m.Generator(Generators.Guid));
Abstract(true);
Discriminator(m => m.Column("type"));
Table("ShapeElement");
}
public class CircleElementMap : SubclassMapping<CircleElement>
{
public CircleElementMap()
{
DiscriminatorValue("circle");
Property(x => x.Diameter);
}
}
public class SquareElementMap : SubclassMapping<SquareElement>
{
public SquareElementMap()
{
DiscriminatorValue("square");
Property(x => x.SideLength);
}
}
}
public abstract class ShapeElement
{
public virtual Guid Id { get; set; }
}
public class CircleElement : ShapeElement
{
public virtual decimal Diameter { get; set; }
}
public class SquareElement : ShapeElement
{
public virtual decimal SideLength { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment