/// <summary> /// Gets a property's value /// </summary> public static object GetValue(object obj, string propertyName) { if (obj is IDwarf) { var type = DwarfHelper.DeProxyfy(obj); if (!Cfg.PropertyExpressions[type].ContainsKey(propertyName)) { throw new ApplicationException(type.Name + " doesn't have a property: " + propertyName); } return(Cfg.PropertyExpressions[type][propertyName].GetValue(obj)); } else { var type = obj.GetType(); var pi = type.GetProperty(propertyName); if (pi == null) { throw new ApplicationException(type.Name + " doesn't have a property: " + propertyName); } return(pi.GetValue(obj, null)); } }
/// <summary> /// Restores the object's properties to their original values /// </summary> public void Reset() { if (originalValues == null) { throw new InvalidOperationException("You cannot reset a new object. Just create a new one?"); } foreach (var kvp in originalValues) { PropertyHelper.SetValue(this, kvp.Key, kvp.Value); } ResetFKProperties(); foreach (var ep in DwarfHelper.GetOneToManyProperties(this)) { var key = GetCollectionKey(ep.Name); CacheManager.RemoveKey(key); } foreach (var ep in DwarfHelper.GetManyToManyProperties(this)) { var key = GetCollectionKey(ep.Name); CacheManager.RemoveKey(key); } if (oneToManyAlternateKeys != null) { oneToManyAlternateKeys.Clear(); } }
/// <summary> /// Sets a property's value /// </summary> public static void SetValue(object obj, string propertyName, object value) { if (obj is IDwarf) { var type = DwarfHelper.DeProxyfy(obj); if (!Cfg.PropertyExpressions[type].ContainsKey(propertyName)) { throw new ApplicationException(type.Name + " doesn't have a property: " + propertyName); } var ep = Cfg.PropertyExpressions[type][propertyName]; if (ep.CanWrite) { ep.SetValue(obj, value); } } else { var type = obj.GetType(); var pi = type.GetProperty(propertyName); if (pi == null) { throw new ApplicationException(type.Name + " doesn't have a property: " + propertyName); } if (pi.CanWrite) { pi.SetValue(obj, value, null); } } }
public static ExpressionProperty GetProperty(Type type, string propertyName) { DwarfHelper.DeProxyfy(ref type); return(Cfg.PropertyExpressions[type].ContainsKey(propertyName) ? Cfg.PropertyExpressions[type][propertyName] : null); }
internal static string GetUserKey <T>(T obj, Guid?alternateId = null) where T : Dwarf <T>, new() { var objectKey = typeof(T).Implements <ICompositeId>() ? DwarfHelper.GetUniqueKeyForCompositeId(obj) : alternateId.HasValue ? alternateId.Value.ToString() : obj.Id.ToString(); return(GetUserKey(objectKey)); }
/// <summary> /// Default Constructor /// </summary> public DwarfList() { if (typeof(T).Implements <IDwarf>()) { sortProperty = DwarfHelper.GetOrderByProperty <T>(); sortAsc = DwarfHelper.GetOrderByDirection <T>().IsNullOrEmpty(); } }
private void OnBeforeDeleteInternal() { //We want to persist all the Inverse OneToManyCollection upon deletion. Let's remove all lists that doesn't //need persistance first (all objects therein will be deleted in the database via delete cascades anyways) foreach (var pi in DwarfHelper.GetOneToManyProperties(this)) { var propertyAtt = OneToManyAttribute.GetAttribute(pi.ContainedProperty); if (propertyAtt == null) { throw new NullReferenceException(pi.Name + " is missing the OneToMany attribute..."); } if (!propertyAtt.IsInverse) { continue; } var obj = (IDwarfList)pi.GetValue(this); var owningProp = oneToManyAlternateKeys.ContainsKey(pi.Name) ? oneToManyAlternateKeys[pi.Name] : GetType().Name; obj.Cast <IDwarf>().ForEachX(x => PropertyHelper.SetValue(x, owningProp, null)); obj.SaveAllInternal <T>(); } if (DbContextHelper <T> .DbContext.IsAuditLoggingSuspended || DwarfContext <T> .GetConfiguration().AuditLogService == null) { return; } var traces = (from ep in DwarfHelper.GetDBProperties(GetType()).Where(x => !x.Name.Equals("Id")) let oldValue = originalValues[ep.Name] where oldValue != null && (oldValue is string? !string.IsNullOrEmpty(oldValue.ToString()) : true) select new AuditLogEventTrace { PropertyName = ep.Name, OriginalValue = oldValue }).ToArray(); var collectionTraces = (from ep in DwarfHelper.GetGemListProperties(GetType()) let oldValue = (IGemList)ep.GetValue(this) where oldValue != null && oldValue.Count > 0 select new AuditLogEventTrace { PropertyName = ep.Name, OriginalValue = oldValue }).ToArray(); var many2ManyTraces = (from ep in DwarfHelper.GetManyToManyProperties(GetType()) let oldValue = ep.GetValue(this) where oldValue != null && ((IList)oldValue).Count > 0 select new AuditLogEventTrace { PropertyName = ep.Name, OriginalValue = oldValue }).ToArray(); DwarfContext <T> .GetConfiguration().AuditLogService.Logg(this, AuditLogTypes.Deleted, traces.Union(collectionTraces).Union(many2ManyTraces).ToArray()); }
/// <summary> /// Returns true if the object contains faulty Foreign Key values /// </summary> private static IEnumerable <string> FaultyForeignKeys(IDwarf obj) { foreach (var pi in Cfg.FKProperties[DwarfHelper.DeProxyfy(obj)]) { var att = DwarfPropertyAttribute.GetAttribute(pi.ContainedProperty); if (!att.IsNullable && (pi.GetValue(obj) == null || !((IDwarf)pi.GetValue(obj)).IsSaved)) { yield return(pi.Name); } } }
/// <summary> /// Restores the object's properties to their original values /// </summary> public void Refresh() { //Fetch the original values from the database (bypass the cache...) var originalObject = DwarfContext <T> .GetDatabase().SelectReferencing <T>(new QueryBuilder().Select <T>().From <T>().Where(this, Cfg.PKProperties[DwarfHelper.DeProxyfy(this)]), false, true).FirstOrDefault(); if (originalObject != null) { foreach (var ep in DwarfHelper.GetDBProperties(GetType())) { SetOriginalValue(ep.Name, ep.GetValue(originalObject)); } } //Else should we throw an exception since the object has been deleted from the DB? Reset(); }
/// <summary> /// Creates and returns an AuditLogEventTrace object for every modified OneToMany relationship /// </summary> private IEnumerable <AuditLogEventTrace> CreateTraceEventsForOneToMany() { if (!IsSaved) { return(new AuditLogEventTrace[0]); } return(from ep in DwarfHelper.GetOneToManyProperties(this) where IsCollectionInitialized(ep.ContainedProperty) let list = ep.GetValue(this) let adds = ((IList)ep.PropertyType.GetMethod("GetAddedItems").Invoke(list, null)).Cast <IDwarf>().ToList() let dels = ((IList)ep.PropertyType.GetMethod("GetDeletedItems").Invoke(list, null)).Cast <IDwarf>().ToList() where adds.Count > 0 || dels.Count > 0 select new AuditLogEventTrace { PropertyName = ep.Name, NewValue = list }); }
/// <summary> /// Stores an AuditLog object for the ongoing transaction /// </summary> public static IAuditLog Logg <T>(IDwarf obj, AuditLogTypes auditLogType, params AuditLogEventTrace[] auditUpdateEvents) { var type = DwarfHelper.DeProxyfy(obj); if (type.Implements <IAuditLogless>() || type.Implements <IAuditLog>()) { return(null); } var al = new AuditLog { ClassType = type.Name, AuditLogType = auditLogType, UserName = DwarfContext <T> .GetConfiguration().UserService.CurrentUser != null ? DwarfContext <T> .GetConfiguration().UserService.CurrentUser.UserName : string.Empty, TimeStamp = DateTime.Now, ObjectValue = obj.ToString(), }; if (!type.Implements <ICompositeId>()) { al.ObjectId = obj.Id.ToString(); } else { foreach (var ep in DwarfHelper.GetPKProperties(type)) { al.ObjectId += string.Format("[{0}: {1}]", ep.Name, ep.GetValue(obj)); } } if (auditLogType != AuditLogTypes.Created) { al.AuditDetails = "<?xml version=\"1.0\"?><Properties>"; foreach (var auditUpdateEvent in auditUpdateEvents) { al.AuditDetails += auditUpdateEvent.ToXml().ToString(); } al.AuditDetails += "</Properties>"; } DwarfContext <T> .GetDatabase().Insert <T, AuditLog>(al); return(al); }
/// <summary> /// Helper method for the proxy classes's MSIL generated foreign key methods /// </summary> protected TY GetProperty <TY>(string propertyName, ref TY backingField, ref bool isAccessed) where TY : Dwarf <TY>, new() { if (isAccessed) { return(backingField); } var orgValue = GetOriginalValue(propertyName); if (orgValue != null) { backingField = (TY)Cfg.LoadExpressions[DwarfHelper.DeProxyfy(typeof(TY))]((Guid)orgValue); } isAccessed = true; return(backingField); }
/// <summary> /// Creates and returns an AuditLogEventTrace object for every modified property /// </summary> private AuditLogEventTrace[] CreateTraceEventsForProperties() { if (!IsSaved) { return(new AuditLogEventTrace[0]); } if (originalValues == null) { var fromDB = !typeof(T).Implements <ICompositeId>() ? Load(Id.Value) : Load(DwarfHelper.GetPKProperties <T>().Select(x => new WhereCondition <T> { ColumnPi = x.ContainedProperty, Value = x.GetValue(this) }).ToArray()); if (fromDB == null) { return(new AuditLogEventTrace[0]); } originalValues = fromDB.originalValues; } var dbProps = from ep in DwarfHelper.GetDBProperties(GetType()) let oldValue = originalValues[ep.Name] let x = ep.GetValue(this) let newValue = x is IDwarf ? ((IDwarf)ep.GetValue(this)).Id : ep.GetValue(this) where (oldValue != null && !oldValue.Equals(newValue)) || (oldValue == null && newValue != null) select new AuditLogEventTrace { PropertyName = ep.Name, OriginalValue = oldValue, NewValue = newValue }; var collections = from ep in DwarfHelper.GetGemListProperties(GetType()) where IsCollectionInitialized(ep.ContainedProperty) let x = (IGemList)ep.GetValue(this) let newValue = x let oldValue = x.Parse((string)originalValues[ep.Name] ?? string.Empty) where (oldValue != null && !oldValue.ComparisonString.Equals(newValue.ComparisonString)) || (oldValue == null && newValue != null) select new AuditLogEventTrace { PropertyName = ep.Name, OriginalValue = oldValue, NewValue = newValue }; return(dbProps.Concat(collections).ToArray()); }
/// <summary> /// Automatically handles default persistance operations over DwarfLists for OneToManyRelationships. /// Should a manual persistance be used via PersistOneToMany, do so before the base call in AppendStore /// </summary> private void PersistOneToManyCollections() { foreach (var pi in DwarfHelper.GetOneToManyProperties(this)) { if (!IsCollectionInitialized(pi.ContainedProperty)) { continue; } var propertyName = pi.Name; var propertyAtt = OneToManyAttribute.GetAttribute(pi.ContainedProperty); if (propertyAtt == null) { throw new NullReferenceException(propertyName + " is missing the OneToMany attribute..."); } var obj = (IDwarfList)PropertyHelper.GetValue(this, propertyName); var list = obj.Cast <IDwarf>().ToList(); var owningProp = oneToManyAlternateKeys.ContainsKey(propertyName) ? oneToManyAlternateKeys[propertyName] : GetType().Name; list.ForEach(x => PropertyHelper.SetValue(x, owningProp, this)); var deleteObjects = obj.GetDeletedItems(); if (propertyAtt.IsInverse) { deleteObjects.ForEach(x => PropertyHelper.SetValue(x, owningProp, null)); deleteObjects.SaveAllInternal <T>(); } else { deleteObjects.DeleteAllInternal <T>(); } list.SaveAllInternal <T>(); oneToManyAlternateKeys.Remove(propertyName); } }
/// <summary> /// Dwarf comparison is done via the Id property /// </summary> public override bool Equals(object obj) { if (obj is IDwarf) { var type = DwarfHelper.DeProxyfy(GetType()); if (type != DwarfHelper.DeProxyfy(obj)) { return(false); } if (!type.Implements <ICompositeId>()) { //Should both objects not be stored they'll both have null as Id, thus we check all the properties to find out if they might be the same object //We also dubbelcheck all unique properties (if existant) to make sure they're NOT equal if (!Id.HasValue && !((IDwarf)obj).Id.HasValue) { var propertiesMatch = DwarfHelper.GetDBProperties(type).Where(ep => ep.GetValue(this) != null && ep.GetValue(obj) != null).All(pi => pi.GetValue(this).Equals(pi.GetValue(obj))); var uniqueProps = DwarfHelper.GetUniqueDBProperties <T>(type).ToList(); if (uniqueProps.Any()) { var uniquePropertiesMatch = uniqueProps.All(ep => ep.GetValue(this) == null ? ep.GetValue(obj) == null : ep.GetValue(this).Equals(ep.GetValue(obj))); return(uniquePropertiesMatch && propertiesMatch); } return(propertiesMatch); } return(Id == ((IDwarf)obj).Id); } return(Cfg.PKProperties[type].All(ep => ep.GetValue(this) == null ? ep.GetValue(obj) == null : ep.GetValue(this).Equals(ep.GetValue(obj)))); } return(false); }
/// <summary> /// Append the Save method with additional modifications /// </summary> private void OnAfterSaveInternal() { foreach (var ep in DwarfHelper.GetDBProperties(GetType())) { SetOriginalValue(ep.Name, ep.GetValue(this)); } foreach (var ep in DwarfHelper.GetGemListProperties(GetType())) { if (IsCollectionInitialized(ep.ContainedProperty)) { SetOriginalValue(ep.Name, ep.GetValue(this)); } } foreach (var ep in DwarfHelper.GetManyToManyProperties(GetType())) { if (IsCollectionInitialized(ep.ContainedProperty)) { SetOriginalValue(ep.Name, ep.GetValue(this)); } } }
/// <summary> /// Automatically handles default persistance operations over DwarfLists for ManyToManyRelationships. /// Should a manual persistance be used via PersistManyToMany, do so before the base call in AppendStore /// </summary> private void PersistManyToManyCollections() { foreach (var pi in DwarfHelper.GetManyToManyProperties(this)) { if (!IsCollectionInitialized(pi.ContainedProperty)) { continue; } var tableName = ManyToManyAttribute.GetTableName(GetType(), pi.ContainedProperty); var obj = (IDwarfList)pi.GetValue(this); foreach (var deletedItem in obj.GetDeletedItems()) { DeleteManyToMany(this, deletedItem, tableName); } foreach (var addedItem in obj.GetAddedItems()) { PersistManyToMany(this, addedItem, tableName); } } }
/// <summary> /// Returns the database object for the supplied typeq /// </summary> internal static IDatabase GetDatabase(Type type) { return(Cfg.Databases[DwarfHelper.DeProxyfy(type).Assembly]); }
internal static IEnumerable <ExpressionProperty> GetProperties(Type type) { DwarfHelper.DeProxyfy(ref type); return(Cfg.PropertyExpressions[type].Values); }
/// <summary> /// Returns true if the supplied object contains a property by the specified name /// </summary> public static bool HasProperty(Type type, string propertyName) { return(Cfg.PropertyExpressions[DwarfHelper.DeProxyfy(type)].ContainsKey(propertyName)); }