Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections;
11 : using System.Collections.Generic;
12 : using System.Data;
13 : using System.Data.Linq;
14 : using System.Linq;
15 : using System.Linq.Expressions;
16 : using Cqrs.DataStores;
17 : using Cqrs.Entities;
18 :
19 : namespace Cqrs.Sql.DataStores
20 : {
21 : /// <summary>
22 : /// A <see cref="IDataStore{TData}"/> that uses EntityFramework to support complex data structures with SQL Server.s
23 : /// </summary>
24 : public class SqlDataStore<TEntity, TDbEntity> : IDataStore<TEntity>
25 : where TDbEntity : class, new()
26 1 : {
27 : /// <summary>
28 : /// Gets or sets the DataContext.
29 : /// </summary>
30 : internal DataContext DataContext { get; private set; }
31 :
32 : /// <summary>
33 : /// Gets or sets the readable Table
34 : /// </summary>
35 : internal Table<TDbEntity> DataTable { get; private set; }
36 :
37 : /// <summary>
38 : /// Gets or sets the EntityQuery
39 : /// </summary>
40 : internal IQueryable<TEntity> EntityQuery { get; private set; }
41 :
42 : /// <summary>
43 : /// Gets or sets the DbEntityQuery
44 : /// </summary>
45 : internal IQueryable<TDbEntity> DbEntityQuery { get; private set; }
46 :
47 : /// <summary>
48 : /// Gets or sets the ExpressionConverter
49 : /// </summary>
50 : internal IExpressionTreeConverter ExpressionConverter { get; set; }
51 :
52 : /// <summary>
53 : /// Instantiates a new instance of the <see cref="SqlDataStore{TEntity,TDbEntity}"/> class
54 : /// </summary>
55 1 : public SqlDataStore(IExpressionTreeConverter expressionConverter, DataContext dataContext)
56 : {
57 : ExpressionConverter = expressionConverter;
58 :
59 : DataContext = dataContext;
60 : DataTable = DataContext.GetTable<TDbEntity>();
61 : DbEntityQuery = DataTable;
62 : EntityQuery = new List<TEntity>().AsQueryable();
63 :
64 : switch (DataContext.Connection.State)
65 : {
66 : case ConnectionState.Closed:
67 : case ConnectionState.Broken:
68 : DataContext.Connection.Open();
69 : DataContext.Transaction = DataContext.Connection.BeginTransaction();
70 : break;
71 : }
72 : }
73 :
74 : /// <summary>
75 : /// Instantiates a new instance of the <see cref="SqlDataStore{TEntity,TDbEntity}"/> class
76 : /// </summary>
77 : internal SqlDataStore(DataContext dataContext, Table<TDbEntity> dataTable, IQueryable<TDbEntity> dbEntityQuery, IQueryable<TEntity> entityQuery)
78 : {
79 : DataContext = dataContext;
80 : DataTable = dataTable;
81 : DbEntityQuery = dbEntityQuery;
82 : EntityQuery = entityQuery;
83 : }
84 :
85 : #region Implementation of IEnumerable
86 :
87 : /// <summary>
88 : /// Returns an enumerator that iterates through the collection.
89 : /// </summary>
90 : /// <returns>
91 : /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
92 : /// </returns>
93 1 : public IEnumerator<TDbEntity> GetEnumerator()
94 : {
95 : return DataTable.GetEnumerator();
96 : }
97 :
98 : /// <summary>
99 : /// Returns an enumerator that iterates through the collection.
100 : /// </summary>
101 : /// <returns>
102 : /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
103 : /// </returns>
104 : IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()
105 : {
106 : return EntityQuery.GetEnumerator();
107 : }
108 :
109 : /// <summary>
110 : /// Returns an enumerator that iterates through a collection.
111 : /// </summary>
112 : /// <returns>
113 : /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
114 : /// </returns>
115 : IEnumerator IEnumerable.GetEnumerator()
116 : {
117 : return GetEnumerator();
118 : }
119 :
120 : #endregion
121 :
122 : #region Implementation of IQueryable
123 :
124 : /// <summary>
125 : /// Gets the expression tree that is associated with the instance of <see cref="T:System.Linq.IQueryable"/>.
126 : /// </summary>
127 : /// <returns>
128 : /// The <see cref="T:System.Linq.Expressions.Expression"/> that is associated with this instance of <see cref="T:System.Linq.IQueryable"/>.
129 : /// </returns>
130 : public Expression Expression
131 : {
132 : get { return EntityQuery.Expression; }
133 : }
134 :
135 : /// <summary>
136 : /// Gets the type of the element(s) that are returned when the expression tree associated with this instance of <see cref="T:System.Linq.IQueryable"/> is executed.
137 : /// </summary>
138 : /// <returns>
139 : /// A <see cref="T:System.Type"/> that represents the type of the element(s) that are returned when the expression tree associated with this object is executed.
140 : /// </returns>
141 : public Type ElementType
142 : {
143 : get { return EntityQuery.ElementType; }
144 : }
145 :
146 : /// <summary>
147 : /// Gets the query provider that is associated with this data source.
148 : /// </summary>
149 : /// <returns>
150 : /// The <see cref="T:System.Linq.IQueryProvider"/> that is associated with this data source.
151 : /// </returns>
152 : public IQueryProvider Provider
153 : {
154 : get { return EntityQuery.Provider; }
155 : }
156 :
157 : #endregion
158 :
159 : #region Implementation of IDataStore<T>
160 :
161 : /// <summary>
162 : /// Add the provided <paramref name="data"/> to the data store and persist the change.
163 : /// </summary>
164 1 : public void Add(TEntity data)
165 : {
166 : var converted = Converters.ConvertTo<TDbEntity>(data);
167 : DataTable.InsertOnSubmit(converted);
168 : }
169 :
170 : /// <summary>
171 : /// Add the provided <paramref name="data"/> to the data store and persist the change.
172 : /// </summary>
173 1 : public void Add(IEnumerable<TEntity> data)
174 : {
175 : DataTable.InsertAllOnSubmit(data.Select(x => Converters.ConvertTo<TDbEntity>(x)));
176 : }
177 :
178 : /// <summary>
179 : /// Will NOT mark the <paramref name="data"/> as logically (or soft) deleted. This will destroy and delete the row in the SQL Server.
180 : /// </summary>
181 1 : public void Remove(TEntity data)
182 : {
183 : Destroy(data);
184 : }
185 :
186 : /// <summary>
187 : /// Remove the provided <paramref name="data"/> (normally by <see cref="IEntity.Rsn"/>) from the data store and persist the change.
188 : /// </summary>
189 1 : public void Destroy(TEntity data)
190 : {
191 : var converted = Converters.ConvertTo<TDbEntity>(data);
192 : DataTable.DeleteOnSubmit(converted);
193 : }
194 :
195 : /// <summary>
196 : /// Remove all contents (normally by use of a truncate operation) from the data store and persist the change.
197 : /// </summary>
198 1 : public void RemoveAll()
199 : {
200 : IList<TDbEntity> all = DataTable.ToList();
201 : DataTable.DeleteAllOnSubmit(all);
202 : }
203 :
204 : /// <summary>
205 : /// Update the provided <paramref name="data"/> in the data store and persist the change.
206 : /// </summary>
207 1 : public void Update(TEntity data)
208 : {
209 : var converted = Converters.ConvertTo<TDbEntity>(data);
210 : DataTable.Attach(converted);
211 : }
212 :
213 : #endregion
214 :
215 : #region Implementation of IDisposable
216 :
217 : /// <summary>
218 : /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
219 : /// </summary>
220 1 : public void Dispose()
221 : {
222 : try
223 : {
224 : DataContext.SubmitChanges();
225 : DataContext.Transaction.Commit();
226 : }
227 : catch
228 : {
229 : DataContext.Transaction.Rollback();
230 : }
231 : finally
232 : {
233 : DataContext.Transaction.Dispose();
234 : DataContext.Dispose();
235 : }
236 : }
237 :
238 : #endregion
239 : }
240 : }
|