Skip to content
This repository has been archived by the owner on May 10, 2020. It is now read-only.

Commit

Permalink
Add Max Id to metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
chanan committed May 30, 2018
1 parent c6ce23c commit b82bff8
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 33 deletions.
1 change: 1 addition & 0 deletions src/BlazorDB/Storage/Metadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ internal class Metadata
public List<Guid> Guids { get; set; }
public string ModelName { get; set; }
public string ContextName { get; set; }
public int MaxId { get; set; }
}
}
109 changes: 76 additions & 33 deletions src/BlazorDB/Storage/StorageManagerSave.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,90 +15,131 @@ public int SaveContextToLocalStorage(StorageContext context)
var contextType = context.GetType();
//Logger.ContextSaved(contextType);
var storageSets = StorageManagerUtil.GetStorageSets(contextType);
total = SaveStorageSets(context, total, contextType, storageSets);
var metadataMap = LoadMetadataList(context, storageSets, contextType);
total = SaveStorageSets(context, total, contextType, storageSets, metadataMap);
//Logger.EndGroup();
return total;
}

private static IReadOnlyDictionary<string, Metadata> LoadMetadataList(StorageContext context, IEnumerable<PropertyInfo> storageSets, Type contextType)
{
var map = new Dictionary<string, Metadata>();
foreach (var prop in storageSets)
{
var modelType = prop.PropertyType.GetGenericArguments()[0];
var storageTableName = Util.GetStorageTableName(contextType, modelType);
var metadata = StorageManagerUtil.LoadMetadata(storageTableName) ?? new Metadata
{
Guids = new List<Guid>(),
ContextName = Util.GetFullyQualifiedTypeName(context.GetType()),
ModelName = Util.GetFullyQualifiedTypeName(modelType)
};
map.Add(Util.GetFullyQualifiedTypeName(modelType), metadata);
}

return map;
}

private static int SaveStorageSets(StorageContext context, int total, Type contextType,
List<PropertyInfo> storageSets)
List<PropertyInfo> storageSets, IReadOnlyDictionary<string, Metadata> metadataMap)
{
foreach (var prop in storageSets)
{
var storageSetValue = prop.GetValue(context);
var modelType = prop.PropertyType.GetGenericArguments()[0];
var storageTableName = Util.GetStorageTableName(contextType, modelType);
EnsureAllModelsHaveIds(storageSetValue, modelType);
EnsureAllAssociationsHaveIds(context, storageSetValue, modelType, storageSets);


EnsureAllModelsHaveIds(storageSetValue, modelType, metadataMap);
EnsureAllAssociationsHaveIds(context, storageSetValue, modelType, storageSets, metadataMap);

var guids = SaveModels(context, storageSetValue, modelType, storageTableName, storageSets);
var guids = SaveModels(storageSetValue, modelType, storageTableName, storageSets);
total += guids.Count;
var oldMetadata = StorageManagerUtil.LoadMetadata(storageTableName);
SaveMetadata(storageTableName, guids, contextType, modelType);
if (oldMetadata != null) DeleteOldModelsFromStorage(oldMetadata, storageTableName);
var oldMetadata = metadataMap[Util.GetFullyQualifiedTypeName(modelType)];
SaveMetadata(storageTableName, guids, contextType, modelType, oldMetadata);
DeleteOldModelsFromStorage(oldMetadata, storageTableName);
Logger.StorageSetSaved(modelType, guids.Count);
}

return total;
}

private static void EnsureAllAssociationsHaveIds(StorageContext context, object storageSetValue, Type modelType, List<PropertyInfo> storageSets)
private static void EnsureAllAssociationsHaveIds(StorageContext context, object storageSetValue, Type modelType, List<PropertyInfo> storageSets, IReadOnlyDictionary<string, Metadata> metadataMap)
{
var storageSetType = StorageManagerUtil.GenericStorageSetType.MakeGenericType(modelType);
var method = storageSetType.GetMethod(StorageManagerUtil.GetEnumerator);
var enumerator = (IEnumerator)method.Invoke(storageSetValue, new object[] { });
enumerator.Reset();
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, model, prop, storageSets);


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 EnsureOneAssociationHasId(StorageContext context, object model, PropertyInfo prop, List<PropertyInfo> storageSets)
private static void EnsureManyAssociationHasId(StorageContext context, object listObject, PropertyInfo prop, List<PropertyInfo> storageSets, IReadOnlyDictionary<string, Metadata> metadataMap)
{
Console.WriteLine("listObject: {0}", listObject);
var method = listObject.GetType().GetMethod(StorageManagerUtil.GetEnumerator);
var enumerator = (IEnumerator)method.Invoke(listObject, new object[] { });
while (enumerator.MoveNext())
{
var model = enumerator.Current;
EnsureOneAssociationHasId(context, model, prop.PropertyType.GetGenericArguments()[0], storageSets, metadataMap);
}
}

private static void EnsureOneAssociationHasId(StorageContext context, object associatedModel, Type propType, List<PropertyInfo> storageSets, IReadOnlyDictionary<string, Metadata> metadataMap)
{
var associatedModel = prop.GetValue(model);
var idProp = GetIdProperty(associatedModel);
var id = Convert.ToString(idProp.GetValue(associatedModel));
var metadata = metadataMap[Util.GetFullyQualifiedTypeName(propType)];
Console.WriteLine("metadata: {0}", metadata.ModelName);
Console.WriteLine("maxId: {0}", metadata.MaxId);
Console.WriteLine("id: {0}", id);
if (id == "0") SaveAssociationModel(context, associatedModel, prop, storageSets);
if (id == "0")
{
metadata.MaxId = metadata.MaxId + 1;
SaveAssociationModel(context, associatedModel, propType, storageSets, metadata.MaxId);
}
Console.WriteLine("maxId: {0}", metadata.MaxId);
}

