1 | #Region "Microsoft.VisualBasic::9e7f515b80a02b0b1bc642658705dc0a, Microsoft.VisualBasic.Core\ComponentModel\DataSource\Repository\Repository.vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Interface IKeyedEntity |
35 | ' |
36 | ' Properties: Key |
37 | ' |
38 | ' Class ClientRecord |
39 | ' |
40 | ' Properties: ClientUniqueKey, Code |
41 | ' |
42 | ' Interface IRepositoryRead |
43 | ' |
44 | ' Function: Exists, GetAll, GetByKey, GetWhere |
45 | ' |
46 | ' Interface IRepositoryWrite |
47 | ' |
48 | ' Function: AddNew |
49 | ' |
50 | ' Sub: AddOrUpdate, Delete |
51 | ' |
52 | ' Interface IRepository |
53 | ' |
54 | ' |
55 | ' |
56 | ' Interface IClientRepository |
57 | ' |
58 | ' |
59 | ' |
60 | ' Class RepositoryReadException |
61 | ' |
62 | ' Properties: Fatal |
63 | ' |
64 | ' Constructor: (+2 Overloads) Sub New |
65 | ' |
66 | ' |
67 | ' /********************************************************************************/ |
68 | |
69 | #End Region |
70 | |
71 | Namespace ComponentModel.DataSourceModel.Repository |
72 | |
73 | ' http://www.codeproject.com/Reference/731015/The-repository-pattern-in-VB-Net |
74 | |
75 | ' The repository pattern (in VB.Net) |
76 | |
77 | ' Background |
78 | ' The repository pattern Is a method To introduce a shearing layer between your business objects And |
79 | ' the data access/persistence technology you are Using And this especially useful In unit testing As |
80 | ' the alternative(mocking an entire data access library) can be quite heart breaking. |
81 | |
82 | ' Motivation |
83 | ' The repository pattern introduces the following advantages over the traditional three-tier architecture over an ORM: |
84 | |
85 | ' 1. The classes persisted by an ORM (Entity framework Or the Like) need To have a good deal Of information about how they are stored. |
86 | ' This Is Not ideal because When you make a change To the underlying storage you would need To change the business objects As well. |
87 | ' 2. Not all persistence Is in the form of a relational database - the repository can be backed by a blended storage made of files, |
88 | ' database tables And NoSQL records As well. |
89 | ' 3. Some fields exist only In order To allow navigation To a record Or To identify child records - these fields should Not |
90 | ' be passed up into the business layer If they have no business meaning. |
91 | |
92 | ''' <summary> |
93 | ''' Interface defining any item we can store in a repository and can identify by |
94 | ''' an unique key |
95 | ''' </summary> |
96 | ''' <remarks> |
97 | ''' This interface is typed so we can make type-safe code for retrieving the entity |
98 | ''' (don't pass in an integer if the entity is keyed by string etc.) |
99 | ''' </remarks> |
100 | Public Interface IKeyedEntity(Of TKeyType) |
101 | |
102 | ''' <summary> |
103 | ''' Get the key to find the entity by |
104 | ''' </summary> |
105 | Property Key As TKeyType |
106 | |
107 | End Interface |
108 | |
109 | ''' <summary> |
110 | ''' Record for storing a client record in the common database |
111 | ''' </summary> |
112 | Public NotInheritable Class ClientRecord |
113 | Implements IKeyedEntity(Of Integer) |
114 | |
115 | ''' <summary> |
116 | ''' The unique number by which we know this client |
117 | ''' </summary> |
118 | ''' <remarks> |
119 | ''' Every client has an unique id but this is not needed publically |
120 | ''' </remarks> |
121 | Public Property ClientUniqueKey As Integer Implements IKeyedEntity(Of Integer).Key |
122 | |
123 | ' Other non-key properties can go here |
124 | ''' <summary> |
125 | ''' The short code for the client |
126 | ''' </summary> |
127 | ''' <remarks> |
128 | ''' e.g. MCL for Merrion Computing Ltd etc. |
129 | ''' </remarks> |
130 | Public Property Code As String |
131 | End Class |
132 | |
133 | ''' <summary> |
134 | ''' Interface to support reading entities from the backing store |
135 | ''' </summary> |
136 | ''' <typeparam name="TEntity"> |
137 | ''' The key-identified type of entity we are reading |
138 | ''' </typeparam> |
139 | ''' <typeparam name="TKey"> |
140 | ''' The type of the key |
141 | ''' </typeparam> |
142 | ''' <remarks> |
143 | ''' In this architecture there is a seperate read and write interface but often this |
144 | ''' pattern has just the one interface for both functions |
145 | ''' </remarks> |
146 | Public Interface IRepositoryRead(Of TKey, TEntity As IKeyedEntity(Of TKey)) |
147 | |
148 | ''' <summary> |
149 | ''' Does a record exist in the repository identified by this key |
150 | ''' </summary> |
151 | ''' <param name="key"> |
152 | ''' The unique identifier of the entity we are looking for |
153 | ''' </param> |
154 | Function Exists(key As TKey) As Boolean |
155 | |
156 | ''' <summary> |
157 | ''' Get the entity uniquely identified by the given key |
158 | ''' </summary> |
159 | ''' <param name="key"> |
160 | ''' The unique identifier to use to get the entity |
161 | ''' </param> |
162 | Function GetByKey(key As TKey) As TEntity |
163 | |
164 | ''' <summary> |
165 | ''' Get a set of entities from the repository that match the where clause |
166 | ''' </summary> |
167 | ''' <param name="clause"> |
168 | ''' A function to apply to filter the results from the repository |
169 | ''' </param> |
170 | Function GetWhere(clause As Func(Of TEntity, Boolean)) As IReadOnlyDictionary(Of TKey, TEntity) |
171 | |
172 | ''' <summary> |
173 | ''' Get all of this type of thing from the repository |
174 | ''' </summary> |
175 | ''' <remarks> |
176 | ''' returns an IQueryable so this request can be filtered further |
177 | ''' </remarks> |
178 | Function GetAll() As IReadOnlyDictionary(Of TKey, TEntity) |
179 | |
180 | End Interface |
181 | |
182 | ''' <summary> |
183 | ''' Interface to support writing (and deletes) to a typed repository |
184 | ''' </summary> |
185 | ''' <typeparam name="TEntity"> |
186 | ''' The type of entity in the repository |
187 | ''' </typeparam> |
188 | ''' <typeparam name="TKey"> |
189 | ''' The type of the key to uniquely identify the entity |
190 | ''' </typeparam> |
191 | ''' <remarks> |
192 | ''' In this architecture there is a seperate read and write interface but often this |
193 | ''' pattern has just the one interface for both functions |
194 | ''' </remarks> |
195 | Public Interface IRepositoryWrite(Of TKey, TEntity As IKeyedEntity(Of TKey)) |
196 | |
197 | ''' <summary> |
198 | ''' Delete the entity uniquely identified by this key |
199 | ''' </summary> |
200 | ''' <param name="key"> |
201 | ''' The unique identifier of the record to delete |
202 | ''' </param> |
203 | Sub Delete(key As TKey) |
204 | |
205 | ''' <summary> |
206 | ''' Add or update the entity |
207 | ''' </summary> |
208 | ''' <param name="entity"> |
209 | ''' The record to add or update on the repository |
210 | ''' </param> |
211 | ''' <param name="key" > |
212 | ''' The key that uniquely identifies the record to add or update |
213 | ''' </param> |
214 | Sub AddOrUpdate(entity As TEntity, key As TKey) |
215 | |
216 | ''' <summary> |
217 | ''' Adds an entity that we know to be new and returns its assigned key |
218 | ''' </summary> |
219 | ''' <param name="entity"> |
220 | ''' The entity we are adding to the repository |
221 | ''' </param> |
222 | ''' <returns> |
223 | ''' The unique identifier for the entity |
224 | ''' </returns> |
225 | ''' <remarks> |
226 | ''' This is useful if the unique identifier is not an intrinsic property of |
227 | ''' the entity - for example if it is a memory address or a GUID |
228 | ''' </remarks> |
229 | Function AddNew(entity As TEntity) As TKey |
230 | |
231 | End Interface |
232 | |
233 | ''' <summary> |
234 | ''' Read/write repository of typed entites |
235 | ''' </summary> |
236 | ''' <typeparam name="TKey"> |
237 | ''' The type by which the entity is uniquely identified |
238 | ''' </typeparam> |
239 | ''' <typeparam name="TEntity"> |
240 | ''' The type of entity in the repository |
241 | ''' </typeparam> |
242 | Public Interface IRepository(Of TKey, TEntity As IKeyedEntity(Of TKey)) |
243 | Inherits IRepositoryRead(Of TKey, TEntity) |
244 | Inherits IRepositoryWrite(Of TKey, TEntity) |
245 | |
246 | End Interface |
247 | |
248 | Public Interface IClientRepository |
249 | Inherits IRepository(Of Integer, ClientRecord) |
250 | |
251 | End Interface |
252 | |
253 | ''' <summary> |
254 | ''' An exception that occured when reading from the repository backing store |
255 | ''' </summary> |
256 | ''' <remarks> |
257 | ''' The inner exception is from whatever |
258 | ''' </remarks> |
259 | Public Class RepositoryReadException |
260 | Inherits Exception |
261 | |
262 | Public ReadOnly Property Fatal As Boolean |
263 | |
264 | Public Sub New(message As String, innerExcption As Exception, fatalInit As Boolean) |
265 | MyBase.New(message, innerExcption) |
266 | Fatal = fatalInit |
267 | End Sub |
268 | |
269 | Public Sub New(message As String, fatalInit As Boolean) |
270 | MyBase.New(message) |
271 | Fatal = fatalInit |
272 | End Sub |
273 | End Class |
274 | End Namespace |