예제 #1
0
        public virtual int Delete <TEntity>(TEntity entity)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            EnsureEntityHasPrimaryKey(typeDescriptor);

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;

            var keyVal = keyMemberDescriptor.GetValue(entity);

            if (keyVal == null)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMember.Name));
            }

            DbExpression left         = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column);
            DbExpression right        = new DbParameterExpression(keyVal);
            DbExpression conditionExp = new DbEqualExpression(left, right);

            DbDeleteExpression e = new DbDeleteExpression(typeDescriptor.Table, conditionExp);

            return(this.ExecuteSqlCommand(e));
        }
예제 #2
0
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int Remove(TEntity entity)
        {
            Checks.NotNull(entity, "entity");

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;

            if (keyMemberDescriptor == null)
            {
                throw new SZORMException(string.Format("该表没有主键不允许这样删除."));
            }

            var keyVal = keyMemberDescriptor.GetValue(entity);

            if (keyVal == null)
            {
                throw new SZORMException(string.Format("{0}主键字段不允许为空.", keyMember.Name));
            }

            DbExpression left         = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column);
            DbExpression right        = new DbParameterExpression(keyVal);
            DbExpression conditionExp = new DbEqualExpression(left, right);

            DbDeleteExpression      e          = new DbDeleteExpression(typeDescriptor.Table, conditionExp);
            IDbExpressionTranslator translator = this.DbContext.DatabaseProvider.CreateDbExpressionTranslator();
            List <DbParam>          parameters;
            string sql = translator.Translate(e, out parameters);

            return(this.DbContext.ExecuteNoQuery(sql, parameters.ToArray()));
        }
예제 #3
0
        public void Refresh()
        {
            Dictionary <MemberInfo, MappingMemberDescriptor> mappingMemberDescriptors = this.TypeDescriptor.MappingMemberDescriptors;

            if (this._fakes == null)
            {
                this._fakes = new Dictionary <MemberInfo, object>(mappingMemberDescriptors.Count);
            }
            else
            {
                this._fakes.Clear();
            }

            object entity = this._entity;

            foreach (var kv in mappingMemberDescriptors)
            {
                MemberInfo key = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                var val = memberDescriptor.GetValue(entity);

                //I hate the byte[].
                if (memberDescriptor.MemberInfoType == UtilConstants.TypeOfByteArray)
                {
                    val = Clone((byte[])val);
                }

                this._fakes[key] = val;
            }
        }
예제 #4
0
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public TEntity Edit(TEntity entity)
        {
            Checks.NotNull(entity, "entity");

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            object keyVal = null;
            MappingMemberDescriptor keyMemberDescriptor = null;

            Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                object val = memberDescriptor.GetValue(entity);
                if (memberDescriptor.SZColumnAttribute.IsKey)
                {
                    if (val == null)
                    {
                        throw new SZORMException("主键值不允许为空.");
                    }
                    keyVal = val;
                    keyMemberDescriptor = memberDescriptor;
                    continue;
                }

                if (memberDescriptor.SZColumnAttribute.IsEditTime)
                {
                    val = DateTime.Now;
                    memberDescriptor.SetValue(entity, val);
                }


                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                updateColumns.Add(memberDescriptor, valExp);
            }

            DbExpression left         = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column);
            DbExpression right        = DbExpression.Parameter(keyVal, keyMemberDescriptor.MemberInfoType);
            DbExpression conditionExp = new DbEqualExpression(left, right);

            DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp);

            foreach (var item in updateColumns)
            {
                e.UpdateColumns.Add(item.Key.Column, item.Value);
            }

            IDbExpressionTranslator translator = this.DbContext.DatabaseProvider.CreateDbExpressionTranslator();
            List <DbParam>          parameters;
            string sql = translator.Translate(e, out parameters);

            this.DbContext.ExecuteNoQuery(sql, parameters.ToArray());

            return(entity);
        }
예제 #5
0
        public virtual T Insert <T>(T entity)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            EnsureMappingTypeHasPrimaryKey(typeDescriptor);

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;

            object keyValue = null;

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                var val = memberDescriptor.GetValue(entity);

                if (memberDescriptor == keyMemberDescriptor)
                {
                    keyValue = val;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            //主键为空并且主键又不是自增列
            if (keyValue == null)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
            }

            DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }

            this.ExecuteSqlCommand(e);
            return(entity);
        }
