Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="cdmdotnet Limited">
4 : // // Copyright cdmdotnet Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Data.Linq;
12 : using System.Linq;
13 : using cdmdotnet.Logging;
14 : using Cqrs.Configuration;
15 : using Cqrs.DataStores;
16 : using Cqrs.Entities;
17 :
18 : namespace Cqrs.Events
19 : {
20 : /// <summary>
21 : /// A simplified SqlServer based <see cref="EventStore{TAuthenticationToken}"/> that uses LinqToSql and follows a rigid schema.
22 : /// </summary>
23 : public class SqlEventStore<TAuthenticationToken> : EventStore<TAuthenticationToken>
24 1 : {
25 : internal const string SqlEventStoreDbFileOrServerOrConnectionApplicationKey = @"SqlEventStoreDbFileOrServerOrConnection";
26 :
27 : internal const string SqlEventStoreConnectionNameApplicationKey = @"Cqrs.SqlEventStore.ConnectionStringName";
28 :
29 : internal const string OldSqlEventStoreGetByCorrelationIdCommandTimeout = @"SqlEventStoreGetByCorrelationIdCommandTimeout";
30 :
31 : internal const string SqlEventStoreGetByCorrelationIdCommandTimeout = @"Cqrs.SqlEventStore.GetByCorrelationId.CommandTimeout";
32 :
33 : protected IConfigurationManager ConfigurationManager { get; private set; }
34 :
35 0 : public SqlEventStore(IEventBuilder<TAuthenticationToken> eventBuilder, IEventDeserialiser<TAuthenticationToken> eventDeserialiser, ILogger logger, IConfigurationManager configurationManager)
36 : : base(eventBuilder, eventDeserialiser, logger)
37 : {
38 : ConfigurationManager = configurationManager;
39 : }
40 :
41 : #region Overrides of EventStore<TAuthenticationToken>
42 :
43 0 : public override IEnumerable<IEvent<TAuthenticationToken>> Get(Type aggregateRootType, Guid aggregateId, bool useLastEventOnly = false, int fromVersion = -1)
44 : {
45 : string streamName = string.Format(CqrsEventStoreStreamNamePattern, aggregateRootType.FullName, aggregateId);
46 :
47 : using (DataContext dbDataContext = CreateDbDataContext())
48 : {
49 : IEnumerable<EventData> query = GetEventStoreTable(dbDataContext)
50 : .AsQueryable()
51 : .Where(eventData => eventData.AggregateId == streamName && eventData.Version > fromVersion)
52 : .OrderByDescending(eventData => eventData.Version);
53 :
54 : if (useLastEventOnly)
55 : query = query.AsQueryable().Take(1);
56 :
57 : return query
58 : .Select(EventDeserialiser.Deserialise)
59 : .ToList();
60 : }
61 : }
62 :
63 0 : public override IEnumerable<EventData> Get(Guid correlationId)
64 : {
65 : using (DataContext dbDataContext = CreateDbDataContext())
66 : {
67 : string commandTimeoutValue;
68 : int commandTimeout;
69 : bool found = ConfigurationManager.TryGetSetting(SqlEventStoreGetByCorrelationIdCommandTimeout, out commandTimeoutValue);
70 : if (!found)
71 : found = ConfigurationManager.TryGetSetting(OldSqlEventStoreGetByCorrelationIdCommandTimeout, out commandTimeoutValue);
72 : if (found && int.TryParse(commandTimeoutValue, out commandTimeout))
73 : dbDataContext.CommandTimeout = commandTimeout;
74 :
75 : IEnumerable<EventData> query = GetEventStoreTable(dbDataContext)
76 : .AsQueryable()
77 : .Where(eventData => eventData.CorrelationId == correlationId)
78 : .OrderBy(eventData => eventData.Timestamp);
79 :
80 : return query.ToList();
81 : }
82 : }
83 :
84 0 : protected override void PersistEvent(EventData eventData)
85 : {
86 : using (DataContext dbDataContext = CreateDbDataContext())
87 : {
88 : Add(dbDataContext, eventData);
89 : }
90 : }
91 :
92 : #endregion
93 :
94 0 : protected virtual DataContext CreateDbDataContext()
95 : {
96 : string connectionStringKey;
97 : string applicationKey;
98 : if (!ConfigurationManager.TryGetSetting(SqlEventStoreConnectionNameApplicationKey, out applicationKey) || string.IsNullOrEmpty(applicationKey))
99 : {
100 : if (!ConfigurationManager.TryGetSetting(SqlEventStoreDbFileOrServerOrConnectionApplicationKey, out connectionStringKey) || string.IsNullOrEmpty(connectionStringKey))
101 : {
102 : if (!ConfigurationManager.TryGetSetting(SqlDataStore<Entity>.SqlDataStoreDbFileOrServerOrConnectionApplicationKey, out connectionStringKey) || string.IsNullOrEmpty(connectionStringKey))
103 : {
104 : throw new NullReferenceException(string.Format("No application setting named '{0}' was found in the configuration file with the name of a connection string to look for.", SqlEventStoreConnectionNameApplicationKey));
105 : }
106 : }
107 : }
108 : else
109 : {
110 : try
111 : {
112 : connectionStringKey = System.Configuration.ConfigurationManager.ConnectionStrings[applicationKey].ConnectionString;
113 : }
114 : catch (NullReferenceException exception)
115 : {
116 : throw new NullReferenceException(string.Format("No connection string setting named '{0}' was found in the configuration file with the SQL Event Store connection string.", applicationKey), exception);
117 : }
118 : }
119 : return new DataContext(connectionStringKey);
120 : }
121 :
122 0 : protected virtual Table<EventData> GetEventStoreTable(DataContext dbDataContext)
123 : {
124 : // Get a typed table to run queries.
125 : return dbDataContext.GetTable<EventData>();
126 : }
127 :
128 0 : protected virtual void Add(DataContext dbDataContext, EventData data)
129 : {
130 : Logger.LogDebug("Adding data to the SQL eventstore database", "SqlEventStore\\Add");
131 : try
132 : {
133 : DateTime start = DateTime.Now;
134 : GetEventStoreTable(dbDataContext).InsertOnSubmit(data);
135 : dbDataContext.SubmitChanges();
136 : DateTime end = DateTime.Now;
137 : Logger.LogDebug(string.Format("Adding data in the SQL eventstore database took {0}.", end - start), "SqlEventStore\\Add");
138 : }
139 : catch (Exception exception)
140 : {
141 : Logger.LogError("There was an issue persisting data to the SQL event store.", exception: exception);
142 : throw;
143 : }
144 : finally
145 : {
146 : Logger.LogDebug("Adding data to the SQL eventstore database... Done", "SqlEventStore\\Add");
147 : }
148 : }
149 : }
150 : }
|