internal Dictionary <string, myPropInfo> Getproperties(Type type, string typename) { Dictionary <string, myPropInfo> sd = null; if (_propertycache.TryGetValue(typename, out sd)) { return(sd); } else { sd = new Custom_ValueType <string, myPropInfo>(); var pr = DeepCloner.GetFastDeepClonerProperties(type); foreach (var p in pr) { if (!p.CanRead)// Property is an indexer { continue; } myPropInfo d = CreateMyProp(p.PropertyType, p.Name); d.Property = p; d.CanWrite = p.CanWrite; foreach (var at in p.Attributes) { if (at is DataMemberAttribute) { var dm = (DataMemberAttribute)at; if (dm.Name != "") { d.memberName = dm.Name; } } } if (d.memberName != null) { sd.Add(d.memberName, d); } else { sd.Add(p.Name.ToLowerInvariant(), d); } } _propertycache.Add(typename, sd); } return(sd); }
/// <summary> /// Get the ColumnSchema /// </summary> /// <param name="datatype"></param> /// <returns></returns> public Custom_ValueType <string, ColumnSchema> GetColumnSchema(Type datatype) { try { var key = datatype.FullName + _transaction.DataBaseTypes.ToString(); if (CachedColumnSchema.ContainsKey(key)) { return(CachedColumnSchema[key]); } datatype = datatype.GetActualType(); var tableName = datatype.TableName(); var sql = $"SELECT COLUMN_NAME as columnname, data_type as datatype ,TABLE_CATALOG as db,TABLE_NAME as tb , IS_NULLABLE as isnullable FROM INFORMATION_SCHEMA.COLUMNS WHERE LOWER(TABLE_NAME) = LOWER(String[{tableName.Name}])"; if (_transaction.DataBaseTypes == DataBaseTypes.Sqllight) { sql = $"SELECT name as columnname, type as datatype FROM pragma_table_info(String[{tableName.Name}])"; } var columns = (List <ColumnSchema>)_transaction.DataReaderConverter(_transaction.GetSqlCommand(sql), typeof(ColumnSchema)); var dic = new Custom_ValueType <string, ColumnSchema>(); if (columns != null) { columns.ForEach(x => dic.Add(x.ColumnName, x)); } return(CachedColumnSchema.GetOrAdd(key, dic)); } catch (NpgsqlException) { _transaction.Renew(); return(GetColumnSchema(datatype)); } }
internal static Dictionary <string, IFastDeepClonerProperty> GetFastDeepClonerProperties(this Type primaryType) { if (!CachedPropertyInfo.ContainsKey(primaryType)) { var properties = new Custom_ValueType <string, IFastDeepClonerProperty>(); if (primaryType.GetTypeInfo().BaseType != null && primaryType.GetTypeInfo().BaseType.Name != "Object") { primaryType.GetRuntimeProperties().Where(x => x.GetField(properties)).ToList(); primaryType.GetTypeInfo().BaseType.GetRuntimeProperties().Where(x => x.GetField(properties)).ToList(); } else { primaryType.GetRuntimeProperties().Where(x => x.GetField(properties)).ToList(); } CachedPropertyInfo.Add(primaryType, properties); } return(CachedPropertyInfo[primaryType]); }
internal static object Creator(this Type type) { if (!DefaultConstructor.ContainsKey(type)) { DefaultConstructor.Add(type, type.GetConstructor(Type.EmptyTypes)); } if (DefaultConstructor[type] != null) { #if NETSTANDARD2_0 || NETSTANDARD1_3 || NETSTANDARD1_5 if (CachedConstructor.ContainsKey(type)) { return(CachedConstructor[type].Invoke()); } return(CachedConstructor.GetOrAdd(type, Expression.Lambda <Func <object> >(Expression.New(type)).Compile()).Invoke()); #else if (CachedDynamicMethod.ContainsKey(type)) { return(CachedDynamicMethod[type]()); } var emptyConstructor = DefaultConstructor[type]; var dynamicMethod = new System.Reflection.Emit.DynamicMethod("CreateInstance", type, Type.EmptyTypes, true); System.Reflection.Emit.ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); ilGenerator.Emit(System.Reflection.Emit.OpCodes.Nop); ilGenerator.Emit(System.Reflection.Emit.OpCodes.Newobj, emptyConstructor); ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret); return(CachedDynamicMethod.GetOrAdd(type, (ObjectActivator)dynamicMethod.CreateDelegate(typeof(ObjectActivator)))()); #endif } else { return(FormatterServices.GetUninitializedObject(type)); } }
private object Save(object o, bool isIndependentData, bool updateOnly = false) { try { 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 = ObjectColumns(o.GetType()); var objectRules = o.GetType().GetCustomAttribute <Rule>(); var tableName = o.GetType().TableName(); var primaryKeySubstitut = !primaryKey.GetCustomAttribute <PrimaryKey>().AutoGenerate ? primaryKeyId : null; object dbTrigger = null; if (objectRules != null && !CachedIDbRuleTrigger.ContainsKey(o.GetType())) { dbTrigger = objectRules.RuleType.CreateInstance(true); 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)) { 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()) + "] SET "; var cols = props.FindAll(x => (availableColumns.FindByPrimaryKey <bool>(x.GetPropertyName()) || availableColumns.FindByPrimaryKey <bool>(x.GetPropertyName().ToLower())) && x.IsInternalType && !x.ContainAttribute <ExcludeFromAbstract>() && x.GetCustomAttribute <PrimaryKey>() == null); 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, _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 <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, (col.ContainAttribute <Stringify>() || 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 { o.SetPrimaryKeyValue(primaryKeyId); Save(o, false, true); } o.SetPrimaryKeyValue(primaryKeyId); _repository.Attach(o, true); return(primaryKeyId); } catch (Exception e) { GlobalConfiguration.Log?.Error(e); _repository.Rollback(); throw; } }