Datei: NDODLL/Mappings.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.Diagnostics;
25 using System.Data;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Reflection;
29 using System.Xml;
30 using NDO;
31 using NDO.Mapping;
32 using NDO.Logging;
33 using NDO.Configuration;
34 using NDO.SqlPersistenceHandling;
35
36 namespace NDO
37 {
38 ····/// <summary>
39 ····/// Summary description for Mappings.
40 ····/// </summary>
41 ····internal class Mappings : NDOMapping
42 ····{
43 ········private Dictionary<Type, IPersistenceHandler> persistenceHandler = new Dictionary<Type, IPersistenceHandler>();
44 ········private Dictionary<Type,int> updateOrder = new Dictionary<Type, int>();
45 ········ILogAdapter logAdapter;
46 ········private bool verboseMode;
47 ········private readonly INDOContainer configContainer;
48
49 internal Mappings( string mappingFile, INDOContainer configContainer )
50 ············: base( mappingFile )
51 ········{
52 ············this.configContainer = configContainer;
53 ············InitClassFields();
54 ············this.updateOrder = new ClassRank().BuildUpdateRank( Classes );
55 ········}
56
57 ········private void InitClassFields()
58 ········{
59 ············foreach ( Class c in Classes )
60 ············{
61 ················((IFieldInitializer) c).InitFields();
62 ············}
63 ············// New loop, because we need the SystemType entries of all classes
64 ············foreach ( Class c in Classes )
65 ············{
66 ················c.ComputeRelationOrdinalBase();
67 ················foreach ( Relation r in c.Relations )
68 ················{
69 ····················((IFieldInitializer) r).InitFields();
70 ················}
71 ············}
72 ············// New loop, we need all relations initialized
73 ············foreach ( Class c in Classes )
74 ············{
75 ················c.CollectForeignKeyNames();
76 ············}
77 ········}
78
79
80 ········/// <summary>
81 ········/// Gets or sets a value which determines, if database operations will be logged in a logging file.
82 ········/// </summary>
83 ········internal bool VerboseMode
84 ········{
85 ············get { return this.verboseMode; }
86 ············set
87 ············{
88 ················this.verboseMode = value;
89 ················foreach ( var de in persistenceHandler )
90 ················{
91 ····················de.Value.VerboseMode = value;
92 ················}
93 ············}
94 ········}
95
96 ········/// <summary>
97 ········/// Gets or sets the Adapter, log entries are written to, if VerboseMode is true.
98 ········/// </summary>
99 ········internal ILogAdapter LogAdapter
100 ········{
101 ············set
102 ············{
103 ················this.logAdapter = value;
104 ················foreach ( var de in persistenceHandler )
105 ················{
106 ····················de.Value.LogAdapter = value;
107 ················}
108 ············}
109 ········}
110
111
112 ········/// <summary>
113 ········/// Find info about the specified class.
114 ········/// </summary>
115 ········/// <param name="pc">the persistent object of the class</param>
116 ········/// <returns>mapping info about the class</returns>
117 ········public Class FindClass( IPersistenceCapable pc )
118 ········{
119 ············return FindClass( pc.GetType().FullName );
120 ········}
121
122
123 ········/// <summary>
124 ········/// Find the relation of the given object with the specified name.
125 ········/// </summary>
126 ········/// <param name="pc">the persistent object with the relation</param>
127 ········/// <param name="fieldName">the field name of the relation</param>
128 ········/// <returns>mapping info about the relation.</returns>
129 ········public Relation FindRelation( IPersistenceCapable pc, string fieldName )
130 ········{
131 ············Class c = FindClass( pc );
132 ············return c.FindRelation( fieldName );
133 ········}
134
135 ········/// <summary>
136 ········/// Look for a FieldInfo in the given object; search all base types for the FieldInfo
137 ········/// </summary>
138 ········/// <param name="pc">Object to search the FieldInfo</param>
139 ········/// <param name="name">Name of the field</param>
140 ········/// <returns>The FieldInfo of the given field; An exception will be thrown, if the field can't be found.</returns>
141 ········private FieldInfo GetFieldInfo( IPersistenceCapable pc, string name )
142 ········{
143 ············Type t = pc.GetType();
144 ············FieldInfo fi = new BaseClassReflector( t ).GetField( name, BindingFlags.Instance | BindingFlags.NonPublic );
145 ············if ( fi == null )
146 ············{
147 ················throw new NDOException( 9, "Invalid mapping: unknown field name " + name + " in type " + t );
148 ············}
149 ············return fi;
150 ········}
151
152 ········/// <summary>
153 ········/// Retrieve the specified relation from the parent object.
154 ········/// </summary>
155 ········/// <param name="pc">the parent object</param>
156 ········/// <param name="r">the relation mapping info</param>
157 ········/// <returns>the content of the relation</returns>
158 ········public IList GetRelationContainer( IPersistenceCapable pc, Relation r )
159 ········{
160 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
161 ············return (IList) fi.GetValue( pc );
162 ········}
163
164 ········/// <summary>
165 ········/// Set the specified relation to the new content.
166 ········/// </summary>
167 ········/// <param name="pc">the parent object</param>
168 ········/// <param name="r">the relation mapping info</param>
169 ········/// <param name="list">the new content of the relation</param>
170 ········public void SetRelationContainer( IPersistenceCapable pc, Relation r, IList list )
171 ········{
172 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
173 ············fi.SetValue( pc, list );
174 ········}
175
176 ········/// <summary>
177 ········/// Construct a relation container
178 ········/// </summary>
179 ········/// <param name="pc">the parent object</param>
180 ········/// <param name="r">the relation mapping info</param>
181 ········public IList CreateRelationContainer( IPersistenceCapable pc, Relation r )
182 ········{
183 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
184 ············return (IList) ListCloner.CreateList( fi.FieldType );
185 ········}
186
187
188 ········/// <summary>
189 ········/// Set the related object.
190 ········/// </summary>
191 ········/// <param name="pc">the parent</param>
192 ········/// <param name="fieldName">the name of the relation field</param>
193 ········/// <param name="theObj">the related object</param>
194 ········public void SetRelationField( IPersistenceCapable pc, string fieldName, object theObj )
195 ········{
196 ············FieldInfo fi = GetFieldInfo( pc, fieldName );
197 ············fi.SetValue( pc, theObj );
198 ········}
199
200 ········/// <summary>
201 ········/// Determine the type of a relation field.
202 ········/// </summary>
203 ········/// <param name="r"></param>
204 ········/// <returns></returns>
205 ········public Type GetRelationFieldType( Relation r )
206 ········{
207 ············FieldInfo fi = new BaseClassReflector( r.Parent.SystemType ).GetField( r.FieldName, BindingFlags.NonPublic | BindingFlags.Instance );
208 ············return fi.FieldType;
209 ········}
210
211 ········/// <summary>
212 ········/// Return the related object.
213 ········/// </summary>
214 ········/// <param name="pc">the parent object</param>
215 ········/// <param name="fieldName">the name of the relation field</param>
216 ········/// <returns>the related object</returns>
217 ········public object GetRelationField( IPersistenceCapable pc, string fieldName )
218 ········{
219 ············FieldInfo fi = GetFieldInfo( pc, fieldName );
220 ············return fi.GetValue( pc );
221 ········}
222
223 ········internal ICollection Get1to1Relations( Type t )
224 ········{
225 ············// this will be optimized later:
226 ············// we can cache the list of 1:1-relations for each type
227 ············Type t2 = t;
228 ············if ( t.IsGenericType )
229 ················t2 = t.GetGenericTypeDefinition();
230 ············ArrayList relations = new ArrayList();
231 ············foreach ( Relation r in FindClass( t2.FullName ).Relations )
232 ············{
233 ················if ( r.Multiplicity == RelationMultiplicity.Element && r.MappingTable == null )
234 ················{
235 ····················relations.Add( r );
236 ················}
237 ············}
238 ············return relations;
239 ········}
240
241
242 ········/// <summary>
243 ········/// Returns the delete update order of a class. Lower values have higher delete priority. The insert and update priority is reversed.
244 ········/// </summary>
245 ········/// <param name="t">the type for which the update order is requested</param>
246 ········/// <returns>the update order of the specified class</returns>
247 ········public int GetUpdateOrder( Type t )
248 ········{
249 ············if ( t.IsGenericType && !t.IsGenericTypeDefinition )
250 ················t = t.GetGenericTypeDefinition();
251 ············return (int) updateOrder[t];
252 ········}
253 ····}
254 }
255
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.Diagnostics;
25 using System.Data;
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Reflection;
29 using System.Xml;
30 using NDO;
31 using NDO.Mapping;
32 using NDO.Logging;
33 using NDO.Configuration;
34 using NDO.SqlPersistenceHandling;
35
36 namespace NDO
37 {
38 ····/// <summary>
39 ····/// Summary description for Mappings.
40 ····/// </summary>
41 ····internal class Mappings : NDOMapping
42 ····{
43 ········private Dictionary<Type, IPersistenceHandler> persistenceHandler = new Dictionary<Type, IPersistenceHandler>();
44 ········private Dictionary<Type,int> updateOrder = new Dictionary<Type, int>();
45 ········ILogAdapter logAdapter;
46 ········private bool verboseMode;
 
47
48 internal Mappings( string mappingFile )
49 ············: base( mappingFile )
50 ········{
 
51 ············InitClassFields();
52 ············this.updateOrder = new ClassRank().BuildUpdateRank( Classes );
53 ········}
54
55 ········private void InitClassFields()
56 ········{
57 ············foreach ( Class c in Classes )
58 ············{
59 ················((IFieldInitializer) c).InitFields();
60 ············}
61 ············// New loop, because we need the SystemType entries of all classes
62 ············foreach ( Class c in Classes )
63 ············{
64 ················c.ComputeRelationOrdinalBase();
65 ················foreach ( Relation r in c.Relations )
66 ················{
67 ····················((IFieldInitializer) r).InitFields();
68 ················}
69 ············}
70 ············// New loop, we need all relations initialized
71 ············foreach ( Class c in Classes )
72 ············{
73 ················c.CollectForeignKeyNames();
74 ············}
75 ········}
76
77
78 ········/// <summary>
79 ········/// Gets or sets a value which determines, if database operations will be logged in a logging file.
80 ········/// </summary>
81 ········internal bool VerboseMode
82 ········{
83 ············get { return this.verboseMode; }
84 ············set
85 ············{
86 ················this.verboseMode = value;
87 ················foreach ( var de in persistenceHandler )
88 ················{
89 ····················de.Value.VerboseMode = value;
90 ················}
91 ············}
92 ········}
93
94 ········/// <summary>
95 ········/// Gets or sets the Adapter, log entries are written to, if VerboseMode is true.
96 ········/// </summary>
97 ········internal ILogAdapter LogAdapter
98 ········{
99 ············set
100 ············{
101 ················this.logAdapter = value;
102 ················foreach ( var de in persistenceHandler )
103 ················{
104 ····················de.Value.LogAdapter = value;
105 ················}
106 ············}
107 ········}
108
109
110 ········/// <summary>
111 ········/// Find info about the specified class.
112 ········/// </summary>
113 ········/// <param name="pc">the persistent object of the class</param>
114 ········/// <returns>mapping info about the class</returns>
115 ········public Class FindClass( IPersistenceCapable pc )
116 ········{
117 ············return FindClass( pc.GetType().FullName );
118 ········}
119
120
121 ········/// <summary>
122 ········/// Find the relation of the given object with the specified name.
123 ········/// </summary>
124 ········/// <param name="pc">the persistent object with the relation</param>
125 ········/// <param name="fieldName">the field name of the relation</param>
126 ········/// <returns>mapping info about the relation.</returns>
127 ········public Relation FindRelation( IPersistenceCapable pc, string fieldName )
128 ········{
129 ············Class c = FindClass( pc );
130 ············return c.FindRelation( fieldName );
131 ········}
132
133 ········/// <summary>
134 ········/// Look for a FieldInfo in the given object; search all base types for the FieldInfo
135 ········/// </summary>
136 ········/// <param name="pc">Object to search the FieldInfo</param>
137 ········/// <param name="name">Name of the field</param>
138 ········/// <returns>The FieldInfo of the given field; An exception will be thrown, if the field can't be found.</returns>
139 ········private FieldInfo GetFieldInfo( IPersistenceCapable pc, string name )
140 ········{
141 ············Type t = pc.GetType();
142 ············FieldInfo fi = new BaseClassReflector( t ).GetField( name, BindingFlags.Instance | BindingFlags.NonPublic );
143 ············if ( fi == null )
144 ············{
145 ················throw new NDOException( 9, "Invalid mapping: unknown field name " + name + " in type " + t );
146 ············}
147 ············return fi;
148 ········}
149
150 ········/// <summary>
151 ········/// Retrieve the specified relation from the parent object.
152 ········/// </summary>
153 ········/// <param name="pc">the parent object</param>
154 ········/// <param name="r">the relation mapping info</param>
155 ········/// <returns>the content of the relation</returns>
156 ········public IList GetRelationContainer( IPersistenceCapable pc, Relation r )
157 ········{
158 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
159 ············return (IList) fi.GetValue( pc );
160 ········}
161
162 ········/// <summary>
163 ········/// Set the specified relation to the new content.
164 ········/// </summary>
165 ········/// <param name="pc">the parent object</param>
166 ········/// <param name="r">the relation mapping info</param>
167 ········/// <param name="list">the new content of the relation</param>
168 ········public void SetRelationContainer( IPersistenceCapable pc, Relation r, IList list )
169 ········{
170 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
171 ············fi.SetValue( pc, list );
172 ········}
173
174 ········/// <summary>
175 ········/// Construct a relation container
176 ········/// </summary>
177 ········/// <param name="pc">the parent object</param>
178 ········/// <param name="r">the relation mapping info</param>
179 ········public IList CreateRelationContainer( IPersistenceCapable pc, Relation r )
180 ········{
181 ············FieldInfo fi = GetFieldInfo( pc, r.FieldName );
182 ············return (IList) ListCloner.CreateList( fi.FieldType );
183 ········}
184
185
186 ········/// <summary>
187 ········/// Set the related object.
188 ········/// </summary>
189 ········/// <param name="pc">the parent</param>
190 ········/// <param name="fieldName">the name of the relation field</param>
191 ········/// <param name="theObj">the related object</param>
192 ········public void SetRelationField( IPersistenceCapable pc, string fieldName, object theObj )
193 ········{
194 ············FieldInfo fi = GetFieldInfo( pc, fieldName );
195 ············fi.SetValue( pc, theObj );
196 ········}
197
198 ········/// <summary>
199 ········/// Determine the type of a relation field.
200 ········/// </summary>
201 ········/// <param name="r"></param>
202 ········/// <returns></returns>
203 ········public Type GetRelationFieldType( Relation r )
204 ········{
205 ············FieldInfo fi = new BaseClassReflector( r.Parent.SystemType ).GetField( r.FieldName, BindingFlags.NonPublic | BindingFlags.Instance );
206 ············return fi.FieldType;
207 ········}
208
209 ········/// <summary>
210 ········/// Return the related object.
211 ········/// </summary>
212 ········/// <param name="pc">the parent object</param>
213 ········/// <param name="fieldName">the name of the relation field</param>
214 ········/// <returns>the related object</returns>
215 ········public object GetRelationField( IPersistenceCapable pc, string fieldName )
216 ········{
217 ············FieldInfo fi = GetFieldInfo( pc, fieldName );
218 ············return fi.GetValue( pc );
219 ········}
220
221 ········internal ICollection Get1to1Relations( Type t )
222 ········{
223 ············// this will be optimized later:
224 ············// we can cache the list of 1:1-relations for each type
225 ············Type t2 = t;
226 ············if ( t.IsGenericType )
227 ················t2 = t.GetGenericTypeDefinition();
228 ············ArrayList relations = new ArrayList();
229 ············foreach ( Relation r in FindClass( t2.FullName ).Relations )
230 ············{
231 ················if ( r.Multiplicity == RelationMultiplicity.Element && r.MappingTable == null )
232 ················{
233 ····················relations.Add( r );
234 ················}
235 ············}
236 ············return relations;
237 ········}
238
239
240 ········/// <summary>
241 ········/// Returns the delete update order of a class. Lower values have higher delete priority. The insert and update priority is reversed.
242 ········/// </summary>
243 ········/// <param name="t">the type for which the update order is requested</param>
244 ········/// <returns>the update order of the specified class</returns>
245 ········public int GetUpdateOrder( Type t )
246 ········{
247 ············if ( t.IsGenericType && !t.IsGenericTypeDefinition )
248 ················t = t.GetGenericTypeDefinition();
249 ············return (int) updateOrder[t];
250 ········}
251 ····}
252 }
253