private static void EnsureAllModelsHaveIds(object storageSetValue, Type modelType)
private static void EnsureAllModelsHaveIds(object storageSetValue, Type modelType, IReadOnlyDictionary<string, Metadata> 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 maxId = GetMaxId(enumerator);
enumerator.Reset();
while (enumerator.MoveNext())
{
var model = enumerator.Current;
if (GetId(model) == 0) SetId(model, ++maxId);
if (GetId(model) == 0)
{
metadata.MaxId = metadata.MaxId + 1;
SetId(model, metadata.MaxId);
}
}
}

private static void SaveMetadata(string storageTableName, List<Guid> guids, Type context, Type modelType)
private static void SaveMetadata(string storageTableName, List<Guid> guids, Type context, Type modelType, Metadata oldMetadata)
{
var metadata = new Metadata
{
Guids = guids,
ContextName = Util.GetFullyQualifiedTypeName(context),
ModelName = Util.GetFullyQualifiedTypeName(modelType)
ModelName = Util.GetFullyQualifiedTypeName(modelType),
MaxId = oldMetadata.MaxId
};
var name = $"{storageTableName}-{StorageManagerUtil.Metadata}";
BlazorDBInterop.SetItem(name, JsonUtil.Serialize(metadata), false);
}

private static List<Guid> SaveModels(StorageContext context, object storageSetValue, Type modelType, string storageTableName,
private static List<Guid> SaveModels(object storageSetValue, Type modelType, string storageTableName,
List<PropertyInfo> storageSets)
{
var guids = new List<Guid>();
Expand All @@ -111,7 +152,7 @@ private static List<Guid> SaveModels(StorageContext context, object storageSetVa
guids.Add(guid);
var model = enumerator.Current;
var name = $"{storageTableName}-{guid}";
var serializedModel = ScanModelForAssociations(context, storageSetValue, model, storageSets, JsonUtil.Serialize(model));
var serializedModel = ScanModelForAssociations(model, storageSets, JsonUtil.Serialize(model));
BlazorDBInterop.SetItem(name, serializedModel, false);
}

Expand Down Expand Up @@ -140,15 +181,15 @@ private static void DeleteOldModelsFromStorage(Metadata metadata, string storage
}
}

private static string ScanModelForAssociations(StorageContext context, object storageSetValue, object model, List<PropertyInfo> storageSets,
private static string ScanModelForAssociations(object model, List<PropertyInfo> storageSets,
string serializedModel)
{
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 (StorageManagerUtil.IsInContext(storageSets, prop)) result = FixOneAssociation(context, storageSetValue, model, prop, result, storageSets);
if (StorageManagerUtil.IsInContext(storageSets, prop)) result = FixOneAssociation(model, prop, result);
if (StorageManagerUtil.IsListInContext(storageSets, prop))
result = FixManyAssociation(model, prop, result);
}
Expand All @@ -170,7 +211,7 @@ private static string FixManyAssociation(object model, PropertyInfo prop, string
return result;
}

private static string FixOneAssociation(StorageContext context, object storageSetValue, object model, PropertyInfo prop, string result, List<PropertyInfo> storageSets)
private static string FixOneAssociation(object model, PropertyInfo prop, string result)
{
var associatedModel = prop.GetValue(model);
var idProp = GetIdProperty(associatedModel);
Expand All @@ -182,22 +223,24 @@ private static string FixOneAssociation(StorageContext context, object storageSe
return result;
}

private static string SaveAssociationModel(StorageContext context, object associatedModel, PropertyInfo prop, List<PropertyInfo> storageSets)
private static int SaveAssociationModel(StorageContext context, object associatedModel, Type propType, IEnumerable<PropertyInfo> storageSets, int id)
{
Console.WriteLine("SaveAssociationModel id: {0}", id);
Console.WriteLine("associatedModel: {0}", associatedModel);
Console.WriteLine("propType: {0}", propType);
var q = from p in storageSets
where p.PropertyType.GetGenericArguments()[0] == prop.PropertyType
select p;
where p.PropertyType.GetGenericArguments()[0] == propType
select p;
var storeageSetProp = q.Single();
Console.WriteLine("storeageSetProp: {0}", storeageSetProp);
var storeageSet = storeageSetProp.GetValue(context);
Console.WriteLine("storeageSet: {0}", storeageSet);
var listProp = storeageSet.GetType().GetProperty(StorageManagerUtil.List, StorageManagerUtil.Flags);
var list = listProp.GetValue(storeageSet);
var addMethod = list.GetType().GetMethod(StorageManagerUtil.Add);
SetId(associatedModel, 999);
SetId(associatedModel, id);
addMethod.Invoke(list, new[] { associatedModel });
return "999";
return id;
}

private static string ReplaceModelWithId(string result, string serializedItem, string id)
Expand Down
3 changes: 3 additions & 0 deletions src/Sample/Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
{
//In this case, address gets serailized as part of the object because Address is not in the Context
var person = new Person { FirstName = "John", LastName = "Smith", HomeAddress = new Address { Street = "221 Baker Street", City = "This should be part of the json, since address is not in context (Very long city)" } };
var address1 = new Address { Street = "Many test 1", City = "Saved as a reference" };
var address2 = new Address { Street = "Many test 2", City = "Saved as a reference" };
person.OtherAddresses = new List<Address> { address1, address2 };
Context.People.Add(person);
}

Expand Down

0 comments on commit b82bff8

Please sign in to comment.