예제 #6
0
        /// <summary>
        /// 传入一个 dto 对象插入数据。dto 需要与实体建立映射关系,否则会报错
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TDto"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="dto"></param>
        /// <returns></returns>
        public static TEntity InsertFromDto <TEntity, TDto>(this IDbContext dbContext, TDto dto)
        {
            /*
             * 支持自动设置 主键=guid
             * 支持自动设置 CreationTime=DateTime.Now
             * 支持自动设置 IsDeleted=false
             */

            Utils.CheckNull(dto);

            TEntity entity = AceMapper.Map <TEntity>(dto);

            Type           entityType     = typeof(TEntity);
            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType);

            /* 设置 主键=guid */
            if (typeDescriptor.PrimaryKeys.Count < 2) /* 只有无主键或单一主键的时候 */
            {
                MappingMemberDescriptor primaryKeyDescriptor = typeDescriptor.PrimaryKeys.FirstOrDefault();
                if (primaryKeyDescriptor != null && primaryKeyDescriptor.IsAutoIncrement == false)
                {
                    var keyValue = primaryKeyDescriptor.GetValue(entity);
                    if (keyValue.IsDefaultValueOfType(primaryKeyDescriptor.MemberInfoType) || string.Empty.Equals(keyValue))
                    {
                        /* 如果未设置主键值,则自动设置为 guid */
                        if (primaryKeyDescriptor.MemberInfoType == typeof(string))
                        {
                            primaryKeyDescriptor.SetValue(entity, IdHelper.CreateGuid());
                        }
                        else if (primaryKeyDescriptor.MemberInfoType.GetUnderlyingType() == typeof(Guid))
                        {
                            primaryKeyDescriptor.SetValue(entity, Guid.NewGuid());
                        }
                    }
                }
            }


            /* 设置 CreationTime=DateTime.Now */
            SetValueIfNeeded(entity, typeDescriptor, "CreationTime", DateTime.Now);

            /* 设置 IsDeleted=false */
            SetValueIfNeeded(entity, typeDescriptor, "IsDeleted", false);

            return(dbContext.Insert(entity));
        }
예제 #7
0
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public TEntity Add(TEntity entity)
        {
            Checks.NotNull(entity, "entity");

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                object val = memberDescriptor.GetValue(entity);

                if (memberDescriptor.SZColumnAttribute.IsKey)
                {
                    if (val == null || string.IsNullOrEmpty(val.ToString()))
                    {
                        val = GetNewKey();
                        memberDescriptor.SetValue(entity, val);
                    }
                }
                if (memberDescriptor.SZColumnAttribute.IsAddTime || memberDescriptor.SZColumnAttribute.IsEditTime)
                {
                    val = DateTime.Now;
                    memberDescriptor.SetValue(entity, val);
                }
                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }
            IDbExpressionTranslator translator = this.DbContext.DatabaseProvider.CreateDbExpressionTranslator();
            List <DbParam>          parameters;
            string sql = translator.Translate(e, out parameters);

            this.DbContext.ExecuteNoQuery(sql, parameters.ToArray());

            return(entity);
        }
예제 #8
0
        public override TEntity Insert <TEntity>(TEntity entity, string table)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;

            object keyValue = null;

            string sequenceName;
            object sequenceValue = null;
            MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName);

            if (defineSequenceMemberDescriptor != null)
            {
                sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType);
            }

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                object val = null;
                if (defineSequenceMemberDescriptor != null && memberDescriptor == defineSequenceMemberDescriptor)
                {
                    val = sequenceValue;
                }
                else
                {
                    val = memberDescriptor.GetValue(entity);
                }

                if (memberDescriptor == keyMemberDescriptor)
                {
                    keyValue = val;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            if (keyMemberDescriptor != null && keyValue == null)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
            }

            DbTable            dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            DbInsertExpression e       = new DbInsertExpression(dbTable);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }

            this.ExecuteSqlCommand(e);

            if (defineSequenceMemberDescriptor != null)
            {
                defineSequenceMemberDescriptor.SetValue(entity, sequenceValue);
            }

            return(entity);
        }
