| 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 |