Merge branch 'dev' into Validation-decorator-integration
This commit is contained in:
commit
007525b4cc
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26228.4
|
VisualStudioVersion = 15.0.26228.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -72,6 +72,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus", "src\BuildingBlo
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBusRabbitMQ", "src\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj", "{8088F3FC-6787-45FA-A924-816EC81CBFAC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBusRabbitMQ", "src\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj", "{8088F3FC-6787-45FA-A924-816EC81CBFAC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationEventLogEF", "src\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj", "{9EE28E45-1533-472B-8267-56C48855BA0E}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
||||||
@ -662,6 +664,54 @@ Global
|
|||||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x64.Build.0 = Release|Any CPU
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.ActiveCfg = Release|Any CPU
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.Build.0 = Release|Any CPU
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.AppStore|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhone.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -689,5 +739,6 @@ Global
|
|||||||
{807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
{807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} = {DB0EFB20-B024-4E5E-A75C-52143C131D25}
|
||||||
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{0044B293-1DCC-4224-B948-00CF6DC7F510} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
{8088F3FC-6787-45FA-A924-816EC81CBFAC} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
|
{9EE28E45-1533-472B-8267-56C48855BA0E} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -11,6 +11,6 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events
|
|||||||
Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid Id { get; private set; }
|
public Guid Id { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
|
|||||||
private readonly Dictionary<string, List<IIntegrationEventHandler>> _handlers;
|
private readonly Dictionary<string, List<IIntegrationEventHandler>> _handlers;
|
||||||
private readonly List<Type> _eventTypes;
|
private readonly List<Type> _eventTypes;
|
||||||
|
|
||||||
private Tuple<IModel, IConnection> _connection;
|
private IModel _model;
|
||||||
|
private IConnection _connection;
|
||||||
private string _queueName;
|
private string _queueName;
|
||||||
|
|
||||||
|
|
||||||
@ -86,15 +87,15 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
|
|||||||
_handlers.Remove(eventName);
|
_handlers.Remove(eventName);
|
||||||
var eventType = _eventTypes.Single(e => e.Name == eventName);
|
var eventType = _eventTypes.Single(e => e.Name == eventName);
|
||||||
_eventTypes.Remove(eventType);
|
_eventTypes.Remove(eventType);
|
||||||
_connection.Item1.QueueUnbind(queue: _queueName,
|
_model.QueueUnbind(queue: _queueName,
|
||||||
exchange: _brokerName,
|
exchange: _brokerName,
|
||||||
routingKey: eventName);
|
routingKey: eventName);
|
||||||
|
|
||||||
if (_handlers.Keys.Count == 0)
|
if (_handlers.Keys.Count == 0)
|
||||||
{
|
{
|
||||||
_queueName = string.Empty;
|
_queueName = string.Empty;
|
||||||
_connection.Item1.Dispose();
|
_model.Dispose();
|
||||||
_connection.Item2.Dispose();
|
_connection.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -103,50 +104,53 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_connection != null)
|
_handlers.Clear();
|
||||||
{
|
_model?.Dispose();
|
||||||
_handlers.Clear();
|
_connection?.Dispose();
|
||||||
_connection.Item1.Dispose();
|
|
||||||
_connection.Item2.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IModel GetChannel()
|
private IModel GetChannel()
|
||||||
{
|
{
|
||||||
if (_connection != null)
|
if (_model != null)
|
||||||
{
|
{
|
||||||
return _connection.Item1;
|
return _model;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var factory = new ConnectionFactory() { HostName = _connectionString };
|
(_model, _connection) = CreateConnection();
|
||||||
var connection = factory.CreateConnection();
|
return _model;
|
||||||
var channel = connection.CreateModel();
|
|
||||||
|
|
||||||
channel.ExchangeDeclare(exchange: _brokerName,
|
|
||||||
type: "direct");
|
|
||||||
if (string.IsNullOrEmpty(_queueName))
|
|
||||||
{
|
|
||||||
_queueName = channel.QueueDeclare().QueueName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var consumer = new EventingBasicConsumer(channel);
|
|
||||||
consumer.Received += async (model, ea) =>
|
|
||||||
{
|
|
||||||
var eventName = ea.RoutingKey;
|
|
||||||
var message = Encoding.UTF8.GetString(ea.Body);
|
|
||||||
|
|
||||||
await ProcessEvent(eventName, message);
|
|
||||||
};
|
|
||||||
channel.BasicConsume(queue: _queueName,
|
|
||||||
noAck: true,
|
|
||||||
consumer: consumer);
|
|
||||||
_connection = new Tuple<IModel, IConnection>(channel, connection);
|
|
||||||
|
|
||||||
return _connection.Item1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private (IModel model, IConnection connection) CreateConnection()
|
||||||
|
{
|
||||||
|
var factory = new ConnectionFactory() { HostName = _connectionString };
|
||||||
|
var con = factory.CreateConnection();
|
||||||
|
var channel = con.CreateModel();
|
||||||
|
|
||||||
|
channel.ExchangeDeclare(exchange: _brokerName,
|
||||||
|
type: "direct");
|
||||||
|
if (string.IsNullOrEmpty(_queueName))
|
||||||
|
{
|
||||||
|
_queueName = channel.QueueDeclare().QueueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var consumer = new EventingBasicConsumer(channel);
|
||||||
|
consumer.Received += async (model, ea) =>
|
||||||
|
{
|
||||||
|
var eventName = ea.RoutingKey;
|
||||||
|
var message = Encoding.UTF8.GetString(ea.Body);
|
||||||
|
|
||||||
|
await ProcessEvent(eventName, message);
|
||||||
|
};
|
||||||
|
channel.BasicConsume(queue: _queueName,
|
||||||
|
noAck: true,
|
||||||
|
consumer: consumer);
|
||||||
|
|
||||||
|
return (channel, con);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ProcessEvent(string eventName, string message)
|
private async Task ProcessEvent(string eventName, string message)
|
||||||
{
|
{
|
||||||
if (_handlers.ContainsKey(eventName))
|
if (_handlers.ContainsKey(eventName))
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="4.1.1" />
|
<PackageReference Include="RabbitMQ.Client" Version="4.1.1" />
|
||||||
|
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLog
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
{
|
{
|
||||||
public enum EventStateEnum
|
public enum EventStateEnum
|
||||||
{
|
{
|
@ -0,0 +1,48 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
|
{
|
||||||
|
public class IntegrationEventLogContext : DbContext
|
||||||
|
{
|
||||||
|
public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("IntegrationEventLog");
|
||||||
|
|
||||||
|
builder.HasKey(e => e.EventId);
|
||||||
|
|
||||||
|
builder.Property(e => e.EventId)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.Content)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.CreationTime)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.State)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.TimesSent)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.Property(e => e.EventTypeName)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<RuntimeFrameworkVersion>1.1.0</RuntimeFrameworkVersion>
|
||||||
|
<RootNamespace>Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\EventBus\EventBus.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -2,11 +2,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLog
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
|
||||||
{
|
{
|
||||||
public class IntegrationEventLogEntry
|
public class IntegrationEventLogEntry
|
||||||
{
|
{
|
||||||
|
private IntegrationEventLogEntry() { }
|
||||||
public IntegrationEventLogEntry(IntegrationEvent @event)
|
public IntegrationEventLogEntry(IntegrationEvent @event)
|
||||||
{
|
{
|
||||||
EventId = @event.Id;
|
EventId = @event.Id;
|
@ -58,6 +58,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Catalog.API.IntegrationEvents;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLog;
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
||||||
@ -16,28 +18,31 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
public class CatalogController : ControllerBase
|
public class CatalogController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly CatalogContext _context;
|
private readonly CatalogContext _catalogContext;
|
||||||
private readonly IOptionsSnapshot<Settings> _settings;
|
private readonly IOptionsSnapshot<Settings> _settings;
|
||||||
private readonly IEventBus _eventBus;
|
private readonly IEventBus _eventBus;
|
||||||
|
private readonly IIntegrationEventLogService _integrationEventLogService;
|
||||||
|
|
||||||
public CatalogController(CatalogContext context, IOptionsSnapshot<Settings> settings, IEventBus eventBus)
|
public CatalogController(CatalogContext Context, IOptionsSnapshot<Settings> settings, IEventBus eventBus, IIntegrationEventLogService integrationEventLogService)
|
||||||
{
|
{
|
||||||
_context = context;
|
_catalogContext = Context;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
_eventBus = eventBus;
|
_eventBus = eventBus;
|
||||||
|
_integrationEventLogService = integrationEventLogService;
|
||||||
|
|
||||||
((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
((DbContext)Context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
|
|
||||||
{
|
{
|
||||||
var totalItems = await _context.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
.LongCountAsync();
|
.LongCountAsync();
|
||||||
|
|
||||||
var itemsOnPage = await _context.CatalogItems
|
var itemsOnPage = await _catalogContext.CatalogItems
|
||||||
.OrderBy(c=>c.Name)
|
.OrderBy(c=>c.Name)
|
||||||
.Skip(pageSize * pageIndex)
|
.Skip(pageSize * pageIndex)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
@ -57,11 +62,11 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
public async Task<IActionResult> Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items(string name, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
var totalItems = await _context.CatalogItems
|
var totalItems = await _catalogContext.CatalogItems
|
||||||
.Where(c => c.Name.StartsWith(name))
|
.Where(c => c.Name.StartsWith(name))
|
||||||
.LongCountAsync();
|
.LongCountAsync();
|
||||||
|
|
||||||
var itemsOnPage = await _context.CatalogItems
|
var itemsOnPage = await _catalogContext.CatalogItems
|
||||||
.Where(c => c.Name.StartsWith(name))
|
.Where(c => c.Name.StartsWith(name))
|
||||||
.Skip(pageSize * pageIndex)
|
.Skip(pageSize * pageIndex)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
@ -80,7 +85,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId}")]
|
[Route("[action]/type/{catalogTypeId}/brand/{catalogBrandId}")]
|
||||||
public async Task<IActionResult> Items(int? catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
public async Task<IActionResult> Items(int? catalogTypeId, int? catalogBrandId, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||||
{
|
{
|
||||||
var root = (IQueryable<CatalogItem>)_context.CatalogItems;
|
var root = (IQueryable<CatalogItem>)_catalogContext.CatalogItems;
|
||||||
|
|
||||||
if (catalogTypeId.HasValue)
|
if (catalogTypeId.HasValue)
|
||||||
{
|
{
|
||||||
@ -113,7 +118,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> CatalogTypes()
|
public async Task<IActionResult> CatalogTypes()
|
||||||
{
|
{
|
||||||
var items = await _context.CatalogTypes
|
var items = await _catalogContext.CatalogTypes
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return Ok(items);
|
return Ok(items);
|
||||||
@ -124,7 +129,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[Route("[action]")]
|
[Route("[action]")]
|
||||||
public async Task<IActionResult> CatalogBrands()
|
public async Task<IActionResult> CatalogBrands()
|
||||||
{
|
{
|
||||||
var items = await _context.CatalogBrands
|
var items = await _catalogContext.CatalogBrands
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return Ok(items);
|
return Ok(items);
|
||||||
@ -135,7 +140,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> EditProduct([FromBody]CatalogItem product)
|
public async Task<IActionResult> EditProduct([FromBody]CatalogItem product)
|
||||||
{
|
{
|
||||||
var item = await _context.CatalogItems.SingleOrDefaultAsync(i => i.Id == product.Id);
|
var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == product.Id);
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
@ -146,20 +151,21 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
{
|
{
|
||||||
var oldPrice = item.Price;
|
var oldPrice = item.Price;
|
||||||
item.Price = product.Price;
|
item.Price = product.Price;
|
||||||
_context.CatalogItems.Update(item);
|
|
||||||
|
|
||||||
var @event = new ProductPriceChangedIntegrationEvent(item.Id, item.Price, oldPrice);
|
var @event = new ProductPriceChangedIntegrationEvent(item.Id, item.Price, oldPrice);
|
||||||
var eventLogEntry = new IntegrationEventLogEntry(@event);
|
|
||||||
_context.IntegrationEventLog.Add(eventLogEntry);
|
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
using (var transaction = _catalogContext.Database.BeginTransaction())
|
||||||
|
{
|
||||||
|
_catalogContext.CatalogItems.Update(item);
|
||||||
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
await _integrationEventLogService.SaveEventAsync(@event);
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
_eventBus.Publish(@event);
|
_eventBus.Publish(@event);
|
||||||
|
|
||||||
eventLogEntry.TimesSent++;
|
await _integrationEventLogService.MarkEventAsPublishedAsync(@event);
|
||||||
eventLogEntry.State = EventStateEnum.Published;
|
|
||||||
_context.IntegrationEventLog.Update(eventLogEntry);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
@ -170,7 +176,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> CreateProduct([FromBody]CatalogItem product)
|
public async Task<IActionResult> CreateProduct([FromBody]CatalogItem product)
|
||||||
{
|
{
|
||||||
_context.CatalogItems.Add(
|
_catalogContext.CatalogItems.Add(
|
||||||
new CatalogItem
|
new CatalogItem
|
||||||
{
|
{
|
||||||
CatalogBrandId = product.CatalogBrandId,
|
CatalogBrandId = product.CatalogBrandId,
|
||||||
@ -181,7 +187,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
Price = product.Price
|
Price = product.Price
|
||||||
});
|
});
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -191,15 +197,15 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
public async Task<IActionResult> DeleteProduct(int id)
|
public async Task<IActionResult> DeleteProduct(int id)
|
||||||
{
|
{
|
||||||
var product = _context.CatalogItems.SingleOrDefault(x => x.Id == id);
|
var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id);
|
||||||
|
|
||||||
if (product == null)
|
if (product == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.CatalogItems.Remove(product);
|
_catalogContext.CatalogItems.Remove(product);
|
||||||
await _context.SaveChangesAsync();
|
await _catalogContext.SaveChangesAsync();
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,24 @@
|
|||||||
using EntityFrameworkCore.Metadata.Builders;
|
using EntityFrameworkCore.Metadata.Builders;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Model;
|
using Model;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLog;
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
public class CatalogContext : DbContext
|
public class CatalogContext : DbContext
|
||||||
{
|
{
|
||||||
public CatalogContext(DbContextOptions options) : base(options)
|
public CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public DbSet<CatalogItem> CatalogItems { get; set; }
|
public DbSet<CatalogItem> CatalogItems { get; set; }
|
||||||
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
||||||
public DbSet<CatalogType> CatalogTypes { get; set; }
|
public DbSet<CatalogType> CatalogTypes { get; set; }
|
||||||
public DbSet<IntegrationEventLogEntry> IntegrationEventLog { get; set; }
|
//public DbSet<IntegrationEventLogEntry> IntegrationEventLog { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Entity<CatalogBrand>(ConfigureCatalogBrand);
|
builder.Entity<CatalogBrand>(ConfigureCatalogBrand);
|
||||||
builder.Entity<CatalogType>(ConfigureCatalogType);
|
builder.Entity<CatalogType>(ConfigureCatalogType);
|
||||||
builder.Entity<CatalogItem>(ConfigureCatalogItem);
|
builder.Entity<CatalogItem>(ConfigureCatalogItem);
|
||||||
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
|
//builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureCatalogItem(EntityTypeBuilder<CatalogItem> builder)
|
void ConfigureCatalogItem(EntityTypeBuilder<CatalogItem> builder)
|
||||||
@ -80,30 +80,30 @@
|
|||||||
.HasMaxLength(100);
|
.HasMaxLength(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
|
//void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
|
||||||
{
|
//{
|
||||||
builder.ToTable("IntegrationEventLog");
|
// builder.ToTable("IntegrationEventLog");
|
||||||
|
|
||||||
builder.HasKey(e => e.EventId);
|
// builder.HasKey(e => e.EventId);
|
||||||
|
|
||||||
builder.Property(e => e.EventId)
|
// builder.Property(e => e.EventId)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
builder.Property(e => e.Content)
|
// builder.Property(e => e.Content)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
builder.Property(e => e.CreationTime)
|
// builder.Property(e => e.CreationTime)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
builder.Property(e => e.State)
|
// builder.Property(e => e.State)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
builder.Property(e => e.TimesSent)
|
// builder.Property(e => e.TimesSent)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
builder.Property(e => e.EventTypeName)
|
// builder.Property(e => e.EventTypeName)
|
||||||
.IsRequired();
|
// .IsRequired();
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CatalogContext))]
|
||||||
|
[Migration("20170322124244_RemoveIntegrationEventLogs")]
|
||||||
|
partial class RemoveIntegrationEventLogs
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_brand_hilo", "'catalog_brand_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_hilo", "'catalog_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_brand_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogBrand");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<int>("CatalogBrandId");
|
||||||
|
|
||||||
|
b.Property<int>("CatalogTypeId");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
|
||||||
|
b.Property<string>("PictureUri");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogBrandId");
|
||||||
|
|
||||||
|
b.HasIndex("CatalogTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Catalog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasAnnotation("SqlServer:HiLoSequenceName", "catalog_type_hilo")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CatalogType");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", "CatalogBrand")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogBrandId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogType", "CatalogType")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CatalogTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class RemoveIntegrationEventLogs : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEventLog");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEventLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
namespace Catalog.API.Infrastructure.Migrations
|
namespace Catalog.API.Infrastructure.Migrations
|
||||||
{
|
{
|
||||||
@ -20,28 +19,6 @@ namespace Catalog.API.Infrastructure.Migrations
|
|||||||
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
.HasAnnotation("SqlServer:Sequence:.catalog_type_hilo", "'catalog_type_hilo', '', '1', '10', '', '', 'Int64', 'False'")
|
||||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events.IntegrationEventLogEntry", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("EventId")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<string>("Content")
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime");
|
|
||||||
|
|
||||||
b.Property<string>("EventTypeName")
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Property<int>("State");
|
|
||||||
|
|
||||||
b.Property<int>("TimesSent");
|
|
||||||
|
|
||||||
b.HasKey("EventId");
|
|
||||||
|
|
||||||
b.ToTable("IntegrationEventLog");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Catalog.API.Model.CatalogBrand", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(IntegrationEventLogContext))]
|
||||||
|
[Migration("20170322145434_IntegrationEventInitial")]
|
||||||
|
partial class IntegrationEventInitial
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
public partial class IntegrationEventInitial : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IntegrationEventLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
EventId = table.Column<Guid>(nullable: false),
|
||||||
|
Content = table.Column<string>(nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(nullable: false),
|
||||||
|
EventTypeName = table.Column<string>(nullable: false),
|
||||||
|
State = table.Column<int>(nullable: false),
|
||||||
|
TimesSent = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IntegrationEventLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
|
||||||
|
namespace Catalog.API.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(IntegrationEventLogContext))]
|
||||||
|
partial class IntegrationEventLogContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.1")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("EventId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime");
|
||||||
|
|
||||||
|
b.Property<string>("EventTypeName")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("State");
|
||||||
|
|
||||||
|
b.Property<int>("TimesSent");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.ToTable("IntegrationEventLog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Catalog.API.IntegrationEvents
|
||||||
|
{
|
||||||
|
public interface IIntegrationEventLogService
|
||||||
|
{
|
||||||
|
Task SaveEventAsync(IntegrationEvent @event);
|
||||||
|
Task MarkEventAsPublishedAsync(IntegrationEvent @event);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
|
||||||
|
namespace Catalog.API.IntegrationEvents
|
||||||
|
{
|
||||||
|
public class IntegrationEventLogService : IIntegrationEventLogService
|
||||||
|
{
|
||||||
|
private readonly IntegrationEventLogContext _integrationEventLogContext;
|
||||||
|
private readonly CatalogContext _catalogContext;
|
||||||
|
|
||||||
|
public IntegrationEventLogService(CatalogContext catalogContext)
|
||||||
|
{
|
||||||
|
_catalogContext = catalogContext;
|
||||||
|
_integrationEventLogContext = new IntegrationEventLogContext(
|
||||||
|
new DbContextOptionsBuilder<IntegrationEventLogContext>()
|
||||||
|
.UseSqlServer(catalogContext.Database.GetDbConnection())
|
||||||
|
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))
|
||||||
|
.Options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SaveEventAsync(IntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var eventLogEntry = new IntegrationEventLogEntry(@event);
|
||||||
|
|
||||||
|
// as a constraint this transaction has to be done together with a catalogContext transaction
|
||||||
|
_integrationEventLogContext.Database.UseTransaction(_catalogContext.Database.CurrentTransaction.GetDbTransaction());
|
||||||
|
_integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
|
||||||
|
|
||||||
|
return _integrationEventLogContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task MarkEventAsPublishedAsync(IntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == @event.Id);
|
||||||
|
eventLogEntry.TimesSent++;
|
||||||
|
eventLogEntry.State = EventStateEnum.Published;
|
||||||
|
|
||||||
|
_integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry);
|
||||||
|
|
||||||
|
return _integrationEventLogContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,19 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||||
{
|
{
|
||||||
|
using global::Catalog.API.IntegrationEvents;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Data.SqlClient;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
@ -36,15 +39,23 @@
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
var sqlConnection = new SqlConnection(Configuration["ConnectionString"]);
|
||||||
|
|
||||||
services.AddDbContext<CatalogContext>(c =>
|
services.AddDbContext<CatalogContext>(c =>
|
||||||
{
|
{
|
||||||
c.UseSqlServer(Configuration["ConnectionString"]);
|
c.UseSqlServer(sqlConnection);
|
||||||
// Changing default behavior when client evaluation occurs to throw.
|
// Changing default behavior when client evaluation occurs to throw.
|
||||||
// Default in EF Core would be to log a warning when client evaluation is performed.
|
// Default in EF Core would be to log a warning when client evaluation is performed.
|
||||||
c.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
c.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
||||||
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDbContext<IntegrationEventLogContext>(c =>
|
||||||
|
{
|
||||||
|
c.UseSqlServer(sqlConnection, b => b.MigrationsAssembly("Catalog.API"));
|
||||||
|
c.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
|
||||||
|
});
|
||||||
|
|
||||||
services.Configure<Settings>(Configuration);
|
services.Configure<Settings>(Configuration);
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
@ -70,6 +81,8 @@
|
|||||||
.AllowCredentials());
|
.AllowCredentials());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddTransient<IIntegrationEventLogService, IntegrationEventLogService>();
|
||||||
|
|
||||||
var serviceProvider = services.BuildServiceProvider();
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
var configuration = serviceProvider.GetRequiredService<IOptionsSnapshot<Settings>>().Value;
|
var configuration = serviceProvider.GetRequiredService<IOptionsSnapshot<Settings>>().Value;
|
||||||
services.AddSingleton<IEventBus>(new EventBusRabbitMQ(configuration.EventBusConnection));
|
services.AddSingleton<IEventBus>(new EventBusRabbitMQ(configuration.EventBusConnection));
|
||||||
@ -77,7 +90,7 @@
|
|||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IntegrationEventLogContext integrationEventLogContext)
|
||||||
{
|
{
|
||||||
//Configure logs
|
//Configure logs
|
||||||
|
|
||||||
@ -98,9 +111,10 @@
|
|||||||
|
|
||||||
//Seed Data
|
//Seed Data
|
||||||
CatalogContextSeed.SeedAsync(app, loggerFactory)
|
CatalogContextSeed.SeedAsync(app, loggerFactory)
|
||||||
.Wait();
|
.Wait();
|
||||||
|
|
||||||
|
|
||||||
|
integrationEventLogContext.Database.Migrate();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user