예제 #9
0
        public override int Update <TEntity>(TEntity entity, string table)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            EnsureMappingTypeHasPrimaryKey(typeDescriptor);

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = keyMemberDescriptor.MemberInfo;

            object keyVal = null;

            IEntityState entityState = this.TryGetTrackedEntityState(entity);
            Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                if (member == keyMember)
                {
                    keyVal = memberDescriptor.GetValue(entity);
                    keyMemberDescriptor = memberDescriptor;
                    continue;
                }

                SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute));
                if (attr != null)
                {
                    continue;
                }

                object val = memberDescriptor.GetValue(entity);

                if (entityState != null && !entityState.HasChanged(memberDescriptor, val))
                {
                    continue;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                updateColumns.Add(memberDescriptor, valExp);
            }

            if (keyVal == null)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMember.Name));
            }

            if (updateColumns.Count == 0)
            {
                return(0);
            }

            DbTable      dbTable      = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            DbExpression left         = new DbColumnAccessExpression(dbTable, keyMemberDescriptor.Column);
            DbExpression right        = DbExpression.Parameter(keyVal, keyMemberDescriptor.MemberInfoType);
            DbExpression conditionExp = new DbEqualExpression(left, right);

            DbUpdateExpression e = new DbUpdateExpression(dbTable, conditionExp);

            foreach (var item in updateColumns)
            {
                e.UpdateColumns.Add(item.Key.Column, item.Value);
            }

            int ret = this.ExecuteSqlCommand(e);

            if (entityState != null)
            {
                entityState.Refresh();
            }
            return(ret);
        }
예제 #10
0
        public override void InsertRange <TEntity>(List <TEntity> entities, bool keepIdentity = false)
        {
            /*
             * 将 entities 分批插入数据库
             * 每批生成 insert into TableName(...) values(...),(...)...
             * 该方法相对循环一条一条插入,速度提升 2/3 这样
             */

            Utils.CheckNull(entities);
            if (entities.Count == 0)
            {
                return;
            }

            int maxParameters = 2100;
            int batchSize     = 50; /* 每批实体大小,此值通过测试得出相对插入速度比较快的一个值 */

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity));

            var e = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value);

            if (keepIdentity == false)
            {
                e = e.Where(a => a.IsAutoIncrement == false);
            }
            List <MappingMemberDescriptor> mappingMemberDescriptors = e.ToList();
            int maxDbParamsCount = maxParameters - mappingMemberDescriptors.Count; /* 控制一个 sql 的参数个数 */

            string sqlTemplate = AppendInsertRangeSqlTemplate(typeDescriptor, mappingMemberDescriptors);

            Action insertAction = () =>
            {
                int            batchCount = 0;
                List <DbParam> dbParams   = new List <DbParam>();
                StringBuilder  sqlBuilder = new StringBuilder();
                for (int i = 0; i < entities.Count; i++)
                {
                    var entity = entities[i];

                    if (batchCount > 0)
                    {
                        sqlBuilder.Append(",");
                    }

                    sqlBuilder.Append("(");
                    for (int j = 0; j < mappingMemberDescriptors.Count; j++)
                    {
                        if (j > 0)
                        {
                            sqlBuilder.Append(",");
                        }

                        MappingMemberDescriptor mappingMemberDescriptor = mappingMemberDescriptors[j];
                        object val = mappingMemberDescriptor.GetValue(entity);
                        if (val == null)
                        {
                            sqlBuilder.Append("NULL");
                            continue;
                        }

                        Type valType = val.GetType();
                        if (valType.IsEnum)
                        {
                            val     = Convert.ChangeType(val, Enum.GetUnderlyingType(valType));
                            valType = val.GetType();
                        }

                        if (ToStringableNumericTypes.ContainsKey(valType))
                        {
                            sqlBuilder.Append(val.ToString());
                            continue;
                        }

                        if (val is bool)
                        {
                            if ((bool)val == true)
                            {
                                sqlBuilder.AppendFormat("1");
                            }
                            else
                            {
                                sqlBuilder.AppendFormat("0");
                            }
                            continue;
                        }
                        else if (val is double)
                        {
                            double v = (double)val;
                            if (v >= long.MinValue && v <= long.MaxValue)
                            {
                                sqlBuilder.Append(((long)v).ToString());
                                continue;
                            }
                        }
                        else if (val is float)
                        {
                            float v = (float)val;
                            if (v >= long.MinValue && v <= long.MaxValue)
                            {
                                sqlBuilder.Append(((long)v).ToString());
                                continue;
                            }
                        }
                        else if (val is decimal)
                        {
                            decimal v = (decimal)val;
                            if (v >= long.MinValue && v <= long.MaxValue)
                            {
                                sqlBuilder.Append(((long)v).ToString());
                                continue;
                            }
                        }

                        string  paramName = UtilConstants.ParameterNamePrefix + dbParams.Count.ToString();
                        DbParam dbParam   = new DbParam(paramName, val)
                        {
                            DbType = mappingMemberDescriptor.Column.DbType
                        };
                        dbParams.Add(dbParam);
                        sqlBuilder.Append(paramName);
                    }
                    sqlBuilder.Append(")");

                    batchCount++;

                    if ((batchCount >= 20 && dbParams.Count >= 120 /*参数个数太多也会影响速度*/) || dbParams.Count >= maxDbParamsCount || batchCount >= batchSize || (i + 1) == entities.Count)
                    {
                        sqlBuilder.Insert(0, sqlTemplate);
                        string sql = sqlBuilder.ToString();
                        this.Session.ExecuteNonQuery(sql, dbParams.ToArray());

                        sqlBuilder.Clear();
                        dbParams.Clear();
                        batchCount = 0;
                    }
                }
            };

            Action fAction = () =>
            {
                bool   shouldTurnOff_IDENTITY_INSERT = false;
                string tableName = null;
                if (keepIdentity == true)
                {
                    tableName = AppendTableName(typeDescriptor.Table);
                    this.Session.ExecuteNonQuery(string.Format("SET IDENTITY_INSERT {0} ON ", tableName));
                    shouldTurnOff_IDENTITY_INSERT = true;
                }

                insertAction();
                if (shouldTurnOff_IDENTITY_INSERT == true)
                {
                    this.Session.ExecuteNonQuery(string.Format("SET IDENTITY_INSERT {0} OFF ", tableName));
                }
            };

            if (this.Session.IsInTransaction)
            {
                fAction();
            }
            else
            {
                /* 因为分批插入,所以需要开启事务保证数据一致性 */
                this.Session.BeginTransaction();
                try
                {
                    fAction();
                    this.Session.CommitTransaction();
                }
                catch
                {
                    if (this.Session.IsInTransaction)
                    {
                        this.Session.RollbackTransaction();
                    }
                    throw;
                }
            }
        }
