@@ -21,7 +21,8 @@ public int SaveContextToLocalStorage(StorageContext context)
2121 return total ;
2222 }
2323
24- private static IReadOnlyDictionary < string , Metadata > LoadMetadataList ( StorageContext context , IEnumerable < PropertyInfo > storageSets , Type contextType )
24+ private static IReadOnlyDictionary < string , Metadata > LoadMetadataList ( StorageContext context ,
25+ IEnumerable < PropertyInfo > storageSets , Type contextType )
2526 {
2627 var map = new Dictionary < string , Metadata > ( ) ;
2728 foreach ( var prop in storageSets )
@@ -48,7 +49,7 @@ private static int SaveStorageSets(StorageContext context, int total, Type conte
4849 var storageSetValue = prop . GetValue ( context ) ;
4950 var modelType = prop . PropertyType . GetGenericArguments ( ) [ 0 ] ;
5051 var storageTableName = Util . GetStorageTableName ( contextType , modelType ) ;
51-
52+
5253 EnsureAllModelsHaveIds ( storageSetValue , modelType , metadataMap ) ;
5354 EnsureAllAssociationsHaveIds ( context , storageSetValue , modelType , storageSets , metadataMap ) ;
5455
@@ -63,36 +64,43 @@ private static int SaveStorageSets(StorageContext context, int total, Type conte
6364 return total ;
6465 }
6566
66- private static void EnsureAllAssociationsHaveIds ( StorageContext context , object storageSetValue , Type modelType , List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
67+ private static void EnsureAllAssociationsHaveIds ( StorageContext context , object storageSetValue , Type modelType ,
68+ List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
6769 {
6870 var storageSetType = StorageManagerUtil . GenericStorageSetType . MakeGenericType ( modelType ) ;
6971 var method = storageSetType . GetMethod ( StorageManagerUtil . GetEnumerator ) ;
70- var enumerator = ( IEnumerator ) method . Invoke ( storageSetValue , new object [ ] { } ) ;
72+ var enumerator = ( IEnumerator ) method . Invoke ( storageSetValue , new object [ ] { } ) ;
7173 while ( enumerator . MoveNext ( ) )
7274 {
7375 var model = enumerator . Current ;
7476 foreach ( var prop in model . GetType ( ) . GetProperties ( ) )
7577 {
76- if ( prop . GetValue ( model ) == null || ( ! StorageManagerUtil . IsInContext ( storageSets , prop ) &&
77- ! StorageManagerUtil . IsListInContext ( storageSets , prop ) ) ) continue ;
78- if ( StorageManagerUtil . IsInContext ( storageSets , prop ) ) EnsureOneAssociationHasId ( context , prop . GetValue ( model ) , prop . PropertyType , storageSets , metadataMap ) ;
79- if ( StorageManagerUtil . IsListInContext ( storageSets , prop ) ) EnsureManyAssociationHasId ( context , prop . GetValue ( model ) , prop , storageSets , metadataMap ) ;
78+ if ( prop . GetValue ( model ) == null || ! StorageManagerUtil . IsInContext ( storageSets , prop ) &&
79+ ! StorageManagerUtil . IsListInContext ( storageSets , prop ) ) continue ;
80+ if ( StorageManagerUtil . IsInContext ( storageSets , prop ) )
81+ EnsureOneAssociationHasId ( context , prop . GetValue ( model ) , prop . PropertyType , storageSets ,
82+ metadataMap ) ;
83+ if ( StorageManagerUtil . IsListInContext ( storageSets , prop ) )
84+ EnsureManyAssociationHasId ( context , prop . GetValue ( model ) , prop , storageSets , metadataMap ) ;
8085 }
8186 }
8287 }
8388
84- private static void EnsureManyAssociationHasId ( StorageContext context , object listObject , PropertyInfo prop , List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
89+ private static void EnsureManyAssociationHasId ( StorageContext context , object listObject , PropertyInfo prop ,
90+ List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
8591 {
8692 var method = listObject . GetType ( ) . GetMethod ( StorageManagerUtil . GetEnumerator ) ;
87- var enumerator = ( IEnumerator ) method . Invoke ( listObject , new object [ ] { } ) ;
93+ var enumerator = ( IEnumerator ) method . Invoke ( listObject , new object [ ] { } ) ;
8894 while ( enumerator . MoveNext ( ) )
8995 {
9096 var model = enumerator . Current ;
91- EnsureOneAssociationHasId ( context , model , prop . PropertyType . GetGenericArguments ( ) [ 0 ] , storageSets , metadataMap ) ;
97+ EnsureOneAssociationHasId ( context , model , prop . PropertyType . GetGenericArguments ( ) [ 0 ] , storageSets ,
98+ metadataMap ) ;
9299 }
93100 }
94101
95- private static void EnsureOneAssociationHasId ( StorageContext context , object associatedModel , Type propType , List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
102+ private static void EnsureOneAssociationHasId ( StorageContext context , object associatedModel , Type propType ,
103+ List < PropertyInfo > storageSets , IReadOnlyDictionary < string , Metadata > metadataMap )
96104 {
97105 var idProp = GetIdProperty ( associatedModel ) ;
98106 var id = Convert . ToString ( idProp . GetValue ( associatedModel ) ) ;
@@ -102,26 +110,56 @@ private static void EnsureOneAssociationHasId(StorageContext context, object ass
102110 metadata . MaxId = metadata . MaxId + 1 ;
103111 SaveAssociationModel ( context , associatedModel , propType , storageSets , metadata . MaxId ) ;
104112 }
113+ else
114+ {
115+ EnsureAssociationModelExistsOrThrow ( context , Convert . ToInt32 ( id ) , storageSets , propType ) ;
116+ }
105117 }
106118
107- private static void EnsureAllModelsHaveIds ( object storageSetValue , Type modelType , IReadOnlyDictionary < string , Metadata > metadataMap )
119+ private static void EnsureAssociationModelExistsOrThrow ( StorageContext context , int id ,
120+ IEnumerable < PropertyInfo > storageSets , Type propType )
121+ {
122+ var q = from p in storageSets
123+ where p . PropertyType . GetGenericArguments ( ) [ 0 ] == propType
124+ select p ;
125+ var storeageSetProp = q . Single ( ) ;
126+ var storeageSet = storeageSetProp . GetValue ( context ) ;
127+ var listProp = storeageSet . GetType ( ) . GetProperty ( StorageManagerUtil . List , StorageManagerUtil . Flags ) ;
128+ var list = listProp . GetValue ( storeageSet ) ;
129+ var method = list . GetType ( ) . GetMethod ( StorageManagerUtil . GetEnumerator ) ;
130+ var enumerator = ( IEnumerator ) method . Invoke ( list , new object [ ] { } ) ;
131+ var found = false ;
132+ while ( enumerator . MoveNext ( ) )
133+ {
134+ var model = enumerator . Current ;
135+ if ( id != GetId ( model ) ) continue ;
136+ found = true ;
137+ break ;
138+ }
139+
140+ if ( ! found )
141+ throw new InvalidOperationException (
142+ $ "A model of type: { propType . Name } with Id { id } was deleted but still being used by an association. Remove it from the association as well.") ;
143+ }
144+
145+ private static void EnsureAllModelsHaveIds ( object storageSetValue , Type modelType ,
146+ IReadOnlyDictionary < string , Metadata > metadataMap )
108147 {
109148 var storageSetType = StorageManagerUtil . GenericStorageSetType . MakeGenericType ( modelType ) ;
110149 var method = storageSetType . GetMethod ( StorageManagerUtil . GetEnumerator ) ;
111150 var metadata = metadataMap [ Util . GetFullyQualifiedTypeName ( modelType ) ] ;
112- var enumerator = ( IEnumerator ) method . Invoke ( storageSetValue , new object [ ] { } ) ;
151+ var enumerator = ( IEnumerator ) method . Invoke ( storageSetValue , new object [ ] { } ) ;
113152 while ( enumerator . MoveNext ( ) )
114153 {
115154 var model = enumerator . Current ;
116- if ( GetId ( model ) == 0 )
117- {
118- metadata . MaxId = metadata . MaxId + 1 ;
119- SetId ( model , metadata . MaxId ) ;
120- }
155+ if ( GetId ( model ) != 0 ) continue ;
156+ metadata . MaxId = metadata . MaxId + 1 ;
157+ SetId ( model , metadata . MaxId ) ;
121158 }
122159 }
123160
124- private static void SaveMetadata ( string storageTableName , List < Guid > guids , Type context , Type modelType , Metadata oldMetadata )
161+ private static void SaveMetadata ( string storageTableName , List < Guid > guids , Type context , Type modelType ,
162+ Metadata oldMetadata )
125163 {
126164 var metadata = new Metadata
127165 {
@@ -169,8 +207,8 @@ private static string ScanModelForAssociations(object model, List<PropertyInfo>
169207 var result = serializedModel ;
170208 foreach ( var prop in model . GetType ( ) . GetProperties ( ) )
171209 {
172- if ( prop . GetValue ( model ) == null || ( ! StorageManagerUtil . IsInContext ( storageSets , prop ) &&
173- ! StorageManagerUtil . IsListInContext ( storageSets , prop ) ) ) continue ;
210+ if ( prop . GetValue ( model ) == null || ! StorageManagerUtil . IsInContext ( storageSets , prop ) &&
211+ ! StorageManagerUtil . IsListInContext ( storageSets , prop ) ) continue ;
174212 if ( StorageManagerUtil . IsInContext ( storageSets , prop ) ) result = FixOneAssociation ( model , prop , result ) ;
175213 if ( StorageManagerUtil . IsListInContext ( storageSets , prop ) )
176214 result = FixManyAssociation ( model , prop , result ) ;
@@ -203,18 +241,19 @@ private static string FixOneAssociation(object model, PropertyInfo prop, string
203241 return result ;
204242 }
205243
206- private static int SaveAssociationModel ( StorageContext context , object associatedModel , Type propType , IEnumerable < PropertyInfo > storageSets , int id )
244+ private static int SaveAssociationModel ( StorageContext context , object associatedModel , Type propType ,
245+ IEnumerable < PropertyInfo > storageSets , int id )
207246 {
208247 var q = from p in storageSets
209248 where p . PropertyType . GetGenericArguments ( ) [ 0 ] == propType
210- select p ;
249+ select p ;
211250 var storeageSetProp = q . Single ( ) ;
212251 var storeageSet = storeageSetProp . GetValue ( context ) ;
213252 var listProp = storeageSet . GetType ( ) . GetProperty ( StorageManagerUtil . List , StorageManagerUtil . Flags ) ;
214253 var list = listProp . GetValue ( storeageSet ) ;
215254 var addMethod = list . GetType ( ) . GetMethod ( StorageManagerUtil . Add ) ;
216255 SetId ( associatedModel , id ) ;
217- addMethod . Invoke ( list , new [ ] { associatedModel } ) ;
256+ addMethod . Invoke ( list , new [ ] { associatedModel } ) ;
218257 return id ;
219258 }
220259
0 commit comments