示例#1
0
 public void AfterSave(ICustomRepository repository, User itemDbEntity, long objectId)
 {
     itemDbEntity.ClearPropertChanges();// clear all changes.
     // lets do some changes here, when the item have updated..
     itemDbEntity.Password = MethodHelper.EncodeStringToBase64(itemDbEntity.Password);
     // and now we want to save this change to the database
     itemDbEntity.State = ItemState.Changed;
     // the lightdatatable will now that it need to update the database agen.
 }
示例#2
0
        private object Save(object o, bool isIndependentData, bool updateOnly = false, List <string> ignoredProperties = null, string lastProperty = null)
        {
            try
            {
                if (ignoredProperties == null)
                {
                    ignoredProperties = new List <string>();
                }
                if (lastProperty == null)
                {
                    lastProperty = string.Empty; // not valid name
                }
                GlobalConfiguration.Log?.Info("Save", o);
                _repository.CreateTransaction();
                var props      = DeepCloner.GetFastDeepClonerProperties(o.GetType());
                var primaryKey = o.GetPrimaryKey();

                if (primaryKey == null)
                {
                    throw new EntityException("Object must have a PrimaryKey");
                }

                var primaryKeyId        = !Extension.ObjectIsNew(o.GetPrimaryKeyValue()) ? o.GetPrimaryKeyValue() : null;
                var availableColumns    = _repository.GetColumnSchema(o.GetType());
                var objectRules         = o.GetType().GetCustomAttribute <Rule>();
                var tableName           = o.GetType().TableName().GetName(_repository.DataBaseTypes);
                var primaryKeySubstitut = !primaryKey.GetCustomAttribute <PrimaryKey>().AutoGenerate ? primaryKeyId : null;

                object dbTrigger = null;
                if (objectRules != null && !CachedIDbRuleTrigger.ContainsKey(o.GetType()))
                {
                    dbTrigger = objectRules.RuleType.CreateInstance();
                    CachedIDbRuleTrigger.Add(o.GetType(), dbTrigger);
                }
                else if (objectRules != null || CachedIDbRuleTrigger.ContainsKey(o.GetType()))
                {
                    dbTrigger = CachedIDbRuleTrigger[o.GetType()];
                }

                if (primaryKeyId != null && !updateOnly) // lets attach the object
                {
                    var data = GetById(primaryKeyId, o.GetType());
                    if (data == null)
                    {
                        primaryKeyId = null;
                        o.SetPrimaryKeyValue();
                    }
                    else
                    {
                        if (!_repository.IsAttached(o))
                        {
                            _repository.Attach(data);
                        }

                        var changes = _repository.GetObjectChanges(o);
                        foreach (var item in props.Where(x => x.CanRead && !changes.Any(a => a.PropertyName == x.Name) && (x.IsInternalType || x.ContainAttribute <JsonDocument>())))
                        {
                            item.SetValue(o, item.GetValue(data));
                        }
                    }
                }

                if (!updateOnly)
                {
                    dbTrigger?.GetType().GetMethod("BeforeSave").Invoke(dbTrigger, new List <object>()
                    {
                        _repository, o
                    }.ToArray());                                                                                                    // Check the Rule before save
                }
                object tempPrimaryKey = null;
                var    sql            = "UPDATE " + (o.GetType().TableName().GetName(_repository.DataBaseTypes)) + " SET ";
                var    cols           = props.FindAll(x => x.CanRead && (availableColumns.ContainsKey(x.GetPropertyName()) || availableColumns.ContainsKey(x.GetPropertyName().ToLower())) && (x.IsInternalType || x.ContainAttribute <JsonDocument>() || x.ContainAttribute <XmlDocument>()) && !x.ContainAttribute <ExcludeFromAbstract>() && x.GetCustomAttribute <PrimaryKey>() == null);

                // Clean out all unwanted properties
                if (ignoredProperties.Any())
                {
                    cols = cols.FindAll(x => !ignoredProperties.Any(a => a == x.Name || a == (o.GetType().Name + "." + x.Name) || a == (lastProperty + "." + x.Name)));
                }

                if (primaryKeyId == null)
                {
                    if (primaryKey.PropertyType.IsNumeric() && primaryKey.GetCustomAttribute <PrimaryKey>().AutoGenerate)
                    {
                        sql  = "INSERT INTO " + tableName + "(" + string.Join(",", cols.Select(x => "[" + x.GetPropertyName() + "]")) + ") Values(";
                        sql += string.Join(",", cols.Select(x => "@" + x.GetPropertyName())) + ");";
                        sql += _repository.DataBaseTypes == DataBaseTypes.Sqllight ? " select last_insert_rowid();" : (_repository.DataBaseTypes != DataBaseTypes.PostgreSql ? " SELECT IDENT_CURRENT('" + tableName + "');" : " SELECT currval('" + string.Format("{0}_{1}_seq", tableName, primaryKey.GetPropertyName()) + "');");
                    }
                    else
                    {
                        var colList = new List <IFastDeepClonerProperty>();
                        tempPrimaryKey = primaryKeySubstitut == null?Guid.NewGuid() : primaryKeySubstitut;

                        if (primaryKeySubstitut == null && primaryKey.PropertyType.IsNumeric())
                        {
                            tempPrimaryKey = _repository.ExecuteScalar(_repository.GetSqlCommand(String.Format("SELECT MAX([{0}]) FROM {1}", primaryKey.GetPropertyName(), tableName))).ConvertValue <long>() + 1;
                        }
                        else if (primaryKey.PropertyType == typeof(string))
                        {
                            tempPrimaryKey = tempPrimaryKey.ToString();
                        }
                        colList.Insert(0, primaryKey);
                        colList.AddRange(cols);
                        sql  = "INSERT INTO " + tableName + "(" + string.Join(",", colList.Select(x => "[" + x.GetPropertyName() + "]")) + ") Values(";
                        sql += string.Join(",", colList.Select(x => "@" + x.GetPropertyName())) + "); select '" + tempPrimaryKey + "'";
                    }
                }
                else
                {
                    sql += string.Join(",", cols.Select(x => "[" + x.GetPropertyName() + "]" + " = @" + x.GetPropertyName()));
                    sql += Querys.Where(_repository.DataBaseTypes).Column(o.GetType().GetActualType().GetPrimaryKey().GetPropertyName()).Equal(primaryKeyId).Execute();
                }

                var cmd = _repository.GetSqlCommand(sql);
                if ((!primaryKey.PropertyType.IsNumeric() || !primaryKey.GetCustomAttribute <PrimaryKey>().AutoGenerate) && primaryKeyId == null)
                {
                    _repository.AddInnerParameter(cmd, primaryKey.GetPropertyName(), tempPrimaryKey);
                }


                foreach (var col in cols)
                {
                    var v = col.GetValue(o);
                    var defaultOnEmpty = col.GetCustomAttribute <DefaultOnEmpty>();
                    if (col.ContainAttribute <ForeignKey>() && (v?.ObjectIsNew() ?? true))
                    {
                        var ob              = props.FirstOrDefault(x => (x.PropertyType == col.GetCustomAttribute <ForeignKey>().Type) && (string.IsNullOrEmpty(col.GetCustomAttribute <ForeignKey>().PropertyName) || col.GetCustomAttribute <ForeignKey>().PropertyName == x.Name));
                        var obValue         = ob?.GetValue(o);
                        var independentData = ob?.GetCustomAttribute <IndependentData>() != null;
                        if (obValue != null)
                        {
                            v = obValue.GetType().GetPrimaryKey().GetValue(obValue)?.ObjectIsNew() ?? true?
                                Save(obValue, independentData, false, ignoredProperties, ob.Name) :
                                    obValue.GetType().GetPrimaryKey().GetValue(obValue);

                            col.SetValue(o, v);
                        }
                    }

                    if (col.ContainAttribute <ToBase64String>())
                    {
                        if (!v?.ConvertValue <string>().IsBase64String() ?? false)
                        {
                            v = MethodHelper.EncodeStringToBase64(v.ConvertValue <string>());
                        }
                    }

                    if (col.ContainAttribute <JsonDocument>())
                    {
                        v = v?.ToJson();
                    }

                    if (col.ContainAttribute <XmlDocument>())
                    {
                        v = v?.ToXml();
                    }

                    if (col.ContainAttribute <Stringify>() || col.ContainAttribute <DataEncode>())
                    {
                        v = v?.ConvertValue <string>();
                    }

                    if (col.ContainAttribute <DataEncode>())
                    {
                        if (col.PropertyType != typeof(string))
                        {
                            throw new EntityException(string.Format("Property {0} Contain DataEncode. PropertyType must be of type String .", col.FullName));
                        }
                        v = new DataCipher(col.GetCustomAttribute <DataEncode>().Key, col.GetCustomAttribute <DataEncode>().KeySize).Encrypt(v.ToString());
                    }

                    if (col.ContainAttribute <NotNullable>() && v == null && defaultOnEmpty == null)
                    {
                        throw new EntityException(string.Format("Property {0} dose not allow null.", col.FullName));
                    }


                    if (v == null && defaultOnEmpty != null)
                    {
                        v = defaultOnEmpty.Value.ConvertValue(col.PropertyType);
                    }

                    _repository.AddInnerParameter(cmd, col.GetPropertyName(), v);
                }

                if (primaryKeyId == null)
                {
                    primaryKeyId = _repository.ExecuteScalar(cmd).ConvertValue(primaryKey.PropertyType);
                }
                else
                {
                    _repository.ExecuteNonQuery(cmd);
                }
                var oState = dbTrigger != null?DeepCloner.Clone(o) : null;

                if (updateOnly)
                {
                    return(primaryKeyId);
                }
                dbTrigger?.GetType().GetMethod("AfterSave").Invoke(dbTrigger, new List <object>()
                {
                    _repository, o, primaryKeyId
                }.ToArray());                                                                                                                 // Check the Rule before save

                foreach (var prop in props.Where(x => !x.IsInternalType && !x.ContainAttribute <JsonDocument>() && !x.ContainAttribute <XmlDocument>() && !x.ContainAttribute <ExcludeFromAbstract>()))
                {
                    var independentData = prop.GetCustomAttribute <IndependentData>() != null;
                    var type            = prop.PropertyType.GetActualType();
                    var oValue          = prop.GetValue(o);
                    if (oValue == null)
                    {
                        continue;
                    }
                    var vList = oValue is IList ? (IList)oValue : new List <object>()
                    {
                        oValue
                    };

                    foreach (var item in vList)
                    {
                        var foreignKey = DeepCloner.GetFastDeepClonerProperties(item.GetType()).FirstOrDefault(x => x.GetCustomAttribute <ForeignKey>()?.Type == o.GetType() && string.IsNullOrEmpty(x.GetCustomAttribute <ForeignKey>().PropertyName));
                        foreignKey?.SetValue(item, primaryKeyId);
                        var res = Save(item, independentData, false, ignoredProperties, prop.Name);
                        foreignKey = props.FirstOrDefault(x => x.GetCustomAttribute <ForeignKey>()?.Type == type && (x.GetCustomAttribute <ForeignKey>().PropertyName == prop.Name || string.IsNullOrEmpty(x.GetCustomAttribute <ForeignKey>().PropertyName)));
                        if (foreignKey == null || !foreignKey.GetValue(o).ObjectIsNew())
                        {
                            continue;
                        }
                        if (o.GetType() == foreignKey.GetCustomAttribute <ForeignKey>().Type)
                        {
                            continue;
                        }
                        foreignKey.SetValue(o, res);
                    }
                }


                if (oState != null && _repository.GetObjectChanges(o, oState).Count > 0) // a change has been made outside the function Save then resave
                {
                    o.SetPrimaryKeyValue(primaryKeyId);
                    Save(o, false, true, ignoredProperties);
                }
                o.SetPrimaryKeyValue(primaryKeyId);
                _repository.Attach(o, true);
                return(primaryKeyId);
            }
            catch (Exception e)
            {
                GlobalConfiguration.Log?.Error(e);
                _repository.Rollback();
                throw;
            }
        }