예제 #11
0
        public override T Insert <T>(T entity)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            EnsureMappingTypeHasPrimaryKey(typeDescriptor);

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
            MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;

            object keyValue = null;

            MappingMemberDescriptor autoIncrementMemberDescriptor = GetAutoIncrementMemberDescriptor(typeDescriptor);

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                if (memberDescriptor == autoIncrementMemberDescriptor)
                {
                    continue;
                }

                var val = memberDescriptor.GetValue(entity);

                if (memberDescriptor == keyMemberDescriptor)
                {
                    keyValue = val;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            //主键为空并且主键又不是自增列
            if (keyValue == null && keyMemberDescriptor != autoIncrementMemberDescriptor)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
            }

            DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }

            if (autoIncrementMemberDescriptor == null)
            {
                this.ExecuteSqlCommand(e);
                return(entity);
            }

            IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator();
            List <DbParam>          parameters;
            string sql = translator.Translate(e, out parameters);

            sql += ";SELECT @@IDENTITY";

            //SELECT @@IDENTITY 返回的是 decimal 类型
            object retIdentity = this.CurrentSession.ExecuteScalar(sql, parameters.ToArray());

            if (retIdentity == null || retIdentity == DBNull.Value)
            {
                throw new ChloeException("Unable to get the identity value.");
            }

            retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType);
            autoIncrementMemberDescriptor.SetValue(entity, retIdentity);
            return(entity);
        }
예제 #12
0
        public override TEntity Insert <TEntity>(TEntity entity, string table)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            Dictionary <MappingMemberDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor);

            string sequenceName;
            object sequenceValue = null;
            MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName);

            if (defineSequenceMemberDescriptor != null)
            {
                if (defineSequenceMemberDescriptor.IsPrimaryKey && typeDescriptor.PrimaryKeys.Count > 1)
                {
                    /* 自增列不能作为联合主键成员 */
                    throw new ChloeException("The member of marked sequence can not be union key.");
                }

                sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType);
            }

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MemberInfo member = kv.Key;
                MappingMemberDescriptor memberDescriptor = kv.Value;

                object val = null;
                if (defineSequenceMemberDescriptor != null && memberDescriptor == defineSequenceMemberDescriptor)
                {
                    val = sequenceValue;
                }
                else
                {
                    val = memberDescriptor.GetValue(entity);
                }

                if (keyValueMap.ContainsKey(memberDescriptor))
                {
                    keyValueMap[memberDescriptor] = val;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            MappingMemberDescriptor nullValueKey = keyValueMap.Where(a => a.Value == null).Select(a => a.Key).FirstOrDefault();

            if (nullValueKey != null)
            {
                throw new ChloeException(string.Format("The primary key '{0}' could not be null.", nullValueKey.MemberInfo.Name));
            }

            DbTable            dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            DbInsertExpression e       = new DbInsertExpression(dbTable);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }

            this.ExecuteSqlCommand(e);

            if (defineSequenceMemberDescriptor != null)
            {
                defineSequenceMemberDescriptor.SetValue(entity, sequenceValue);
            }

            return(entity);
        }
