diff --git a/src/BlazorDB/BlazorDB.csproj b/src/BlazorDB/BlazorDB.csproj
index 2175514..10ef9ff 100644
--- a/src/BlazorDB/BlazorDB.csproj
+++ b/src/BlazorDB/BlazorDB.csproj
@@ -7,7 +7,7 @@
false
7.3
BlazorDB
- 0.1.0
+ 0.1.1
Chanan Braunstein
Blazor localStorage Database
In memory, persisted to localstorage, database for .net Blazor browser framework
diff --git a/src/BlazorDB/Storage/StorageManagerLoad.cs b/src/BlazorDB/Storage/StorageManagerLoad.cs
index c485496..4a19ae9 100644
--- a/src/BlazorDB/Storage/StorageManagerLoad.cs
+++ b/src/BlazorDB/Storage/StorageManagerLoad.cs
@@ -1,10 +1,10 @@
-using Microsoft.AspNetCore.Blazor;
-using Microsoft.Extensions.DependencyInjection;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
+using Microsoft.AspNetCore.Blazor;
+using Microsoft.Extensions.DependencyInjection;
namespace BlazorDB.Storage
{
diff --git a/src/BlazorDB/Storage/StorageManagerSave.cs b/src/BlazorDB/Storage/StorageManagerSave.cs
index ea1943e..1ef18fc 100644
--- a/src/BlazorDB/Storage/StorageManagerSave.cs
+++ b/src/BlazorDB/Storage/StorageManagerSave.cs
@@ -21,7 +21,8 @@ public int SaveContextToLocalStorage(StorageContext context)
return total;
}
- private static IReadOnlyDictionary LoadMetadataList(StorageContext context, IEnumerable storageSets, Type contextType)
+ private static IReadOnlyDictionary LoadMetadataList(StorageContext context,
+ IEnumerable storageSets, Type contextType)
{
var map = new Dictionary();
foreach (var prop in storageSets)
@@ -48,7 +49,7 @@ private static int SaveStorageSets(StorageContext context, int total, Type conte
var storageSetValue = prop.GetValue(context);
var modelType = prop.PropertyType.GetGenericArguments()[0];
var storageTableName = Util.GetStorageTableName(contextType, modelType);
-
+
EnsureAllModelsHaveIds(storageSetValue, modelType, metadataMap);
EnsureAllAssociationsHaveIds(context, storageSetValue, modelType, storageSets, metadataMap);
@@ -63,36 +64,43 @@ private static int SaveStorageSets(StorageContext context, int total, Type conte
return total;
}
- private static void EnsureAllAssociationsHaveIds(StorageContext context, object storageSetValue, Type modelType, List storageSets, IReadOnlyDictionary metadataMap)
+ private static void EnsureAllAssociationsHaveIds(StorageContext context, object storageSetValue, Type modelType,
+ List storageSets, IReadOnlyDictionary metadataMap)
{
var storageSetType = StorageManagerUtil.GenericStorageSetType.MakeGenericType(modelType);
var method = storageSetType.GetMethod(StorageManagerUtil.GetEnumerator);
- var enumerator = (IEnumerator)method.Invoke(storageSetValue, new object[] { });
+ var enumerator = (IEnumerator) method.Invoke(storageSetValue, new object[] { });
while (enumerator.MoveNext())
{
var model = enumerator.Current;
foreach (var prop in model.GetType().GetProperties())
{
- if (prop.GetValue(model) == null || (!StorageManagerUtil.IsInContext(storageSets, prop) &&
- !StorageManagerUtil.IsListInContext(storageSets, prop))) continue;
- if (StorageManagerUtil.IsInContext(storageSets, prop)) EnsureOneAssociationHasId(context, prop.GetValue(model), prop.PropertyType, storageSets, metadataMap);
- if (StorageManagerUtil.IsListInContext(storageSets, prop)) EnsureManyAssociationHasId(context, prop.GetValue(model), prop, storageSets, metadataMap);
+ if (prop.GetValue(model) == null || !StorageManagerUtil.IsInContext(storageSets, prop) &&
+ !StorageManagerUtil.IsListInContext(storageSets, prop)) continue;
+ if (StorageManagerUtil.IsInContext(storageSets, prop))
+ EnsureOneAssociationHasId(context, prop.GetValue(model), prop.PropertyType, storageSets,
+ metadataMap);
+ if (StorageManagerUtil.IsListInContext(storageSets, prop))
+ EnsureManyAssociationHasId(context, prop.GetValue(model), prop, storageSets, metadataMap);
}
}
}
- private static void EnsureManyAssociationHasId(StorageContext context, object listObject, PropertyInfo prop, List storageSets, IReadOnlyDictionary metadataMap)
+ private static void EnsureManyAssociationHasId(StorageContext context, object listObject, PropertyInfo prop,
+ List storageSets, IReadOnlyDictionary metadataMap)
{
var method = listObject.GetType().GetMethod(StorageManagerUtil.GetEnumerator);
- var enumerator = (IEnumerator)method.Invoke(listObject, new object[] { });
+ var enumerator = (IEnumerator) method.Invoke(listObject, new object[] { });
while (enumerator.MoveNext())
{
var model = enumerator.Current;
- EnsureOneAssociationHasId(context, model, prop.PropertyType.GetGenericArguments()[0], storageSets, metadataMap);
+ EnsureOneAssociationHasId(context, model, prop.PropertyType.GetGenericArguments()[0], storageSets,
+ metadataMap);
}
}
- private static void EnsureOneAssociationHasId(StorageContext context, object associatedModel, Type propType, List storageSets, IReadOnlyDictionary metadataMap)
+ private static void EnsureOneAssociationHasId(StorageContext context, object associatedModel, Type propType,
+ List storageSets, IReadOnlyDictionary metadataMap)
{
var idProp = GetIdProperty(associatedModel);
var id = Convert.ToString(idProp.GetValue(associatedModel));
@@ -102,26 +110,56 @@ private static void EnsureOneAssociationHasId(StorageContext context, object ass
metadata.MaxId = metadata.MaxId + 1;
SaveAssociationModel(context, associatedModel, propType, storageSets, metadata.MaxId);
}
+ else
+ {
+ EnsureAssociationModelExistsOrThrow(context, Convert.ToInt32(id), storageSets, propType);
+ }
}
- private static void EnsureAllModelsHaveIds(object storageSetValue, Type modelType, IReadOnlyDictionary metadataMap)
+ private static void EnsureAssociationModelExistsOrThrow(StorageContext context, int id,
+ IEnumerable storageSets, Type propType)
+ {
+ var q = from p in storageSets
+ where p.PropertyType.GetGenericArguments()[0] == propType
+ select p;
+ var storeageSetProp = q.Single();
+ var storeageSet = storeageSetProp.GetValue(context);
+ var listProp = storeageSet.GetType().GetProperty(StorageManagerUtil.List, StorageManagerUtil.Flags);
+ var list = listProp.GetValue(storeageSet);
+ var method = list.GetType().GetMethod(StorageManagerUtil.GetEnumerator);
+ var enumerator = (IEnumerator) method.Invoke(list, new object[] { });
+ var found = false;
+ while (enumerator.MoveNext())
+ {
+ var model = enumerator.Current;
+ if (id != GetId(model)) continue;
+ found = true;
+ break;
+ }
+
+ if (!found)
+ throw new InvalidOperationException(
+ $"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.");
+ }
+
+ private static void EnsureAllModelsHaveIds(object storageSetValue, Type modelType,
+ IReadOnlyDictionary metadataMap)
{
var storageSetType = StorageManagerUtil.GenericStorageSetType.MakeGenericType(modelType);
var method = storageSetType.GetMethod(StorageManagerUtil.GetEnumerator);
var metadata = metadataMap[Util.GetFullyQualifiedTypeName(modelType)];
- var enumerator = (IEnumerator)method.Invoke(storageSetValue, new object[] { });
+ var enumerator = (IEnumerator) method.Invoke(storageSetValue, new object[] { });
while (enumerator.MoveNext())
{
var model = enumerator.Current;
- if (GetId(model) == 0)
- {
- metadata.MaxId = metadata.MaxId + 1;
- SetId(model, metadata.MaxId);
- }
+ if (GetId(model) != 0) continue;
+ metadata.MaxId = metadata.MaxId + 1;
+ SetId(model, metadata.MaxId);
}
}
- private static void SaveMetadata(string storageTableName, List guids, Type context, Type modelType, Metadata oldMetadata)
+ private static void SaveMetadata(string storageTableName, List guids, Type context, Type modelType,
+ Metadata oldMetadata)
{
var metadata = new Metadata
{
@@ -169,8 +207,8 @@ private static string ScanModelForAssociations(object model, List
var result = serializedModel;
foreach (var prop in model.GetType().GetProperties())
{
- if (prop.GetValue(model) == null || (!StorageManagerUtil.IsInContext(storageSets, prop) &&
- !StorageManagerUtil.IsListInContext(storageSets, prop))) continue;
+ if (prop.GetValue(model) == null || !StorageManagerUtil.IsInContext(storageSets, prop) &&
+ !StorageManagerUtil.IsListInContext(storageSets, prop)) continue;
if (StorageManagerUtil.IsInContext(storageSets, prop)) result = FixOneAssociation(model, prop, result);
if (StorageManagerUtil.IsListInContext(storageSets, prop))
result = FixManyAssociation(model, prop, result);
@@ -203,18 +241,19 @@ private static string FixOneAssociation(object model, PropertyInfo prop, string
return result;
}
- private static int SaveAssociationModel(StorageContext context, object associatedModel, Type propType, IEnumerable storageSets, int id)
+ private static int SaveAssociationModel(StorageContext context, object associatedModel, Type propType,
+ IEnumerable storageSets, int id)
{
var q = from p in storageSets
where p.PropertyType.GetGenericArguments()[0] == propType
- select p;
+ select p;
var storeageSetProp = q.Single();
var storeageSet = storeageSetProp.GetValue(context);
var listProp = storeageSet.GetType().GetProperty(StorageManagerUtil.List, StorageManagerUtil.Flags);
var list = listProp.GetValue(storeageSet);
var addMethod = list.GetType().GetMethod(StorageManagerUtil.Add);
SetId(associatedModel, id);
- addMethod.Invoke(list, new[] { associatedModel });
+ addMethod.Invoke(list, new[] {associatedModel});
return id;
}
diff --git a/src/BlazorDB/StorageSet.cs b/src/BlazorDB/StorageSet.cs
index 76d5806..121be53 100644
--- a/src/BlazorDB/StorageSet.cs
+++ b/src/BlazorDB/StorageSet.cs
@@ -85,19 +85,7 @@ IEnumerator IEnumerable.GetEnumerator()
{
return List.GetEnumerator();
}
-
- //TODO: Consider using an "Id table"
- private int SetId(TModel item)
- {
- var prop = item.GetType().GetProperty("Id");
- if (prop == null) throw new ArgumentException("Model must have an Id property");
- var max = List.Select(i => (int) prop.GetValue(i)).Concat(new[] {0}).Max();
-
- var id = max + 1;
- prop.SetValue(item, id);
- return id;
- }
-
+
private static int GetId(TModel item)
{
var prop = item.GetType().GetProperty("Id");
diff --git a/src/Sample/Pages/Associations.cshtml b/src/Sample/Pages/Associations.cshtml
index 5da0f53..7f96bb0 100644
--- a/src/Sample/Pages/Associations.cshtml
+++ b/src/Sample/Pages/Associations.cshtml
@@ -18,6 +18,10 @@
Load Person
+Delete Test (Should throw exception)
+
+Add a Person with Addresses then delete Address
+
Result
@if (_person != null)
@@ -76,4 +80,16 @@
_person = Context.People[1];
StateHasChanged();
}
+
+ void OnDelete(UIMouseEventArgs e)
+ {
+ var person = new Person { FirstName = "John", LastName = "Smith" };
+ var address = new Address { Street = "221 Baker Streeet", City = "This should be a refrence to address since Address exists in the context" };
+ person.HomeAddress = address;
+ Context.People.Add(person);
+ Context.SaveChanges();
+
+ Context.Addresses.RemoveAt(0);
+ Context.SaveChanges();
+ }
}
\ No newline at end of file
diff --git a/src/Sample/global.json b/src/Sample/global.json
index 5502b6f..d65e3d5 100644
--- a/src/Sample/global.json
+++ b/src/Sample/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "2.1.300-preview2-008533"
+ "version": "2.1.300"
}
}