Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions sample/SqlServerEventStore/SqlServerEventStore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ void DoJsonSerializedEvents()
public class BinarySampleRuntime : SimpleCqrs.SimpleCqrsRuntime<SimpleCqrs.Unity.UnityServiceLocator>
{
protected override IEventStore GetEventStore(SimpleCqrs.IServiceLocator serviceLocator) {
var configuration = new SqlServerConfiguration("Server=(local)\\sqlexpress;Database=test_event_store;Trusted_Connection=True;",
"dbo", "binary_event_store");
var configuration = new SqlServerConfiguration(@"Server=(local)\sqlexpress;Database=test_event_store;Trusted_Connection=True;");
return new SqlServerEventStore(configuration, new BinaryDomainEventSerializer());
}
}
Expand All @@ -80,8 +79,7 @@ public class JsonSampleRuntime : SimpleCqrs.SimpleCqrsRuntime<SimpleCqrs.Unity.U
{
protected override IEventStore GetEventStore(SimpleCqrs.IServiceLocator serviceLocator)
{
var configuration = new SqlServerConfiguration("Server=(local)\\sqlexpress;Database=test_event_store;Trusted_Connection=True;",
"dbo", "json_event_store");
var configuration = new SqlServerConfiguration(@"Server=(local)\sqlexpress;Database=test_event_store;Trusted_Connection=True;");
return new SqlServerEventStore(configuration, new JsonDomainEventSerializer());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
<HintPath>..\..\..\binaries\servicelocators\unity\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\..\..\src\EventStores\SimpleCqrs.EventStore.SqlServer\bin\Debug\ServiceStack.Text.dll</HintPath>
<HintPath>..\..\..\lib\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="SimpleCqrs">
<HintPath>..\..\..\binaries\SimpleCqrs.dll</HintPath>
</Reference>
<Reference Include="SimpleCqrs.EventStore.SqlServer">
<HintPath>..\..\..\src\EventStores\SimpleCqrs.EventStore.SqlServer\bin\Debug\SimpleCqrs.EventStore.SqlServer.dll</HintPath>
<HintPath>..\..\..\binaries\eventstores\sqlserver\SimpleCqrs.EventStore.SqlServer.dll</HintPath>
</Reference>
<Reference Include="SimpleCqrs.Unity">
<HintPath>..\..\..\binaries\servicelocators\unity\SimpleCqrs.Unity.dll</HintPath>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleCqrs.Eventing;

namespace SimpleCqrs.EventStore.MySql
{
public interface IDomainEventSerializer
{
string Serialize(DomainEvent domainEvent);
DomainEvent Deserialize(Type targetType, string serializedDomainEvent);
}
}
123 changes: 123 additions & 0 deletions src/EventStores/SimpleCqrs.EventStore.MySql/MySqlEventStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
// using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using System.Linq;
using System.Text;
using ServiceStack.Text;
using SimpleCqrs.Eventing;
using Dapper;

namespace SimpleCqrs.EventStore.MySql
{
public class MySqlEventStore : IEventStore
{
private readonly IDomainEventSerializer serializer;
private readonly MySqlServerConfiguration configuration;

public MySqlEventStore(MySqlServerConfiguration configuration, IDomainEventSerializer serializer)
{
this.serializer = serializer;
this.configuration = configuration;
Init();
}

public void Init()
{
using (var connection = new MySqlConnection(configuration.ConnectionString))
{
connection.Open();
var sql = string.Format(MySqlStatements.CreateTheEventStoreTable, "EventStore");
using (var command = new MySqlCommand(sql, connection))
command.ExecuteNonQuery();
connection.Close();
}
}

public IEnumerable<DomainEvent> GetEvents(Guid aggregateRootId, int startSequence)
{
var events = new List<DomainEvent>();
using (var connection = new MySqlConnection(configuration.ConnectionString))
{
connection.Open();
var sql = string.Format(MySqlStatements.GetEventsByAggregateRootAndSequence, "", "EventStore", aggregateRootId,
startSequence);
using (var command = new MySqlCommand(sql, connection))
using (var reader = command.ExecuteReader())
while (reader.Read())
{
var type = reader["EventType"].ToString();
var data = reader["data"].ToString();

try
{
events.Add(serializer.Deserialize(Type.GetType(type), data));
} catch(ArgumentNullException ex)
{
throw new Exception(string.Format("Cannot find type '{0}', yet the type is in the event store. Are you sure you haven't changed a class name or something arising from mental dullness?", type.Split(',')[0]), ex.InnerException);
}
}
connection.Close();
}
return events;
}

public void Insert(IEnumerable<DomainEvent> domainEvents)
{
var queries = domainEvents.Select( domainEvent =>
new {
EventType = TypeToStringHelperMethods.GetString(domainEvent.GetType()),
AggregateRootId = domainEvent.AggregateRootId,
EventDate = domainEvent.EventDate,
Sequence = domainEvent.Sequence,
Data = (serializer.Serialize(domainEvent) ?? string.Empty)
.Replace("'", "''")
});


if (!queries.Any()) return;

using (var connection = new MySqlConnection(configuration.ConnectionString))
{
connection.Open();
connection.Execute(string.Format(MySqlStatements.InsertEvents, "EventStore"), queries);
connection.Close();
}
}

public IEnumerable<DomainEvent> GetEventsByEventTypes(IEnumerable<Type> domainEventTypes)
{
var events = new List<DomainEvent>();

var eventParameters = domainEventTypes.Select(TypeToStringHelperMethods.GetString).Join("','");

using (var connection = new MySqlConnection(configuration.ConnectionString))
{
connection.Open();
var sql = string.Format(MySqlStatements.GetEventsByType, "EventStore", eventParameters);
using (var command = new MySqlCommand(sql, connection))
using (var reader = command.ExecuteReader())
while (reader.Read())
{
var type = reader["EventType"].ToString();
var data = reader["data"].ToString();

var domainEvent = serializer.Deserialize(Type.GetType(type), data);
events.Add(domainEvent);
}
connection.Close();
}
return events;
}

public IEnumerable<DomainEvent> GetEventsByEventTypes(IEnumerable<Type> domainEventTypes, Guid aggregateRootId)
{
throw new NotImplementedException();
}

public IEnumerable<DomainEvent> GetEventsByEventTypes(IEnumerable<Type> domainEventTypes, DateTime startDate, DateTime endDate)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace SimpleCqrs.EventStore.MySql
{
public class MySqlServerConfiguration
{
private readonly string connectionString;

public MySqlServerConfiguration(string connectionString)
{
this.connectionString = connectionString;
}

public string ConnectionString
{
get { return connectionString; }
}
}
}
21 changes: 21 additions & 0 deletions src/EventStores/SimpleCqrs.EventStore.MySql/MySqlStatements.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace SimpleCqrs.EventStore.MySql
{
public class MySqlStatements
{
internal const string GetEventsByType = "SELECT EVENTTYPE, DATA FROM {0} WHERE EVENTTYPE IN (@EventType)";
internal const string InsertEvents = @"INSERT INTO {0} (EventType, AggregateRootId, EventDate, Sequence, Data) VALUES ( @EventType, @AggregateRootId, @EventDate, @Sequence, @Data)";
internal const string GetEventsByAggregateRootAndSequence = @"SELECT eventtype, data FROM {1} WHERE aggregaterootid = @AggregateRootId AND sequence >= @Sequence";
internal const string CreateTheEventStoreTable = @"CREATE TABLE IF NOT EXISTS {0}
(
EventId INT AUTO_INCREMENT NOT NULL,
EventType VARCHAR(255),
AggregateRootId VARBINARY(36) NOT NULL,
EventDate DATETIME NOT NULL,
Sequence int NOT NULL,
Data BLOB,
CONSTRAINT PK_{0} PRIMARY KEY (EventId)
);";


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SimpleCqrs.EventStore.MySql")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Hewlett-Packard")]
[assembly: AssemblyProduct("SimpleCqrs.EventStore.MySql")]
[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3d0353d4-22d9-4336-a0e9-2d7d380e2faa")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using ServiceStack.Text;
using SimpleCqrs.Eventing;

namespace SimpleCqrs.EventStore.MySql.Serializers
{
public class JsonDomainEventSerializer : IDomainEventSerializer
{

public string Serialize(DomainEvent domainEvent)
{
return JsonSerializer.SerializeToString(domainEvent, domainEvent.GetType());
}

public DomainEvent Deserialize(Type targetType, string serializedDomainEvent)
{
return (DomainEvent)JsonSerializer.DeserializeFromString(serializedDomainEvent, targetType);
}
}

public class BinaryDomainEventSerializer : IDomainEventSerializer
{
public string Serialize(DomainEvent domainEvent) {
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream()) {
formatter.Serialize(stream, domainEvent);
stream.Flush();
stream.Position = 0;
return Convert.ToBase64String(stream.ToArray());
}
}

public DomainEvent Deserialize(Type targetType, string serializedDomainEvent) {
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream(Convert.FromBase64String(serializedDomainEvent))) {
return (DomainEvent)formatter.Deserialize(stream);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D55AC0E2-94D7-4805-A108-C51A59F9E2D1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SimpleCqrs.EventStore.MySql</RootNamespace>
<AssemblyName>SimpleCqrs.EventStore.MySql</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\binaries\eventstores\mysql\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="MySql.Data">
<HintPath>..\..\packages\MySql.Data.6.5.4\lib\net40\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\..\..\lib\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IDomainEventSerializer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Serializers\JsonDomainEventSerializer.cs" />
<Compile Include="MySqlServerConfiguration.cs" />
<Compile Include="MySqlEventStore.cs" />
<Compile Include="MySqlStatements.cs" />
<Compile Include="SqlMapper.cs" />
<Compile Include="TypeToStringHelperMethods.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SimpleCqrs\SimpleCqrs.csproj">
<Project>{E04C12B5-A6D3-4D64-9F38-896BEE68162E}</Project>
<Name>SimpleCqrs</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Loading