예제 #13
0
        public override int Update <TEntity>(TEntity entity, string table)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            EnsureMappingTypeHasPrimaryKey(typeDescriptor);

            Dictionary <MappingMemberDescriptor, object> keyValueMap = CreateKeyValueMap(typeDescriptor);

            IEntityState entityState = this.TryGetTrackedEntityState(entity);
            Dictionary <MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MappingMemberDescriptor memberDescriptor = kv.Value;

                if (keyValueMap.ContainsKey(memberDescriptor))
                {
                    keyValueMap[memberDescriptor] = memberDescriptor.GetValue(entity);
                    continue;
                }

                SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute));
                if (attr != null)
                {
                    continue;
                }

                object val = memberDescriptor.GetValue(entity);

                if (entityState != null && !entityState.HasChanged(memberDescriptor, val))
                {
                    continue;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                updateColumns.Add(memberDescriptor, valExp);
            }

            if (updateColumns.Count == 0)
            {
                return(0);
            }

            DbTable            dbTable      = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            DbExpression       conditionExp = MakeCondition(keyValueMap, dbTable);
            DbUpdateExpression e            = new DbUpdateExpression(dbTable, conditionExp);

            foreach (var item in updateColumns)
            {
                e.UpdateColumns.Add(item.Key.Column, item.Value);
            }

            int ret = this.ExecuteSqlCommand(e);

            if (entityState != null)
            {
                entityState.Refresh();
            }
            return(ret);
        }