示例#3
0
        private object Save(object o, bool isIndependentData, bool updateOnly = false)
        {
            try
            {
                _repository.CreateTransaction();
                var props      = DeepCloner.GetFastDeepClonerProperties(o.GetType());
                var primaryKey = o.GetPrimaryKey();

                if (primaryKey == null)
                {
                    throw new NullReferenceException("Object must have a PrimaryKey");
                }

                var primaryKeyId     = !Extension.ObjectIsNew(o.GetPrimaryKeyValue()) ? o.GetPrimaryKeyValue() : null;
                var availableColumns = ObjectColumns(o.GetType());
                var objectRules      = o.GetType().GetCustomAttribute <Rule>();
                var tableName        = o.GetType().GetCustomAttribute <Table>()?.Name ?? o.GetType().Name;


                object dbTrigger = null;
                if (objectRules != null && !CachedIDbRuleTrigger.ContainsKey(o.GetType()))
                {
                    dbTrigger = objectRules.RuleType.CreateInstance(true);
                    CachedIDbRuleTrigger.Add(o.GetType(), dbTrigger);
                }
                else if (objectRules != null)
                {
                    dbTrigger = CachedIDbRuleTrigger[o.GetType()];
                }

                if (primaryKeyId != null && !updateOnly) // lets attach the object
                {
                    var data = GetById(primaryKeyId, o.GetType());
                    if (data == null)
                    {
                        primaryKeyId = null;
                        o.SetPrimaryKeyValue();
                    }
                    else
                    {
                        if (!_repository.IsAttached(o))
                        {
                            _repository.Attach(data);
                        }

                        var changes = _repository.GetObjectChanges(o);
                        foreach (var item in props.Where(x => x.CanRead && !changes.Any(a => a.PropertyName == x.Name) && x.IsInternalType))
                        {
                            item.SetValue(o, item.GetValue(data));
                        }
                    }
                }

                if (!updateOnly)
                {
                    dbTrigger?.GetType().GetMethod("BeforeSave").Invoke(dbTrigger, new List <object>()
                    {
                        _repository, o
                    }.ToArray());                                                                                                    // Check the Rule before save
                }
                object tempPrimaryKey = null;
                var    sql            = "UPDATE [" + (o.GetType().GetCustomAttribute <Table>()?.Name ?? o.GetType().Name) + "] SET ";
                var    cols           = props.FindAll(x => availableColumns.FindByPrimaryKey <bool>(x.GetPropertyName()) && x.IsInternalType && !x.ContainAttribute <ExcludeFromAbstract>() && x.GetCustomAttribute <PrimaryKey>() == null);
                if (primaryKeyId == null)
                {
                    if (primaryKey.PropertyType.IsNumeric())
                    {
                        sql  = "INSERT INTO [" + tableName + "](" + string.Join(",", cols.Select(x => "[" + x.GetPropertyName() + "]")) + ") Values(";
                        sql += string.Join(",", cols.Select(x => "@" + x.GetPropertyName())) + ");";
                        sql += _repository.DataBaseTypes == DataBaseTypes.Sqllight ? " select last_insert_rowid();" : " SELECT IDENT_CURRENT('" + tableName + "');";
                    }
                    else
                    {
                        var colList = new List <IFastDeepClonerProperty>();
                        tempPrimaryKey = Guid.NewGuid();
                        colList.Insert(0, primaryKey);
                        colList.AddRange(cols);
                        sql  = "INSERT INTO [" + tableName + "](" + string.Join(",", colList.Select(x => "[" + x.GetPropertyName() + "]")) + ") Values(";
                        sql += string.Join(",", colList.Select(x => "@" + x.GetPropertyName())) + "); select '" + tempPrimaryKey + "'";
                    }
                }
                else
                {
                    sql += string.Join(",", cols.Select(x => "[" + x.GetPropertyName() + "]" + " = @" + x.GetPropertyName()));
                    sql += Querys.Where(_repository.DataBaseTypes).Column(o.GetType().GetActualType().GetPrimaryKey().GetPropertyName()).Equal(string.Format("Guid[{0}]", primaryKeyId), true).Execute();
                }

                var cmd = _repository.GetSqlCommand(sql);
                if (!primaryKey.PropertyType.IsNumeric() && primaryKeyId == null)
                {
                    _repository.AddInnerParameter(cmd, primaryKey.GetPropertyName(), tempPrimaryKey, _repository.GetSqlType(primaryKey.PropertyType));
                }


                foreach (var col in cols)
                {
                    var v = col.GetValue(o);
                    var defaultOnEmpty = col.GetCustomAttribute <DefaultOnEmpty>();
                    if (col.ContainAttribute <ForeignKey>() && (v?.ObjectIsNew() ?? true))
                    {
                        var ob              = props.FirstOrDefault(x => x.PropertyType == col.GetCustomAttribute <ForeignKey>().Type&& (string.IsNullOrEmpty(col.GetCustomAttribute <ForeignKey>().PropertyName) || col.GetCustomAttribute <ForeignKey>().PropertyName == x.Name));
                        var obValue         = ob?.GetValue(o);
                        var independentData = ob?.GetCustomAttribute <IndependentData>() != null;
                        if (obValue != null)
                        {
                            v = obValue.GetType().GetPrimaryKey().GetValue(obValue)?.ObjectIsNew() ?? true?
                                Save(obValue, independentData) :
                                    obValue.GetType().GetPrimaryKey().GetValue(obValue);

                            col.SetValue(o, v);
                        }
                    }

                    if (col.ContainAttribute <ToBase64String>())
                    {
                        if (!v?.ConvertValue <string>().IsBase64String() ?? false)
                        {
                            v = MethodHelper.EncodeStringToBase64(v.ConvertValue <string>());
                        }
                    }

                    if (col.ContainAttribute <StringFy>() || col.ContainAttribute <DataEncode>())
                    {
                        v = v?.ConvertValue <string>();
                    }

                    if (col.ContainAttribute <DataEncode>())
                    {
                        if (col.PropertyType != typeof(string))
                        {
                            throw new NoNullAllowedException(string.Format("Property {0} Contain DataEncode. PropertyType must be of type String .", col.FullName));
                        }
                        v = new DataCipher(col.GetCustomAttribute <DataEncode>().Key, col.GetCustomAttribute <DataEncode>().KeySize).Encrypt(v.ToString());
                    }

                    if (col.ContainAttribute <NotNullable>() && v == null && defaultOnEmpty == null)
                    {
                        throw new NoNullAllowedException(string.Format("Property {0} dose not allow null.", col.FullName));
                    }


                    if (v == null && defaultOnEmpty != null)
                    {
                        v = defaultOnEmpty.Value.ConvertValue(col.PropertyType);
                    }

                    _repository.AddInnerParameter(cmd, col.GetPropertyName(), v, (col.ContainAttribute <StringFy>() || col.ContainAttribute <DataEncode>() || col.ContainAttribute <ToBase64String>() ? _repository.GetSqlType(typeof(string)) : _repository.GetSqlType(col.PropertyType)));
                }

                if (primaryKeyId == null)
                {
                    primaryKeyId = _repository.ExecuteScalar(cmd).ConvertValue(primaryKey.PropertyType);
                }
                else
                {
                    _repository.ExecuteNonQuery(cmd);
                }
                var oState = dbTrigger != null?DeepCloner.Clone(o) : null;

                if (updateOnly)
                {
                    return(primaryKeyId);
                }
                dbTrigger?.GetType().GetMethod("AfterSave").Invoke(dbTrigger, new List <object>()
                {
                    _repository, o, primaryKeyId
                }.ToArray());                                                                                                                 // Check the Rule before save

                foreach (var prop in props.Where(x => !x.IsInternalType && !x.ContainAttribute <ExcludeFromAbstract>()))
                {
                    var independentData = prop.GetCustomAttribute <IndependentData>() != null;
                    var type            = prop.PropertyType.GetActualType();
                    var oValue          = prop.GetValue(o);
                    if (oValue == null)
                    {
                        continue;
                    }
                    var vList = oValue is IList ? (IList)oValue : new List <object>()
                    {
                        oValue
                    };

                    foreach (var item in vList)
                    {
                        var foreignKey = DeepCloner.GetFastDeepClonerProperties(item.GetType()).FirstOrDefault(x => x.GetCustomAttribute <ForeignKey>()?.Type == o.GetType() && string.IsNullOrEmpty(x.GetCustomAttribute <ForeignKey>().PropertyName));
                        foreignKey?.SetValue(item, primaryKeyId);
                        var res = Save(item, independentData);
                        foreignKey = props.FirstOrDefault(x => x.GetCustomAttribute <ForeignKey>()?.Type == type && (x.GetCustomAttribute <ForeignKey>().PropertyName == prop.Name || string.IsNullOrEmpty(x.GetCustomAttribute <ForeignKey>().PropertyName)));
                        if (foreignKey == null || !foreignKey.GetValue(o).ObjectIsNew())
                        {
                            continue;
                        }
                        if (o.GetType() == foreignKey.GetCustomAttribute <ForeignKey>().Type)
                        {
                            continue;
                        }
                        foreignKey.SetValue(o, res);
                    }
                }

                if (oState != null && _repository.GetObjectChanges(o, oState).Count > 0) // a change has been made outside the function Save then resave
                {
                    Save(o, false);
                }

                o.GetType().GetPrimaryKey().SetValue(o, primaryKeyId.ConvertValue(primaryKey.PropertyType));
                _repository.Attach(o, true);
                return(primaryKeyId);
            }
            catch
            {
                _repository.Rollback();
                throw;
            }
        }