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.Linq;
12 : using System.Linq.Expressions;
13 : using cdmdotnet.Logging;
14 : using Cqrs.Configuration;
15 : using Cqrs.Entities;
16 : using Cqrs.DataStores;
17 : using Cqrs.Repositories.Queries;
18 :
19 : namespace Cqrs.Repositories
20 : {
21 : public abstract class Repository<TQueryStrategy, TQueryBuilder, TData> : IRepository<TQueryStrategy, TData>
22 : where TQueryStrategy : IQueryStrategy
23 : where TQueryBuilder : QueryBuilder<TQueryStrategy, TData>
24 : where TData : Entity
25 0 : {
26 : protected Func<IDataStore<TData>> CreateDataStoreFunction { get; private set; }
27 :
28 : protected TQueryBuilder QueryBuilder { get; private set; }
29 :
30 : protected ITelemetryHelper TelemetryHelper { get; set; }
31 :
32 0 : protected Repository(Func<IDataStore<TData>> createDataStoreFunction, TQueryBuilder queryBuilder)
33 : {
34 : CreateDataStoreFunction = createDataStoreFunction;
35 : QueryBuilder = queryBuilder;
36 : TelemetryHelper = new NullTelemetryHelper();
37 : }
38 :
39 : #region Implementation of IRepository<TData>
40 :
41 0 : public virtual void Create(TData data)
42 : {
43 : using (var dataStore = CreateDataStoreFunction())
44 : dataStore.Add(data);
45 : }
46 :
47 0 : public virtual void Create(IEnumerable<TData> data)
48 : {
49 : using (var dataStore = CreateDataStoreFunction())
50 : dataStore.Add(data);
51 : }
52 :
53 0 : public virtual ISingleResultQuery<TQueryStrategy, TData> Retrieve(ISingleResultQuery<TQueryStrategy, TData> singleResultQuery, bool throwExceptionWhenNoQueryResults = true)
54 : {
55 : // The .Select(i => i) is necessary due to inheritance
56 : // http://stackoverflow.com/questions/1021274/linq-to-sql-mapping-exception-when-using-abstract-base-classes
57 : IQueryable<TData> query = QueryBuilder.CreateQueryable(singleResultQuery).Select(i => i);
58 :
59 : IEnumerable<TData> result = query.AsEnumerable();
60 : int finalResultCount = 0;
61 : TData finalResult = throwExceptionWhenNoQueryResults
62 : ? result.Single()
63 : : result.SingleOrDefault();
64 : if (finalResult != null)
65 : finalResultCount = 1;
66 :
67 : try
68 : {
69 : return new SingleResultQuery<TQueryStrategy, TData>
70 : {
71 : QueryStrategy = singleResultQuery.QueryStrategy,
72 : Result = finalResult
73 : };
74 : }
75 : finally
76 : {
77 : TelemetryHelper.TrackMetric(string.Format("Cqrs/Repository/Retrieve/Single/{0}", typeof(TData).Name), finalResultCount);
78 :
79 : // This is disabled until I can figure out a better way to handle disposing these... as it will most likely dispose the data store... and that's not cool.
80 : /*
81 : var disposable = result as IDisposable;
82 : if (disposable != null)
83 : disposable.Dispose();
84 : */
85 : }
86 : }
87 :
88 0 : public virtual ICollectionResultQuery<TQueryStrategy, TData> Retrieve(ICollectionResultQuery<TQueryStrategy, TData> resultQuery)
89 : {
90 : // The .Select(i => i) is necessary due to inheritance
91 : // http://stackoverflow.com/questions/1021274/linq-to-sql-mapping-exception-when-using-abstract-base-classes
92 : IQueryable<TData> result = QueryBuilder.CreateQueryable(resultQuery).Select(i => i);
93 :
94 : IList<TData> finalResult = result.ToList();
95 :
96 : try
97 : {
98 : return new CollectionResultQuery<TQueryStrategy, TData>
99 : {
100 : QueryStrategy = resultQuery.QueryStrategy,
101 : Result = finalResult
102 : };
103 : }
104 : finally
105 : {
106 : TelemetryHelper.TrackMetric(string.Format("Cqrs/Repository/Retrieve/Collection/{0}", typeof(TData).Name), finalResult.Count);
107 : // This is disabled until I can figure out a better way to handle disposing these... as it will most likely dispose the data store... and that's not cool.
108 : /*
109 : var disposable = result as IDisposable;
110 : if (disposable != null)
111 : disposable.Dispose();
112 : */
113 : }
114 : }
115 :
116 0 : public virtual void Update(TData data)
117 : {
118 : using (var dataStore = CreateDataStoreFunction())
119 : dataStore.Update(data);
120 : }
121 :
122 : /// <summary>
123 : /// Will mark the <paramref name="data"/> as logically (or soft).
124 : /// </summary>
125 1 : public virtual void Delete(TData data)
126 : {
127 : using (var dataStore = CreateDataStoreFunction())
128 : dataStore.Remove(data);
129 : }
130 :
131 0 : public virtual void DeleteAll()
132 : {
133 : using (var dataStore = CreateDataStoreFunction())
134 : dataStore.RemoveAll();
135 : }
136 :
137 0 : public void Destroy(TData data)
138 : {
139 : using (var dataStore = CreateDataStoreFunction())
140 : dataStore.Destroy(data);
141 : }
142 :
143 0 : public virtual TData Load(Guid rsn, bool throwExceptionOnMissingEntity = true)
144 : {
145 : using (IDataStore<TData> dataStore = CreateDataStoreFunction())
146 : {
147 : IEnumerable<TData> query = dataStore
148 : // The .Select(i => i) is necessary due to inheritance
149 : // http://stackoverflow.com/questions/1021274/linq-to-sql-mapping-exception-when-using-abstract-base-classes
150 : .Select(i => i)
151 : .Where(entity => entity.Rsn == rsn)
152 : .AsEnumerable();
153 :
154 : int finalResultCount = 0;
155 : TData result = throwExceptionOnMissingEntity
156 : ? query.Single()
157 : : query.SingleOrDefault();
158 : if (result != null)
159 : finalResultCount = 1;
160 :
161 : try
162 : {
163 : return result;
164 : }
165 : finally
166 : {
167 : TelemetryHelper.TrackMetric(string.Format("Cqrs/Repository/Load/{0}", typeof(TData).Name), finalResultCount);
168 : }
169 : }
170 : }
171 :
172 : #endregion
173 :
174 0 : protected virtual IQueryable<TData> CreateQueryable(Expression<Func<TData, bool>> predicate)
175 : {
176 : return CreateDataStoreFunction().Where(predicate);
177 : }
178 : }
179 : }
|