Datei: NDODLL/PersistenceManagerBase.cs

Last Commit (37b7958)
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
23 using System;
24 using System.Collections.Generic;
25 using System.Linq;
26 using System.IO;
27 using System.Data;
28 using NDO.Logging;
29 using NDO.Mapping;
30 using NDO.Configuration;
31 using NDO.SqlPersistenceHandling;
32 using System.Reflection;
33
34 namespace NDO
35 {
36 ····/// <summary>
37 ····/// Provides base functionality for PersistenceManager classes
38 ····/// </summary>
39 ····public class PersistenceManagerBase : IPersistenceManagerBase
40 ····{
41 ········internal Cache cache = new Cache();
42 ········/// <summary>
43 ········/// The DataSet used as template for DataRows
44 ········/// </summary>
45 ········protected DataSet ds = null;
46 ········/// <summary>
47 ········/// The StateManager instance which will be used for all objects
48 ········/// </summary>
49 ········protected IStateManager sm;
50 ········internal Mappings mappings;··// protected will make the compiler complaining
51 ········private string logPath;
52 ········private ILogAdapter logAdapter;
53 ········private Type persistenceHandlerType = null;
54 ········private INDOContainer configContainer;
55 ········private IPersistenceHandlerManager persistenceHandlerManager;
56 ········bool isClosing = false;
57
58 ········/// <summary>
59 ········/// Register a listener to this event, if you have to provide user generated ids.
60 ········/// This event is usefull for databases, which doesn't provide auto-incremented ids, like the Oracle Db.
61 ········/// The event will be fired if a new id is needed.
62 ········/// </summary>
63 ········public event IdGenerationHandler IdGenerationEvent;
64
65 ········/// <summary>
66 ········/// Constructor
67 ········/// </summary>
68 ········public PersistenceManagerBase()
69 ········{
70 ············string baseDir = AppDomain.CurrentDomain.BaseDirectory;
71 ············if (File.Exists( Path.Combine( baseDir, "Web.config" ) ))
72 ················baseDir = Path.Combine( baseDir, "bin" );
73 ············var entryAssemblyName = Assembly.GetEntryAssembly()?.GetName()?.Name;
74 ············List<string> paths = new List<string>();
75 ············if (entryAssemblyName != null)
76 ············paths.Add( Path.Combine( baseDir, $"{entryAssemblyName}.ndo.mapping" ) );
77 ············paths.Add( Path.Combine( baseDir, "NDOMapping.xml" ) );
78 ············
79 ············bool found = false;
80 ············foreach (var path in paths)
81 ············{
82 ················if (File.Exists(path))
83 ················{
84 ····················Init( path );
85 ····················found = true;
86 ····················break;
87 ················}
88 ············}
89 ············if (!found)
90 ················throw new NDOException( 49, $"Can't determine the path to the mapping file. Tried the following locations:\n{string.Join("\n", paths)}\nPlease provide a mapping file path as argument to the PersistenceManager ctor." );
91 ········}
92
93 ········/// <summary>
94 ········/// Constructs a PersistenceManagerBase object using the path to a mapping file.
95 ········/// </summary>
96 ········/// <param name="mappingFile"></param>
97 ········public PersistenceManagerBase(string mappingFile)
98 ········{
99 ············Init(mappingFile);
100 ········}
101
102 ········/// <summary>
103 ········/// Constructs a PersistenceManagerBase object using the mapping object.
104 ········/// </summary>
105 ········/// <param name="mapping"></param>
106 ········public PersistenceManagerBase(NDOMapping mapping)
107 ········{
108 ············var localMappings = mapping as Mappings;
109 ············if (localMappings == null)
110 ················throw new ArgumentException( "The mapping must be constructed by a PersistenceManager", nameof( mapping ) );
111
112 ············Init( localMappings );
113 ········}
114
115 ········/// <summary>
116 ········/// Initializes a PersistenceManager using the path to a mapping file
117 ········/// </summary>
118 ········/// <param name="mappingPath"></param>
119 ········protected virtual void Init(string mappingPath)
120 ········{
121 ············if (!File.Exists(mappingPath))
122 ················throw new NDOException(45, String.Format("Mapping File {0} doesn't exist.", mappingPath));
123 Init( new Mappings( mappingPath, ConfigContainer ) ) ;
124 ········}
125
126 ········/// <summary>
127 ········/// Initializes the persistence manager
128 ········/// </summary>
129 ········/// <remarks>
130 ········/// Note: This is the method, which will be called from all different ways to instantiate a PersistenceManagerBase.
131 ········/// </remarks>
132 ········/// <param name="mapping"></param>
133 ········internal virtual void Init( Mappings mapping )
134 ········{
135 ············this.mappings = mapping;
136
137 ············ConfigContainer.RegisterInstance( mappings );
138
139 ············this.ds = new NDODataSet( mappings );··// Each PersistenceManager instance must have it's own DataSet.
140
141 ············string logPath = AppDomain.CurrentDomain.BaseDirectory;
142
143 ············if (logPath == null)
144 ················logPath = Path.GetDirectoryName( mapping.FileName );
145
146 ············this.LogPath = logPath;
147 ········}
148
149 ········/// <summary>
150 ········/// Used by PersistenceManagers, to get an owner supplied id.
151 ········/// </summary>
152 ········/// <param name="t">Type of the object, the id is intended for.</param>
153 ········/// <param name="oid">ObjectId object which will hold the id value.</param>
154 ········protected void FireIdGenerationEvent(Type t, ObjectId oid)
155 ········{
156 ············if (IdGenerationEvent != null)
157 ················IdGenerationEvent(t, oid);
158 ········}
159
160
161 ········Dictionary<string,Class> myClassesName;
162 ········Dictionary<Type, Class> myClassesType;
163
164 ········/// <summary>
165 ········/// Initializes the class mappings
166 ········/// </summary>
167 ········protected void InitClasses()
168 ········{
169 ············int cnt = mappings.Classes.Count();
170 ············myClassesName = new Dictionary<string, Class>(cnt);
171 ············myClassesType = new Dictionary<Type, Class>(cnt);
172 ············foreach(Class cl in mappings.Classes)
173 ············{
174 ················myClassesName.Add(cl.FullName, cl);
175 ················myClassesType.Add(cl.SystemType, cl);
176 ············}
177 ········}
178 ········
179
180 ········internal Class GetClass(string name)
181 ········{
182 ············if (!myClassesName.ContainsKey(name))
183 ················throw new NDOException(17, "Can't find mapping information for class " + name);
184
185 ············return myClassesName[name];
186 ········}
187
188 ········internal Class GetClass(IPersistenceCapable pc)
189 ········{
190 ············return GetClass(pc.GetType());
191 ········}
192
193 ········internal Class GetClass(Type type)
194 ········{
195 ············Type t = type;
196
197 ············if (type.IsGenericType)
198 ················t = type.GetGenericTypeDefinition();
199
200 ············if (! myClassesType.ContainsKey(t))
201 ················throw new NDOException(17, "Can't find mapping information for class " + t.FullName);
202
203 ············return myClassesType[t];
204
205 ········}
206
207 ········internal Field GetField(Class cl, string field)
208 ········{
209 ············Field f = cl.FindField(field);
210 ············if (f == null)
211 ················throw new NDOException(7, "Can't find mapping information for field " + cl.FullName + "." + field);
212 ············return f;
213 ········}
214
215 ········/// <summary>
216 ········/// Hilfsfunktion
217 ········/// Liefert die Tabelle im DataSet ab, in der die DataRows des Datentyps liegen
218 ········/// </summary>
219 ········/// <param name="t">Data type</param>
220 ········/// <returns></returns>
221 ········protected DataTable GetTable(Type t)
222 ········{
223 ············return GetTable(GetClass(t).TableName);
224 ········}
225
226 ········/// <summary>
227 ········/// Hilfsfunktion
228 ········/// Liefert die Tabelle im DataSet ab, in der die DataRow des Objekts liegt
229 ········/// </summary>
230 ········/// <param name="pc"></param>
231 ········/// <returns></returns>
232 ········protected DataTable GetTable(IPersistenceCapable pc)
233 ········{
234 ············return GetTable(GetClass(pc).TableName);
235 ········}
236
237
238 ········/// <summary>
239 ········/// Retrieve a table with the given name
240 ········/// </summary>
241 ········/// <param name="name">Table name</param>
242 ········/// <returns></returns>
243 ········protected DataTable GetTable(string name)
244 ········{
245 ············DataTable dt = ds.Tables[name];
246 ············if (dt == null)
247 ················throw new NDOException(39, "Can't find table '" + name + "' in the schema. Check your mapping file.");
248 ············return dt;
249 ········}
250
251 ········/// <summary>
252 ········/// Gets a DataRow for a given object; if necessary the row will be constructed
253 ········/// </summary>
254 ········/// <param name="pc">Persistence capable object</param>
255 ········/// <returns></returns>
256 ········protected DataRow GetDataRow(IPersistenceCapable pc)
257 ········{
258 ············DataRow row;
259 ············if ((row = this.cache.GetDataRow(pc)) != null)
260 ················return row;
261 ············return null;
262 ········}
263
264
265
266 ········/// <summary>
267 ········/// Indicates, if there is a listener registered for the IdGenerationEvent.
268 ········/// </summary>
269 ········public bool HasOwnerCreatedIds
270 ········{
271 ············get { return IdGenerationEvent != null; }
272 ········}
273
274 ········/// <summary>
275 ········/// If set, the PersistenceManager writes a log of all SQL statements issued to the databases.
276 ········/// By default a LogFileAdapter to the file SqlIOLog.txt will be used. The log medium can be
277 ········/// changed using the <see cref="NDO.PersistenceManagerBase.LogAdapter">LogAdapter property</see>.
278 ········/// </summary>
279 ········public virtual bool VerboseMode
280 ········{
281 ············get {return mappings.VerboseMode;}
282 ············set {mappings.VerboseMode = value;}
283 ········}
284
285 ········/// <summary>
286 ········/// Gets or sets the type which is used to construct persistence handlers.
287 ········/// </summary>
288 ········[Obsolete("Use the ConfigContainer to register a handler type.")]
289 ········public Type PersistenceHandlerType
290 ········{
291 ············get { return persistenceHandlerType; }
292 ············set
293 ············{
294 ················if (value != null && value.GetInterface("IPersistenceHandler") == null)
295 ····················throw new NDOException(46, "Invalid PersistenceHandlerType: " + value.FullName);
296 ················ConfigContainer.RegisterType( typeof( IPersistenceHandler ), persistenceHandlerType );
297 ············}
298 ········}
299
300 ········/// <summary>
301 ········/// Gets or sets the container for the configuration of the system.
302 ········/// </summary>
303 ········public INDOContainer ConfigContainer
304 ········{
305 ············get
306 ············{
307 ················if (this.configContainer == null)
308 ················{
309 ····················this.configContainer = NDOContainer.Instance.CreateChildContainer();
310 ····················this.configContainer.RegisterType<IQueryGenerator, SqlQueryGenerator>();
311
312 ····················// Currently the PersistenceManager instance is not used.
313 ····················// But we are able to pull it from the container.
314 ····················this.configContainer.RegisterInstance( typeof( PersistenceManager ), this );
315 ················}
316
317 ················return this.configContainer;
318 ············}
319 ············set { this.configContainer = value; }
320 ········}
321
322
323 ········/// <summary>
324 ········/// Sets or gets the logging Adapter, log information is written to.
325 ········/// </summary>
326 ········/// <remarks>
327 ········/// If LogPath is set, a LogFileAdapter object is created and attached to this property.
328 ········/// <seealso cref="LogPath"/><seealso cref="ILogAdapter"/>
329 ········/// </remarks>
330 ········public ILogAdapter LogAdapter
331 ········{
332 ············get
333 ············{
334 ················return this.logAdapter;
335 ············}
336 ············set
337 ············{
338 ················this.logAdapter = value;
339 ················mappings.LogAdapter = this.logAdapter;
340 ················LogFileAdapter lfa = this.logAdapter as LogFileAdapter;
341 ················if (lfa != null)
342 ················{
343 ····················this.logPath = Path.GetDirectoryName(lfa.FileName);
344 ················}
345 ············}
346 ········}
347
348 ········/// <summary>
349 ········/// Gets or sets an implementation of the PersistenceHandlerManager.
350 ········/// </summary>
351 ········public IPersistenceHandlerManager PersistenceHandlerManager
352 ········{
353 ············get
354 ············{
355 ················// (this.persistenceHandlerManager == null)
356 ················return this.persistenceHandlerManager = ConfigContainer.Resolve<IPersistenceHandlerManager>();
357
358 ················//return this.persistenceHandlerManager;
359 ············}
360 ············set { this.persistenceHandlerManager = value; }
361 ········}
362
363
364 ········/// <summary>
365 ········/// Gets or sets the directory, where NDO writes the sql log file to.
366 ········/// </summary>
367 ········/// <remarks>
368 ········/// A file with the name NDO.Sql.log will be generated in the LogPath, if
369 ········/// verbose mode is set to true. Note, that a FileLogAdapter object is created,
370 ········/// if LogPath is set. If a LogAdapter is set, LogPath might
371 ········/// reflect an undefined state.<seealso cref="LogAdapter"/><seealso cref="ILogAdapter"/>
372 ········/// </remarks>
373 ········public string LogPath
374 ········{
375 ············get { return logPath; }
376 ············set
377 ············{
378 ················logPath = value;
379 ················if (logPath == null)
380 ····················return;
381 ················if (!Directory.Exists(value))
382 ····················throw new NDOException(47, "Log path doesn't exist: " + value);
383 ················string fileName = Path.Combine(logPath, "NDO.Sql.log");
384 ················// use the Property to invoke the additional logic
385 ················this.LogAdapter = new LogFileAdapter(fileName);
386 ············}
387 ········}
388
389 ········
390 ········/// <summary>
391 ········/// Gets the Mapping structure of the application as stored in NDOMapping.xml.
392 ········/// Use it only if you know exactly, what you're doing!
393 ········/// Do not change anything in the mapping structure because it will cause the
394 ········/// NDO Framework to fail.
395 ········/// </summary>
396 ········public NDOMapping NDOMapping
397 ········{
398 ············get { return this.mappings; }
399 ········}
400
401 ········/// <summary>
402 ········/// Gets the DataSet behind the operations of the pm.
403 ········/// </summary>
404 ········/// <remarks>This property should't be used by user code. It exists only for test purposes.</remarks>
405 ········public DataSet DataSet
406 ········{
407 ············get { return this.ds; }
408 ········}
409
410 ········internal NDO.Cache Cache
411 ········{
412 ············get { return this.cache; }
413 ········}
414
415 ········/// <summary>
416 ········/// Clears any log file entries in the log file
417 ········/// </summary>
418 ········/// <remarks>
419 ········/// Note, that not all LogAdapters support this function. In that case, the
420 ········/// call to ClearLogfile is ignored.
421 ········/// </remarks>
422 ········public void ClearLogfile()
423 ········{
424 ············if (this.logAdapter != null)
425 ················this.LogAdapter.Clear();
426 ········}
427
428 ········/// <summary>
429 ········/// Determines, if a log message will actually be issued.
430 ········/// </summary>
431 ········public bool LoggingPossible
432 ········{
433 ············get { return (VerboseMode && this.logAdapter != null); }
434 ········}
435
436 ········/// <summary>
437 ········/// Checks whether an object is an IPersistenceCapable and converts the object into an IPersistenceCapable.
438 ········/// </summary>
439 ········/// <param name="o"></param>
440 ········/// <returns></returns>
441 ········/// <remarks>Throws an NDOException, if the object can't be converted.</remarks>
442 ········protected internal IPersistenceCapable CheckPc(object o)
443 ········{
444 ············IPersistenceCapable pc = o as IPersistenceCapable;
445 ············if (pc == null && !(o == null))
446 ················throw new NDOException(31, "Parameter should implement IPersistenceCapable. Check, if the type " + o.GetType().FullName + "," + o.GetType().Assembly.FullName + " is enhanced.");
447 ············return pc;
448 ········}
449
450 ········/// <summary>
451 ········/// Closes the PersistenceManager and releases all resources.
452 ········/// </summary>
453 ········public virtual void Close()
454 ········{
455 ············if (isClosing)
456 ················return;
457 ············isClosing = true;
458 ············this.ds.Dispose();
459 ············this.ds = null;
460 ············this.configContainer.Dispose();··// Leads to another Disposal of the PM. therefore we query for isClosing.
461 ········}
462
463 ········/// <summary>
464 ········/// IDisposable implementation.
465 ········/// </summary>
466 ········/// <remarks>Note: The derived classes don't need to override the Dispose methods, since Close() is virtual. Just override Close() and call base.Close() in the overridden version.</remarks>
467 ········/// <param name="disposing"></param>
468 ········protected virtual void Dispose(bool disposing)
469 ········{
470 ············if (disposing)
471 ················Close();
472 ········}
473
474 ········/// <summary>
475 ········/// Disposes any Resources which might be held by the PersistenceManager implementation.
476 ········/// </summary>
477 ········public virtual void Dispose()
478 ········{
479 ············Dispose( true );
480 ············GC.SuppressFinalize( this );
481 ········}
482
483 ········/// <summary>
484 ········/// Finalizer.
485 ········/// </summary>
486 ········~PersistenceManagerBase()
487 ········{
488 ············Dispose( false );
489 ········}
490 ····}
491 }
492
New Commit (1b950ea)
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
23 using System;
24 using System.Collections.Generic;
25 using System.Linq;
26 using System.IO;
27 using System.Data;
28 using NDO.Logging;
29 using NDO.Mapping;
30 using NDO.Configuration;
31 using NDO.SqlPersistenceHandling;
32 using System.Reflection;
33
34 namespace NDO
35 {
36 ····/// <summary>
37 ····/// Provides base functionality for PersistenceManager classes
38 ····/// </summary>
39 ····public class PersistenceManagerBase : IPersistenceManagerBase
40 ····{
41 ········internal Cache cache = new Cache();
42 ········/// <summary>
43 ········/// The DataSet used as template for DataRows
44 ········/// </summary>
45 ········protected DataSet ds = null;
46 ········/// <summary>
47 ········/// The StateManager instance which will be used for all objects
48 ········/// </summary>
49 ········protected IStateManager sm;
50 ········internal Mappings mappings;··// protected will make the compiler complaining
51 ········private string logPath;
52 ········private ILogAdapter logAdapter;
53 ········private Type persistenceHandlerType = null;
54 ········private INDOContainer configContainer;
55 ········private IPersistenceHandlerManager persistenceHandlerManager;
56 ········bool isClosing = false;
57
58 ········/// <summary>
59 ········/// Register a listener to this event, if you have to provide user generated ids.
60 ········/// This event is usefull for databases, which doesn't provide auto-incremented ids, like the Oracle Db.
61 ········/// The event will be fired if a new id is needed.
62 ········/// </summary>
63 ········public event IdGenerationHandler IdGenerationEvent;
64
65 ········/// <summary>
66 ········/// Constructor
67 ········/// </summary>
68 ········public PersistenceManagerBase()
69 ········{
70 ············string baseDir = AppDomain.CurrentDomain.BaseDirectory;
71 ············if (File.Exists( Path.Combine( baseDir, "Web.config" ) ))
72 ················baseDir = Path.Combine( baseDir, "bin" );
73 ············var entryAssemblyName = Assembly.GetEntryAssembly()?.GetName()?.Name;
74 ············List<string> paths = new List<string>();
75 ············if (entryAssemblyName != null)
76 ············paths.Add( Path.Combine( baseDir, $"{entryAssemblyName}.ndo.mapping" ) );
77 ············paths.Add( Path.Combine( baseDir, "NDOMapping.xml" ) );
78 ············
79 ············bool found = false;
80 ············foreach (var path in paths)
81 ············{
82 ················if (File.Exists(path))
83 ················{
84 ····················Init( path );
85 ····················found = true;
86 ····················break;
87 ················}
88 ············}
89 ············if (!found)
90 ················throw new NDOException( 49, $"Can't determine the path to the mapping file. Tried the following locations:\n{string.Join("\n", paths)}\nPlease provide a mapping file path as argument to the PersistenceManager ctor." );
91 ········}
92
93 ········/// <summary>
94 ········/// Constructs a PersistenceManagerBase object using the path to a mapping file.
95 ········/// </summary>
96 ········/// <param name="mappingFile"></param>
97 ········public PersistenceManagerBase(string mappingFile)
98 ········{
99 ············Init(mappingFile);
100 ········}
101
102 ········/// <summary>
103 ········/// Constructs a PersistenceManagerBase object using the mapping object.
104 ········/// </summary>
105 ········/// <param name="mapping"></param>
106 ········public PersistenceManagerBase(NDOMapping mapping)
107 ········{
108 ············var localMappings = mapping as Mappings;
109 ············if (localMappings == null)
110 ················throw new ArgumentException( "The mapping must be constructed by a PersistenceManager", nameof( mapping ) );
111
112 ············Init( localMappings );
113 ········}
114
115 ········/// <summary>
116 ········/// Initializes a PersistenceManager using the path to a mapping file
117 ········/// </summary>
118 ········/// <param name="mappingPath"></param>
119 ········protected virtual void Init(string mappingPath)
120 ········{
121 ············if (!File.Exists(mappingPath))
122 ················throw new NDOException(45, String.Format("Mapping File {0} doesn't exist.", mappingPath));
123 Init( new Mappings( mappingPath ) ) ;
124 ········}
125
126 ········/// <summary>
127 ········/// Initializes the persistence manager
128 ········/// </summary>
129 ········/// <remarks>
130 ········/// Note: This is the method, which will be called from all different ways to instantiate a PersistenceManagerBase.
131 ········/// </remarks>
132 ········/// <param name="mapping"></param>
133 ········internal virtual void Init( Mappings mapping )
134 ········{
135 ············this.mappings = mapping;
136
137 ············ConfigContainer.RegisterInstance( mappings );
138
139 ············this.ds = new NDODataSet( mappings );··// Each PersistenceManager instance must have it's own DataSet.
140
141 ············string logPath = AppDomain.CurrentDomain.BaseDirectory;
142
143 ············if (logPath == null)
144 ················logPath = Path.GetDirectoryName( mapping.FileName );
145
146 ············this.LogPath = logPath;
147 ········}
148
149 ········/// <summary>
150 ········/// Used by PersistenceManagers, to get an owner supplied id.
151 ········/// </summary>
152 ········/// <param name="t">Type of the object, the id is intended for.</param>
153 ········/// <param name="oid">ObjectId object which will hold the id value.</param>
154 ········protected void FireIdGenerationEvent(Type t, ObjectId oid)
155 ········{
156 ············if (IdGenerationEvent != null)
157 ················IdGenerationEvent(t, oid);
158 ········}
159
160
161 ········Dictionary<string,Class> myClassesName;
162 ········Dictionary<Type, Class> myClassesType;
163
164 ········/// <summary>
165 ········/// Initializes the class mappings
166 ········/// </summary>
167 ········protected void InitClasses()
168 ········{
169 ············int cnt = mappings.Classes.Count();
170 ············myClassesName = new Dictionary<string, Class>(cnt);
171 ············myClassesType = new Dictionary<Type, Class>(cnt);
172 ············foreach(Class cl in mappings.Classes)
173 ············{
174 ················myClassesName.Add(cl.FullName, cl);
175 ················myClassesType.Add(cl.SystemType, cl);
176 ············}
177 ········}
178 ········
179
180 ········internal Class GetClass(string name)
181 ········{
182 ············if (!myClassesName.ContainsKey(name))
183 ················throw new NDOException(17, "Can't find mapping information for class " + name);
184
185 ············return myClassesName[name];
186 ········}
187
188 ········internal Class GetClass(IPersistenceCapable pc)
189 ········{
190 ············return GetClass(pc.GetType());
191 ········}
192
193 ········internal Class GetClass(Type type)
194 ········{
195 ············Type t = type;
196
197 ············if (type.IsGenericType)
198 ················t = type.GetGenericTypeDefinition();
199
200 ············if (! myClassesType.ContainsKey(t))
201 ················throw new NDOException(17, "Can't find mapping information for class " + t.FullName);
202
203 ············return myClassesType[t];
204
205 ········}
206
207 ········internal Field GetField(Class cl, string field)
208 ········{
209 ············Field f = cl.FindField(field);
210 ············if (f == null)
211 ················throw new NDOException(7, "Can't find mapping information for field " + cl.FullName + "." + field);
212 ············return f;
213 ········}
214
215 ········/// <summary>
216 ········/// Hilfsfunktion
217 ········/// Liefert die Tabelle im DataSet ab, in der die DataRows des Datentyps liegen
218 ········/// </summary>
219 ········/// <param name="t">Data type</param>
220 ········/// <returns></returns>
221 ········protected DataTable GetTable(Type t)
222 ········{
223 ············return GetTable(GetClass(t).TableName);
224 ········}
225
226 ········/// <summary>
227 ········/// Hilfsfunktion
228 ········/// Liefert die Tabelle im DataSet ab, in der die DataRow des Objekts liegt
229 ········/// </summary>
230 ········/// <param name="pc"></param>
231 ········/// <returns></returns>
232 ········protected DataTable GetTable(IPersistenceCapable pc)
233 ········{
234 ············return GetTable(GetClass(pc).TableName);
235 ········}
236
237
238 ········/// <summary>
239 ········/// Retrieve a table with the given name
240 ········/// </summary>
241 ········/// <param name="name">Table name</param>
242 ········/// <returns></returns>
243 ········protected DataTable GetTable(string name)
244 ········{
245 ············DataTable dt = ds.Tables[name];
246 ············if (dt == null)
247 ················throw new NDOException(39, "Can't find table '" + name + "' in the schema. Check your mapping file.");
248 ············return dt;
249 ········}
250
251 ········/// <summary>
252 ········/// Gets a DataRow for a given object; if necessary the row will be constructed
253 ········/// </summary>
254 ········/// <param name="pc">Persistence capable object</param>
255 ········/// <returns></returns>
256 ········protected DataRow GetDataRow(IPersistenceCapable pc)
257 ········{
258 ············DataRow row;
259 ············if ((row = this.cache.GetDataRow(pc)) != null)
260 ················return row;
261 ············return null;
262 ········}
263
264
265
266 ········/// <summary>
267 ········/// Indicates, if there is a listener registered for the IdGenerationEvent.
268 ········/// </summary>
269 ········public bool HasOwnerCreatedIds
270 ········{
271 ············get { return IdGenerationEvent != null; }
272 ········}
273
274 ········/// <summary>
275 ········/// If set, the PersistenceManager writes a log of all SQL statements issued to the databases.
276 ········/// By default a LogFileAdapter to the file SqlIOLog.txt will be used. The log medium can be
277 ········/// changed using the <see cref="NDO.PersistenceManagerBase.LogAdapter">LogAdapter property</see>.
278 ········/// </summary>
279 ········public virtual bool VerboseMode
280 ········{
281 ············get {return mappings.VerboseMode;}
282 ············set {mappings.VerboseMode = value;}
283 ········}
284
285 ········/// <summary>
286 ········/// Gets or sets the type which is used to construct persistence handlers.
287 ········/// </summary>
288 ········[Obsolete("Use the ConfigContainer to register a handler type.")]
289 ········public Type PersistenceHandlerType
290 ········{
291 ············get { return persistenceHandlerType; }
292 ············set
293 ············{
294 ················if (value != null && value.GetInterface("IPersistenceHandler") == null)
295 ····················throw new NDOException(46, "Invalid PersistenceHandlerType: " + value.FullName);
296 ················ConfigContainer.RegisterType( typeof( IPersistenceHandler ), persistenceHandlerType );
297 ············}
298 ········}
299
300 ········/// <summary>
301 ········/// Gets or sets the container for the configuration of the system.
302 ········/// </summary>
303 ········public INDOContainer ConfigContainer
304 ········{
305 ············get
306 ············{
307 ················if (this.configContainer == null)
308 ················{
309 ····················this.configContainer = NDOContainer.Instance.CreateChildContainer();
310 ····················this.configContainer.RegisterType<IQueryGenerator, SqlQueryGenerator>();
311
312 ····················// Currently the PersistenceManager instance is not used.
313 ····················// But we are able to pull it from the container.
314 ····················this.configContainer.RegisterInstance( typeof( PersistenceManager ), this );
315 ················}
316
317 ················return this.configContainer;
318 ············}
319 ············set { this.configContainer = value; }
320 ········}
321
322
323 ········/// <summary>
324 ········/// Sets or gets the logging Adapter, log information is written to.
325 ········/// </summary>
326 ········/// <remarks>
327 ········/// If LogPath is set, a LogFileAdapter object is created and attached to this property.
328 ········/// <seealso cref="LogPath"/><seealso cref="ILogAdapter"/>
329 ········/// </remarks>
330 ········public ILogAdapter LogAdapter
331 ········{
332 ············get
333 ············{
334 ················return this.logAdapter;
335 ············}
336 ············set
337 ············{
338 ················this.logAdapter = value;
339 ················mappings.LogAdapter = this.logAdapter;
340 ················LogFileAdapter lfa = this.logAdapter as LogFileAdapter;
341 ················if (lfa != null)
342 ················{
343 ····················this.logPath = Path.GetDirectoryName(lfa.FileName);
344 ················}
345 ············}
346 ········}
347
348 ········/// <summary>
349 ········/// Gets or sets an implementation of the PersistenceHandlerManager.
350 ········/// </summary>
351 ········public IPersistenceHandlerManager PersistenceHandlerManager
352 ········{
353 ············get
354 ············{
355 ················// (this.persistenceHandlerManager == null)
356 ················return this.persistenceHandlerManager = ConfigContainer.Resolve<IPersistenceHandlerManager>();
357
358 ················//return this.persistenceHandlerManager;
359 ············}
360 ············set { this.persistenceHandlerManager = value; }
361 ········}
362
363
364 ········/// <summary>
365 ········/// Gets or sets the directory, where NDO writes the sql log file to.
366 ········/// </summary>
367 ········/// <remarks>
368 ········/// A file with the name NDO.Sql.log will be generated in the LogPath, if
369 ········/// verbose mode is set to true. Note, that a FileLogAdapter object is created,
370 ········/// if LogPath is set. If a LogAdapter is set, LogPath might
371 ········/// reflect an undefined state.<seealso cref="LogAdapter"/><seealso cref="ILogAdapter"/>
372 ········/// </remarks>
373 ········public string LogPath
374 ········{
375 ············get { return logPath; }
376 ············set
377 ············{
378 ················logPath = value;
379 ················if (logPath == null)
380 ····················return;
381 ················if (!Directory.Exists(value))
382 ····················throw new NDOException(47, "Log path doesn't exist: " + value);
383 ················string fileName = Path.Combine(logPath, "NDO.Sql.log");
384 ················// use the Property to invoke the additional logic
385 ················this.LogAdapter = new LogFileAdapter(fileName);
386 ············}
387 ········}
388
389 ········
390 ········/// <summary>
391 ········/// Gets the Mapping structure of the application as stored in NDOMapping.xml.
392 ········/// Use it only if you know exactly, what you're doing!
393 ········/// Do not change anything in the mapping structure because it will cause the
394 ········/// NDO Framework to fail.
395 ········/// </summary>
396 ········public NDOMapping NDOMapping
397 ········{
398 ············get { return this.mappings; }
399 ········}
400
401 ········/// <summary>
402 ········/// Gets the DataSet behind the operations of the pm.
403 ········/// </summary>
404 ········/// <remarks>This property should't be used by user code. It exists only for test purposes.</remarks>
405 ········public DataSet DataSet
406 ········{
407 ············get { return this.ds; }
408 ········}
409
410 ········internal NDO.Cache Cache
411 ········{
412 ············get { return this.cache; }
413 ········}
414
415 ········/// <summary>
416 ········/// Clears any log file entries in the log file
417 ········/// </summary>
418 ········/// <remarks>
419 ········/// Note, that not all LogAdapters support this function. In that case, the
420 ········/// call to ClearLogfile is ignored.
421 ········/// </remarks>
422 ········public void ClearLogfile()
423 ········{
424 ············if (this.logAdapter != null)
425 ················this.LogAdapter.Clear();
426 ········}
427
428 ········/// <summary>
429 ········/// Determines, if a log message will actually be issued.
430 ········/// </summary>
431 ········public bool LoggingPossible
432 ········{
433 ············get { return (VerboseMode && this.logAdapter != null); }
434 ········}
435
436 ········/// <summary>
437 ········/// Checks whether an object is an IPersistenceCapable and converts the object into an IPersistenceCapable.
438 ········/// </summary>
439 ········/// <param name="o"></param>
440 ········/// <returns></returns>
441 ········/// <remarks>Throws an NDOException, if the object can't be converted.</remarks>
442 ········protected internal IPersistenceCapable CheckPc(object o)
443 ········{
444 ············IPersistenceCapable pc = o as IPersistenceCapable;
445 ············if (pc == null && !(o == null))
446 ················throw new NDOException(31, "Parameter should implement IPersistenceCapable. Check, if the type " + o.GetType().FullName + "," + o.GetType().Assembly.FullName + " is enhanced.");
447 ············return pc;
448 ········}
449
450 ········/// <summary>
451 ········/// Closes the PersistenceManager and releases all resources.
452 ········/// </summary>
453 ········public virtual void Close()
454 ········{
455 ············if (isClosing)
456 ················return;
457 ············isClosing = true;
458 ············this.ds.Dispose();
459 ············this.ds = null;
460 ············this.configContainer.Dispose();··// Leads to another Disposal of the PM. therefore we query for isClosing.
461 ········}
462
463 ········/// <summary>
464 ········/// IDisposable implementation.
465 ········/// </summary>
466 ········/// <remarks>Note: The derived classes don't need to override the Dispose methods, since Close() is virtual. Just override Close() and call base.Close() in the overridden version.</remarks>
467 ········/// <param name="disposing"></param>
468 ········protected virtual void Dispose(bool disposing)
469 ········{
470 ············if (disposing)
471 ················Close();
472 ········}
473
474 ········/// <summary>
475 ········/// Disposes any Resources which might be held by the PersistenceManager implementation.
476 ········/// </summary>
477 ········public virtual void Dispose()
478 ········{
479 ············Dispose( true );
480 ············GC.SuppressFinalize( this );
481 ········}
482
483 ········/// <summary>
484 ········/// Finalizer.
485 ········/// </summary>
486 ········~PersistenceManagerBase()
487 ········{
488 ············Dispose( false );
489 ········}
490 ····}
491 }
492