Datei: NDODLL/Cache.cs

Last Commit (10db6e2)
1 //
2 // Copyright (c) 2002-2016 Mirko Matytschak
3 // (www.netdataobjects.de)
4 //
5 // Author: Mirko Matytschak
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10 // Software, and to permit persons to whom the Software is furnished to do so, subject to the following
11 // conditions:
12
13 // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 // of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22 #pragma warning disable 1591
23
24 using System;
25 using System.Linq;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Data;
29 using System.Diagnostics;
30 using NDO.Mapping;
31 using NDO.ShortId;
32
33 namespace NDO
34 {
35 ····/// <summary>
36 ····/// This is a cache of persistent objects. While the object is not part of a transaction, only a weak reference is held.
37 ····/// While the object is part of a transaction, a strong reference is held.
38 ····/// </summary>
39 #if !DEBUG
40 ····internal class Cache
41 #else
42 ····public class Cache
43 #endif
44 ····{
45 ········/// <summary>
46 ········/// Because all entries are put in a hash table, we use a class instead of a struct (which would be boxed anyway)
47 ········/// </summary>
48 #if !DEBUG
49 ········internal class Entry
50 #else
51 ········public class Entry
52 #endif
53 ········{
54 ············public IPersistenceCapable pc;
55 ············public DataRow row;
56 ············public List<KeyValuePair<Relation, object>> relations;
57
58 ············public Entry( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
59 ············{
60 ················this.pc = pc;
61 ················this.row = row;
62 ················this.relations = relations;
63 ············}
64 ········}
65
66 ········private Dictionary<ObjectId, Entry> lockedObjects = new Dictionary<ObjectId, Entry>( 100 );
67 ········private Dictionary<ObjectId, WeakReference<IPersistenceCapable>> objects = new Dictionary<ObjectId, WeakReference<IPersistenceCapable>>( 100 );
68
69 ········/// <summary>
70 ········/// Defaul Constructor
71 ········/// </summary>
72 ········public Cache()
73 ········{
74 ········}
75
76 ········public bool IsRegistered( IPersistenceCapable pc )
77 ········{
78 ············if (pc.NDOObjectId == null)
79 ················throw new InternalException( 60, "Cache.IsRegistered: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
80 ············return objects.ContainsKey( pc.NDOObjectId ) || lockedObjects.ContainsKey( pc.NDOObjectId );
81 ········}
82
83 ········/// <summary>
84 ········/// Register an object
85 ········/// </summary>
86 ········/// <param name="pc">The Object</param>
87 ········public void Register( IPersistenceCapable pc )
88 ········{
89 ············if (pc.NDOObjectId == null)
90 ················throw new InternalException( 60, "Cache.Register: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
91
92 ············if (!pc.NDOObjectId.IsValid())
93 ············{
94 ················throw new ArgumentException( "Cannot register object with invalid key: " + pc );
95 ············}
96
97 ············if (objects.ContainsKey( pc.NDOObjectId ) || lockedObjects.ContainsKey( pc.NDOObjectId ))
98 ············{
99 ················throw new ArgumentException( "Object already cached: " + pc.NDOObjectId, "pc" );
100 ············}
101 ············if (pc.NDOObjectState != NDO.NDOObjectState.Hollow && pc.NDOObjectState != NDO.NDOObjectState.Persistent && pc.NDOObjectState != NDO.NDOObjectState.Transient)
102 ············{
103 ················throw new ArgumentException( "Object in wrong state " + pc.NDOObjectId, "pc" );
104 ············}
105 ············objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
106 ········}
107
108 ········/// <summary>
109 ········/// Re-Register an object in the locked cache
110 ········/// </summary>
111 ········/// <param name="pc">The Object</param>
112 ········/// <param name="row">The data row, which holds the original state of the object</param>
113 ········/// <param name="relations">A list of all relations of the object.</param>········
114 ········public void RegisterLockedObject( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
115 ········{
116 ············if (pc.NDOObjectId == null)
117 ················throw new InternalException( 60, "Cache.RegisterLockedObject: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
118
119 ············if (!pc.NDOObjectId.IsValid())
120 ············{
121 ················throw new ArgumentException( "Cannot register object with invalid key: " + pc );
122 ············}
123
124 ············if (lockedObjects.ContainsKey( pc.NDOObjectId ))
125 ············{
126 ················throw new ArgumentException( "Object already cached: " + pc.NDOObjectId, "pc" );
127 ············}
128 ············Cache.Entry e = new Entry( pc, row, relations );
129 ············lockedObjects.Add( pc.NDOObjectId, e );
130 ········}
131
132
133 ········/// <summary>
134 ········/// Put an object in the cache; remove older versions of the object if existent
135 ········/// </summary>
136 ········/// <param name="pc">The object to put into the cache</param>
137 ········public void UpdateCache( IPersistenceCapable pc )
138 ········{
139 ············ObjectId oid = pc.NDOObjectId;
140 ············if (lockedObjects.ContainsKey( oid ))
141 ················return;
142 ············Debug.Assert( pc.NDOObjectState == NDOObjectState.Persistent || pc.NDOObjectState == NDOObjectState.Hollow );
143 ············WeakReference<IPersistenceCapable> objRef = null;
144 ············if (objects.TryGetValue( oid, out objRef ))
145 ············{
146 ················objRef.SetTarget( pc );
147 ············}
148 ············else
149 ············{
150 ················objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
151 ············}
152 ········}
153
154 ········/// <summary>
155 ········/// Remove an object from the cache
156 ········/// </summary>
157 ········/// <param name="pc">The object to remove</param>
158 ········public void Deregister( IPersistenceCapable pc )
159 ········{
160 ············if (pc.NDOObjectId == null)
161 ················throw new InternalException( 60, "Cache.Deregister: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
162
163 ············objects.Remove( pc.NDOObjectId );
164 ············lockedObjects.Remove( pc.NDOObjectId );
165 ········}
166
167 ········/// <summary>
168 ········/// Remove an object from the locked objects cache
169 ········/// </summary>
170 ········/// <param name="pc">The object to remove</param>
171 ········public void DeregisterLockedObject( IPersistenceCapable pc )
172 ········{
173 ············if (pc.NDOObjectId == null)
174 ················throw new InternalException( 60, "Cache.DeregisterLockedObject: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
175 ············lockedObjects.Remove( pc.NDOObjectId );
176 ········}
177
178 ········/// <summary>
179 ········/// Unload all unused objects, i.e., those that lost their weak reference.
180 ········/// </summary>
181 ········public void Cleanup()
182 ········{
183 ············IPersistenceCapable target; // dummy
184 ············List<ObjectId> unusedObjects = new List<ObjectId>();
185 ············foreach (var e in objects)
186 ············{
187 ················if (!e.Value.TryGetTarget( out target ))
188 ················{
189 ····················unusedObjects.Add( e.Key );
190 ················}
191 ············}
192 ············foreach (var key in unusedObjects)
193 ············{
194 ················objects.Remove( key );
195 ············}
196 ············//············Debug.WriteLine("Cache unloaded " + unusedObjects.Count + " unused objects");
197 ········}
198
199 ········/// <summary>
200 ········/// Unload all inactive objects.
201 ········/// </summary>
202 ········public void Unload()
203 ········{
204 ············//············Debug.WriteLine("Cache unloaded " + objects.Count + " objects");
205 ············lockedObjects.Clear();
206 ············objects.Clear();
207 ········}
208
209 ········/// <summary>
210 ········/// Retrieve an object in the cache
211 ········/// </summary>
212 ········/// <param name="id">Object ID of the object</param>
213 ········/// <returns></returns>
214 ········public IPersistenceCapable GetObject( ObjectId id )
215 ········{
216 ············Entry e = null;
217 ············lockedObjects.TryGetValue( id, out e );
218 ············IPersistenceCapable pc = e?.pc;
219 ············if (pc == null)
220 ············{
221 ················WeakReference<IPersistenceCapable> objRef = null;
222 ················objects.TryGetValue( id, out objRef );
223 ················if (objRef == null || !objRef.TryGetTarget( out pc ))
224 ················{
225 ····················objects.Remove( id );
226 ················}
227 ············}
228 ············return pc;
229 ········}
230
231 ········/// <summary>
232 ········/// Retrieve a DataRow related to an object
233 ········/// </summary>
234 ········/// <param name="pc"></param>
235 ········/// <returns></returns>
236 ········public DataRow GetDataRow( IPersistenceCapable pc )
237 ········{
238 ············if (pc.NDOObjectId == null)
239 ················throw new InternalException( 60, "Cache.GetDataRow: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
240 ············Entry e = null;
241 ············lockedObjects.TryGetValue( pc.NDOObjectId, out e );
242 ············return e?.row;
243 ········}
244
245 ········/// <summary>
246 ········/// Lock an object for use in a transaction; store the relatetd DataRow
247 ········/// </summary>
248 ········/// <param name="pc">The object to lock</param>
249 ········/// <param name="row">The DataRow</param>
250 ········/// <param name="relations">Relation info for the Object</param>
251 ········public void Lock( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
252 ········{
253 ············if (pc.NDOObjectId == null)
254 ················throw new InternalException( 60, "Cache.Lock: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
255 ············objects.Remove( pc.NDOObjectId );
256 ············lockedObjects.Add( pc.NDOObjectId, new Entry( pc, row, relations ) );
257 ········}
258
259 ········Entry GetEntry(IPersistenceCapable pc)
260 ········{
261 ············if (pc.NDOObjectId == null)
262 ················throw new InternalException( 60, "Cache.GetEntry: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
263 ············Entry e = null;
264 ············lockedObjects.TryGetValue( pc.NDOObjectId, out e );
265 ············return e;
266 ········}
267
268
269 ········/// <summary>
270 ········/// Unlock an object
271 ········/// </summary>
272 ········/// <param name="pc">The object to unlock</param>
273 ········public void Unlock( IPersistenceCapable pc )
274 ········{
275 ············Entry e = GetEntry(pc);
276 ············lockedObjects.Remove( pc.NDOObjectId );
277 ············objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
278 ········}
279
280 ········/// <summary>
281 ········/// Returns all locked objects
282 ········/// </summary>
283 ········public ICollection<Entry> LockedObjects
284 ········{
285 ············get { return lockedObjects.Values; }
286 ········}
287
288
289 ········/// <summary>
290 ········/// Returns all known objects
291 ········/// </summary>
292 ········public List<IPersistenceCapable> AllObjects
293 ········{
294 ············get
295 ············{
296 ················Cleanup();
297 ················List<IPersistenceCapable> al = new List<IPersistenceCapable>( this.lockedObjects.Count + this.objects.Count );
298
299 ················foreach (var de in this.lockedObjects)
300 ················{
301 ····················Cache.Entry ce = de.Value;
302 ····················if (ce.row.RowState != DataRowState.Deleted)
303 ························al.Add( ce.pc );
304 ················}
305
306 ················foreach (var de in this.objects)
307 ················{
308 ····················var weakReference = de.Value;
309 ····················if (weakReference != null)
310 ····················{
311 ························IPersistenceCapable pc;
312 ························if (weakReference.TryGetTarget( out pc ))
313 ····························al.Add( pc );
314 ····················}
315 ················}
316 ················return al;
317 ············}
318 ········}
319
320 ········/// <summary>
321 ········/// Check if object is locked
322 ········/// </summary>
323 ········/// <param name="pc">Object to check</param>
324 ········/// <returns>True if object is in the LockedObjects Collection</returns>
325 ········public bool IsLocked( IPersistenceCapable pc )
326 ········{
327 ············if (pc.NDOObjectId == null)
328 ················throw new InternalException( 60, "Cache.IsLocked: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
329 ············return lockedObjects.ContainsKey( pc.NDOObjectId );
330 ········}
331
332 ········/// <summary>
333 ········/// Returns all objects which are not locked
334 ········/// </summary>
335 ········public IEnumerable<IPersistenceCapable> UnlockedObjects
336 ········{
337 ············get
338 ············{
339 ················IPersistenceCapable pc = null;
340 ················foreach (var wr in objects.Values)
341 ················{
342 ····················if (wr.TryGetTarget( out pc ))
343 ························yield return pc;
344 ················}
345 ············}
346 ········}
347
348 ········/// <summary>
349 ········/// Unlock all locked objects
350 ········/// </summary>
351 ········public void UnlockAll()
352 ········{
353 ············foreach (Entry e in lockedObjects.Values)
354 ············{
355 objects. Add( e. pc. NDOObjectId, new WeakReference<IPersistenceCapable>( e. pc ) ) ;
 
 
356 ················if (e.relations != null)
357 ················{
358 ····················// support GC
359 ····················e.relations.Clear();
360 ····················e.relations = null;
361 ················}
362 ············}
363
364 ············lockedObjects.Clear();
365 ········}
366 ····}
367 }
368
369 #pragma warning restore 1591
New Commit (8c50417)
1 //
2 // Copyright (c) 2002-2016 Mirko Matytschak
3 // (www.netdataobjects.de)
4 //
5 // Author: Mirko Matytschak
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10 // Software, and to permit persons to whom the Software is furnished to do so, subject to the following
11 // conditions:
12
13 // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 // of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22 #pragma warning disable 1591
23
24 using System;
25 using System.Linq;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Data;
29 using System.Diagnostics;
30 using NDO.Mapping;
31 using NDO.ShortId;
32
33 namespace NDO
34 {
35 ····/// <summary>
36 ····/// This is a cache of persistent objects. While the object is not part of a transaction, only a weak reference is held.
37 ····/// While the object is part of a transaction, a strong reference is held.
38 ····/// </summary>
39 #if !DEBUG
40 ····internal class Cache
41 #else
42 ····public class Cache
43 #endif
44 ····{
45 ········/// <summary>
46 ········/// Because all entries are put in a hash table, we use a class instead of a struct (which would be boxed anyway)
47 ········/// </summary>
48 #if !DEBUG
49 ········internal class Entry
50 #else
51 ········public class Entry
52 #endif
53 ········{
54 ············public IPersistenceCapable pc;
55 ············public DataRow row;
56 ············public List<KeyValuePair<Relation, object>> relations;
57
58 ············public Entry( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
59 ············{
60 ················this.pc = pc;
61 ················this.row = row;
62 ················this.relations = relations;
63 ············}
64 ········}
65
66 ········private Dictionary<ObjectId, Entry> lockedObjects = new Dictionary<ObjectId, Entry>( 100 );
67 ········private Dictionary<ObjectId, WeakReference<IPersistenceCapable>> objects = new Dictionary<ObjectId, WeakReference<IPersistenceCapable>>( 100 );
68
69 ········/// <summary>
70 ········/// Defaul Constructor
71 ········/// </summary>
72 ········public Cache()
73 ········{
74 ········}
75
76 ········public bool IsRegistered( IPersistenceCapable pc )
77 ········{
78 ············if (pc.NDOObjectId == null)
79 ················throw new InternalException( 60, "Cache.IsRegistered: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
80 ············return objects.ContainsKey( pc.NDOObjectId ) || lockedObjects.ContainsKey( pc.NDOObjectId );
81 ········}
82
83 ········/// <summary>
84 ········/// Register an object
85 ········/// </summary>
86 ········/// <param name="pc">The Object</param>
87 ········public void Register( IPersistenceCapable pc )
88 ········{
89 ············if (pc.NDOObjectId == null)
90 ················throw new InternalException( 60, "Cache.Register: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
91
92 ············if (!pc.NDOObjectId.IsValid())
93 ············{
94 ················throw new ArgumentException( "Cannot register object with invalid key: " + pc );
95 ············}
96
97 ············if (objects.ContainsKey( pc.NDOObjectId ) || lockedObjects.ContainsKey( pc.NDOObjectId ))
98 ············{
99 ················throw new ArgumentException( "Object already cached: " + pc.NDOObjectId, "pc" );
100 ············}
101 ············if (pc.NDOObjectState != NDO.NDOObjectState.Hollow && pc.NDOObjectState != NDO.NDOObjectState.Persistent && pc.NDOObjectState != NDO.NDOObjectState.Transient)
102 ············{
103 ················throw new ArgumentException( "Object in wrong state " + pc.NDOObjectId, "pc" );
104 ············}
105 ············objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
106 ········}
107
108 ········/// <summary>
109 ········/// Re-Register an object in the locked cache
110 ········/// </summary>
111 ········/// <param name="pc">The Object</param>
112 ········/// <param name="row">The data row, which holds the original state of the object</param>
113 ········/// <param name="relations">A list of all relations of the object.</param>········
114 ········public void RegisterLockedObject( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
115 ········{
116 ············if (pc.NDOObjectId == null)
117 ················throw new InternalException( 60, "Cache.RegisterLockedObject: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
118
119 ············if (!pc.NDOObjectId.IsValid())
120 ············{
121 ················throw new ArgumentException( "Cannot register object with invalid key: " + pc );
122 ············}
123
124 ············if (lockedObjects.ContainsKey( pc.NDOObjectId ))
125 ············{
126 ················throw new ArgumentException( "Object already cached: " + pc.NDOObjectId, "pc" );
127 ············}
128 ············Cache.Entry e = new Entry( pc, row, relations );
129 ············lockedObjects.Add( pc.NDOObjectId, e );
130 ········}
131
132
133 ········/// <summary>
134 ········/// Put an object in the cache; remove older versions of the object if existent
135 ········/// </summary>
136 ········/// <param name="pc">The object to put into the cache</param>
137 ········public void UpdateCache( IPersistenceCapable pc )
138 ········{
139 ············ObjectId oid = pc.NDOObjectId;
140 ············if (lockedObjects.ContainsKey( oid ))
141 ················return;
142 ············Debug.Assert( pc.NDOObjectState == NDOObjectState.Persistent || pc.NDOObjectState == NDOObjectState.Hollow );
143 ············WeakReference<IPersistenceCapable> objRef = null;
144 ············if (objects.TryGetValue( oid, out objRef ))
145 ············{
146 ················objRef.SetTarget( pc );
147 ············}
148 ············else
149 ············{
150 ················objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
151 ············}
152 ········}
153
154 ········/// <summary>
155 ········/// Remove an object from the cache
156 ········/// </summary>
157 ········/// <param name="pc">The object to remove</param>
158 ········public void Deregister( IPersistenceCapable pc )
159 ········{
160 ············if (pc.NDOObjectId == null)
161 ················throw new InternalException( 60, "Cache.Deregister: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
162
163 ············objects.Remove( pc.NDOObjectId );
164 ············lockedObjects.Remove( pc.NDOObjectId );
165 ········}
166
167 ········/// <summary>
168 ········/// Remove an object from the locked objects cache
169 ········/// </summary>
170 ········/// <param name="pc">The object to remove</param>
171 ········public void DeregisterLockedObject( IPersistenceCapable pc )
172 ········{
173 ············if (pc.NDOObjectId == null)
174 ················throw new InternalException( 60, "Cache.DeregisterLockedObject: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
175 ············lockedObjects.Remove( pc.NDOObjectId );
176 ········}
177
178 ········/// <summary>
179 ········/// Unload all unused objects, i.e., those that lost their weak reference.
180 ········/// </summary>
181 ········public void Cleanup()
182 ········{
183 ············IPersistenceCapable target; // dummy
184 ············List<ObjectId> unusedObjects = new List<ObjectId>();
185 ············foreach (var e in objects)
186 ············{
187 ················if (!e.Value.TryGetTarget( out target ))
188 ················{
189 ····················unusedObjects.Add( e.Key );
190 ················}
191 ············}
192 ············foreach (var key in unusedObjects)
193 ············{
194 ················objects.Remove( key );
195 ············}
196 ············//············Debug.WriteLine("Cache unloaded " + unusedObjects.Count + " unused objects");
197 ········}
198
199 ········/// <summary>
200 ········/// Unload all inactive objects.
201 ········/// </summary>
202 ········public void Unload()
203 ········{
204 ············//············Debug.WriteLine("Cache unloaded " + objects.Count + " objects");
205 ············lockedObjects.Clear();
206 ············objects.Clear();
207 ········}
208
209 ········/// <summary>
210 ········/// Retrieve an object in the cache
211 ········/// </summary>
212 ········/// <param name="id">Object ID of the object</param>
213 ········/// <returns></returns>
214 ········public IPersistenceCapable GetObject( ObjectId id )
215 ········{
216 ············Entry e = null;
217 ············lockedObjects.TryGetValue( id, out e );
218 ············IPersistenceCapable pc = e?.pc;
219 ············if (pc == null)
220 ············{
221 ················WeakReference<IPersistenceCapable> objRef = null;
222 ················objects.TryGetValue( id, out objRef );
223 ················if (objRef == null || !objRef.TryGetTarget( out pc ))
224 ················{
225 ····················objects.Remove( id );
226 ················}
227 ············}
228 ············return pc;
229 ········}
230
231 ········/// <summary>
232 ········/// Retrieve a DataRow related to an object
233 ········/// </summary>
234 ········/// <param name="pc"></param>
235 ········/// <returns></returns>
236 ········public DataRow GetDataRow( IPersistenceCapable pc )
237 ········{
238 ············if (pc.NDOObjectId == null)
239 ················throw new InternalException( 60, "Cache.GetDataRow: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
240 ············Entry e = null;
241 ············lockedObjects.TryGetValue( pc.NDOObjectId, out e );
242 ············return e?.row;
243 ········}
244
245 ········/// <summary>
246 ········/// Lock an object for use in a transaction; store the relatetd DataRow
247 ········/// </summary>
248 ········/// <param name="pc">The object to lock</param>
249 ········/// <param name="row">The DataRow</param>
250 ········/// <param name="relations">Relation info for the Object</param>
251 ········public void Lock( IPersistenceCapable pc, DataRow row, List<KeyValuePair<Relation, object>> relations )
252 ········{
253 ············if (pc.NDOObjectId == null)
254 ················throw new InternalException( 60, "Cache.Lock: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
255 ············objects.Remove( pc.NDOObjectId );
256 ············lockedObjects.Add( pc.NDOObjectId, new Entry( pc, row, relations ) );
257 ········}
258
259 ········Entry GetEntry(IPersistenceCapable pc)
260 ········{
261 ············if (pc.NDOObjectId == null)
262 ················throw new InternalException( 60, "Cache.GetEntry: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
263 ············Entry e = null;
264 ············lockedObjects.TryGetValue( pc.NDOObjectId, out e );
265 ············return e;
266 ········}
267
268
269 ········/// <summary>
270 ········/// Unlock an object
271 ········/// </summary>
272 ········/// <param name="pc">The object to unlock</param>
273 ········public void Unlock( IPersistenceCapable pc )
274 ········{
275 ············Entry e = GetEntry(pc);
276 ············lockedObjects.Remove( pc.NDOObjectId );
277 ············objects.Add( pc.NDOObjectId, new WeakReference<IPersistenceCapable>( pc ) );
278 ········}
279
280 ········/// <summary>
281 ········/// Returns all locked objects
282 ········/// </summary>
283 ········public ICollection<Entry> LockedObjects
284 ········{
285 ············get { return lockedObjects.Values; }
286 ········}
287
288
289 ········/// <summary>
290 ········/// Returns all known objects
291 ········/// </summary>
292 ········public List<IPersistenceCapable> AllObjects
293 ········{
294 ············get
295 ············{
296 ················Cleanup();
297 ················List<IPersistenceCapable> al = new List<IPersistenceCapable>( this.lockedObjects.Count + this.objects.Count );
298
299 ················foreach (var de in this.lockedObjects)
300 ················{
301 ····················Cache.Entry ce = de.Value;
302 ····················if (ce.row.RowState != DataRowState.Deleted)
303 ························al.Add( ce.pc );
304 ················}
305
306 ················foreach (var de in this.objects)
307 ················{
308 ····················var weakReference = de.Value;
309 ····················if (weakReference != null)
310 ····················{
311 ························IPersistenceCapable pc;
312 ························if (weakReference.TryGetTarget( out pc ))
313 ····························al.Add( pc );
314 ····················}
315 ················}
316 ················return al;
317 ············}
318 ········}
319
320 ········/// <summary>
321 ········/// Check if object is locked
322 ········/// </summary>
323 ········/// <param name="pc">Object to check</param>
324 ········/// <returns>True if object is in the LockedObjects Collection</returns>
325 ········public bool IsLocked( IPersistenceCapable pc )
326 ········{
327 ············if (pc.NDOObjectId == null)
328 ················throw new InternalException( 60, "Cache.IsLocked: ObjectId of an object of type " + pc.GetType().FullName + " is null." );
329 ············return lockedObjects.ContainsKey( pc.NDOObjectId );
330 ········}
331
332 ········/// <summary>
333 ········/// Returns all objects which are not locked
334 ········/// </summary>
335 ········public IEnumerable<IPersistenceCapable> UnlockedObjects
336 ········{
337 ············get
338 ············{
339 ················IPersistenceCapable pc = null;
340 ················foreach (var wr in objects.Values)
341 ················{
342 ····················if (wr.TryGetTarget( out pc ))
343 ························yield return pc;
344 ················}
345 ············}
346 ········}
347
348 ········/// <summary>
349 ········/// Unlock all locked objects
350 ········/// </summary>
351 ········public void UnlockAll()
352 ········{
353 ············foreach (Entry e in lockedObjects.Values)
354 ············{
355 var oid = e. pc. NDOObjectId;
356 ················if (!objects.ContainsKey( oid ))
357 ····················objects.Add( oid, new WeakReference<IPersistenceCapable>( e.pc ) );
358 ················if (e.relations != null)
359 ················{
360 ····················// support GC
361 ····················e.relations.Clear();
362 ····················e.relations = null;
363 ················}
364 ············}
365
366 ············lockedObjects.Clear();
367 ········}
368 ····}
369 }
370
371 #pragma warning restore 1591