예제 #14
0
        public override void InsertRange <TEntity>(List <TEntity> entities, bool keepIdentity = false)
        {
            /*
             * 将 entities 分批插入数据库
             * 每批生成 insert into TableName(...) select ... from dual union all select ... from dual...
             * 对于 oracle,貌似速度提升不了...- -
             * #期待各码友的优化建议#
             */

            Utils.CheckNull(entities);
            if (entities.Count == 0)
            {
                return;
            }

            int maxParameters = 1000;
            int batchSize     = 40; /* 每批实体大小,此值通过测试得出相对插入速度比较快的一个值 */

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(TEntity));

            var e = typeDescriptor.MappingMemberDescriptors.Select(a => a.Value);

            List <MappingMemberDescriptor> mappingMemberDescriptors = e.ToList();
            int maxDbParamsCount = maxParameters - mappingMemberDescriptors.Count; /* 控制一个 sql 的参数个数 */

            string sqlTemplate = AppendInsertRangeSqlTemplate(typeDescriptor, mappingMemberDescriptors, keepIdentity);

            Action insertAction = () =>
            {
                int            batchCount = 0;
                List <DbParam> dbParams   = new List <DbParam>();
                StringBuilder  sqlBuilder = new StringBuilder();
                for (int i = 0; i < entities.Count; i++)
                {
                    var entity = entities[i];

                    if (batchCount > 0)
                    {
                        sqlBuilder.Append(" UNION ALL ");
                    }

                    sqlBuilder.Append(" SELECT ");
                    for (int j = 0; j < mappingMemberDescriptors.Count; j++)
                    {
                        if (j > 0)
                        {
                            sqlBuilder.Append(",");
                        }

                        MappingMemberDescriptor mappingMemberDescriptor = mappingMemberDescriptors[j];

                        string sequenceName;
                        if (keepIdentity == false && HasSequenceAttribute(mappingMemberDescriptor, out sequenceName))
                        {
                            sqlBuilder.AppendFormat("1");
                            continue;
                        }

                        object val = mappingMemberDescriptor.GetValue(entity);
                        if (val == null)
                        {
                            sqlBuilder.Append("NULL");
                            sqlBuilder.Append(" C").Append(j.ToString());
                            continue;
                        }

                        Type valType = val.GetType();
                        if (valType.IsEnum)
                        {
                            val     = Convert.ChangeType(val, Enum.GetUnderlyingType(valType));
                            valType = val.GetType();
                        }

                        if (Utils.IsToStringableNumericType(valType))
                        {
                            sqlBuilder.Append(val.ToString());
                        }
                        else if (val is bool)
                        {
                            if ((bool)val == true)
                            {
                                sqlBuilder.AppendFormat("1");
                            }
                            else
                            {
                                sqlBuilder.AppendFormat("0");
                            }
                        }
                        else
                        {
                            string  paramName = UtilConstants.ParameterNamePrefix + dbParams.Count.ToString();
                            DbParam dbParam   = new DbParam(paramName, val)
                            {
                                DbType = mappingMemberDescriptor.Column.DbType
                            };
                            dbParams.Add(dbParam);
                            sqlBuilder.Append(paramName);
                        }

                        sqlBuilder.Append(" C").Append(j.ToString());
                    }

                    sqlBuilder.Append(" FROM DUAL");

                    batchCount++;

                    if ((batchCount >= 20 && dbParams.Count >= 400 /*参数个数太多也会影响速度*/) || dbParams.Count >= maxDbParamsCount || batchCount >= batchSize || (i + 1) == entities.Count)
                    {
                        sqlBuilder.Insert(0, sqlTemplate);

                        if (keepIdentity == false)
                        {
                            sqlBuilder.Append(") T");
                        }

                        string sql = sqlBuilder.ToString();
                        this.Session.ExecuteNonQuery(sql, dbParams.ToArray());

                        sqlBuilder.Clear();
                        dbParams.Clear();
                        batchCount = 0;
                    }
                }
            };

            Action fAction = insertAction;

            if (this.Session.IsInTransaction)
            {
                fAction();
            }
            else
            {
                /* 因为分批插入,所以需要开启事务保证数据一致性 */
                this.Session.BeginTransaction();
                try
                {
                    fAction();
                    this.Session.CommitTransaction();
                }
                catch
                {
                    if (this.Session.IsInTransaction)
                    {
                        this.Session.RollbackTransaction();
                    }
                    throw;
                }
            }
        }
예제 #15
0
        public virtual TEntity Insert <TEntity>(TEntity entity, string table)
        {
            Utils.CheckNull(entity);

            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());

            MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;

            object keyValue = null;

            MappingMemberDescriptor autoIncrementMemberDescriptor = typeDescriptor.AutoIncrement;

            Dictionary <MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary <MappingMemberDescriptor, DbExpression>();

            foreach (var kv in typeDescriptor.MappingMemberDescriptors)
            {
                MappingMemberDescriptor memberDescriptor = kv.Value;

                if (memberDescriptor == autoIncrementMemberDescriptor)
                {
                    continue;
                }

                object val = memberDescriptor.GetValue(entity);

                if (memberDescriptor == keyMemberDescriptor)
                {
                    keyValue = val;
                }

                DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
                insertColumns.Add(memberDescriptor, valExp);
            }

            if (keyMemberDescriptor != null)
            {
                //主键为空并且主键又不是自增列
                if (keyValue == null && keyMemberDescriptor != autoIncrementMemberDescriptor)
                {
                    throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
                }
            }

            DbTable            dbTable = table == null ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            DbInsertExpression e       = new DbInsertExpression(dbTable);

            foreach (var kv in insertColumns)
            {
                e.InsertColumns.Add(kv.Key.Column, kv.Value);
            }

            if (autoIncrementMemberDescriptor == null)
            {
                this.ExecuteSqlCommand(e);
                return(entity);
            }

            IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator();
            List <DbParam>          parameters;
            string sql = translator.Translate(e, out parameters);

            sql = string.Concat(sql, ";", this.GetSelectLastInsertIdClause());

            //SELECT @@IDENTITY 返回的是 decimal 类型
            object retIdentity = this.Session.ExecuteScalar(sql, parameters.ToArray());

            if (retIdentity == null || retIdentity == DBNull.Value)
            {
                throw new ChloeException("Unable to get the identity value.");
            }

            retIdentity = ConvertIdentityType(retIdentity, autoIncrementMemberDescriptor.MemberInfoType);
            autoIncrementMemberDescriptor.SetValue(entity, retIdentity);
            return(entity);
        }