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 |