Exemple #1
0
        async Task SaveOneToOne(ComplexPropertyDescriptor navPropertyDescriptor, object owner, TypeDescriptor ownerTypeDescriptor, bool @async)
        {
            /*
             * 1:1
             * T    <1:1>    TOther
             * T.TOther <--> TOther.T
             * T.Id <--> TOther.Id
             */

            //owner is T
            //navPropertyDescriptor is T.TOther
            //TypeDescriptor of T.TOther
            TypeDescriptor navTypeDescriptor = EntityTypeContainer.GetDescriptor(navPropertyDescriptor.PropertyType);
            //TOther.T
            ComplexPropertyDescriptor TOtherDotT = navTypeDescriptor.ComplexPropertyDescriptors.Where(a => a.PropertyType == ownerTypeDescriptor.Definition.Type).FirstOrDefault();

            bool isOneToOne = TOtherDotT != null;

            if (!isOneToOne)
            {
                return;
            }

            //instance of T.TOther
            object navValue = navPropertyDescriptor.GetValue(owner);

            if (navValue == null)
            {
                return;
            }

            //T.Id
            PrimitivePropertyDescriptor foreignKeyProperty = navPropertyDescriptor.ForeignKeyProperty;

            if (foreignKeyProperty.IsAutoIncrement || foreignKeyProperty.HasSequence())
            {
                //value of T.Id
                object foreignKeyValue = foreignKeyProperty.GetValue(owner);

                //T.TOther.Id = T.Id
                TOtherDotT.ForeignKeyProperty.SetValue(navValue, foreignKeyValue);
            }

            MethodInfo saveMethod = GetSaveMethod(navPropertyDescriptor.PropertyType);
            //DbContext.Save(navValue, ownerTypeDescriptor, @async);
            Task  task = (Task)saveMethod.Invoke(this, navValue, ownerTypeDescriptor, @async);
            await task;
        }
Exemple #2
0
        DataTable ConvertToSqlBulkCopyDataTable <TModel>(List <TModel> modelList, TypeDescriptor typeDescriptor)
        {
            DataTable dt = new DataTable();

            var mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.Where(a => !a.IsTimestamp()).ToList();

            for (int i = 0; i < mappingPropertyDescriptors.Count; i++)
            {
                PrimitivePropertyDescriptor mappingPropertyDescriptor = mappingPropertyDescriptors[i];

                Type dataType = mappingPropertyDescriptor.PropertyType.GetUnderlyingType();
                if (dataType.IsEnum)
                {
                    dataType = Enum.GetUnderlyingType(dataType);
                }

                dt.Columns.Add(new DataColumn(mappingPropertyDescriptor.Column.Name, dataType));
            }

            foreach (var model in modelList)
            {
                DataRow dr = dt.NewRow();
                for (int i = 0; i < mappingPropertyDescriptors.Count; i++)
                {
                    PrimitivePropertyDescriptor mappingPropertyDescriptor = mappingPropertyDescriptors[i];
                    object value = mappingPropertyDescriptor.GetValue(model);

                    PublicHelper.NotNullCheck(mappingPropertyDescriptor, value);

                    if (mappingPropertyDescriptor.PropertyType.GetUnderlyingType().IsEnum)
                    {
                        if (value != null)
                        {
                            value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
                        }
                    }

                    dr[i] = value ?? DBNull.Value;
                }

                dt.Rows.Add(dr);
            }

            return(dt);
        }
Exemple #3
0
        async Task SaveCollection(CollectionPropertyDescriptor collectionPropertyDescriptor, object owner, TypeDescriptor ownerTypeDescriptor, bool @async)
        {
            PrimitivePropertyDescriptor ownerKeyPropertyDescriptor = ownerTypeDescriptor.PrimaryKeys.FirstOrDefault();

            if (ownerKeyPropertyDescriptor == null)
            {
                return;
            }

            //T.Elements
            IList elementList = collectionPropertyDescriptor.GetValue(owner) as IList;

            if (elementList == null || elementList.Count == 0)
            {
                return;
            }

            TypeDescriptor elementTypeDescriptor = EntityTypeContainer.GetDescriptor(collectionPropertyDescriptor.ElementType);
            //Element.T
            ComplexPropertyDescriptor elementDotT = elementTypeDescriptor.ComplexPropertyDescriptors.Where(a => a.PropertyType == ownerTypeDescriptor.Definition.Type).FirstOrDefault();

            object     ownerKeyValue = ownerKeyPropertyDescriptor.GetValue(owner);
            MethodInfo saveMethod    = GetSaveMethod(collectionPropertyDescriptor.ElementType);

            for (int i = 0; i < elementList.Count; i++)
            {
                object element = elementList[i];
                if (element == null)
                {
                    continue;
                }

                //element.ForeignKey = T.Id
                elementDotT.ForeignKeyProperty.SetValue(element, ownerKeyValue);
                //DbContext.Save(element, ownerTypeDescriptor, @async);
                Task  task = (Task)saveMethod.Invoke(this, element, ownerTypeDescriptor, @async);
                await task;
            }
        }
Exemple #4
0
        public override void InsertRange <TEntity>(List <TEntity> entities, string table)
        {
            /*
             * 将 entities 分批插入数据库
             * 每批生成 insert into TableName(...) values(...),(...)...
             * 该方法相对循环一条一条插入,速度提升 2/3 这样
             */

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

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

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

            List <PrimitivePropertyDescriptor> mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.Where(a => a.IsAutoIncrement == false).ToList();
            int maxDbParamsCount = maxParameters - mappingPropertyDescriptors.Count; /* 控制一个 sql 的参数个数 */

            DbTable dbTable     = string.IsNullOrEmpty(table) ? typeDescriptor.Table : new DbTable(table, typeDescriptor.Table.Schema);
            string  sqlTemplate = AppendInsertRangeSqlTemplate(dbTable, mappingPropertyDescriptors);

            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 < mappingPropertyDescriptors.Count; j++)
                    {
                        if (j > 0)
                        {
                            sqlBuilder.Append(",");
                        }

                        PrimitivePropertyDescriptor mappingPropertyDescriptor = mappingPropertyDescriptors[j];

                        object val = mappingPropertyDescriptor.GetValue(entity);

                        PublicHelper.NotNullCheck(mappingPropertyDescriptor, val);

                        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 (Utils.IsToStringableNumericType(valType))
                        {
                            sqlBuilder.Append(val.ToString());
                            continue;
                        }

                        if (val is bool)
                        {
                            if ((bool)val == true)
                            {
                                sqlBuilder.AppendFormat("1");
                            }
                            else
                            {
                                sqlBuilder.AppendFormat("0");
                            }
                            continue;
                        }

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

                    batchCount++;

                    if ((batchCount >= 20 && dbParams.Count >= 400 /*参数个数太多也会影响速度*/) || 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 = insertAction;

            if (this.Session.IsInTransaction)
            {
                fAction();
            }
            else
            {
                /* 因为分批插入,所以需要开启事务保证数据一致性 */
                this.Session.BeginTransaction();
                try
                {
                    fAction();
                    this.Session.CommitTransaction();
                }
                catch
                {
                    if (this.Session.IsInTransaction)
                    {
                        this.Session.RollbackTransaction();
                    }
                    throw;
                }
            }
        }
Exemple #5
0
        protected override async Task InsertRange <TEntity>(List <TEntity> entities, string table, bool @async)
        {
            /*
             * 将 entities 分批插入数据库
             * 每批生成 insert into TableName(...) values(...),(...)...
             * 该方法相对循环一条一条插入,速度提升 2/3 这样
             */

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

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

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

            List <PrimitivePropertyDescriptor> mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.Where(a => a.IsAutoIncrement == false).ToList();
            int maxDbParamsCount = maxParameters - mappingPropertyDescriptors.Count; /* 控制一个 sql 的参数个数 */

            DbTable dbTable     = PublicHelper.CreateDbTable(typeDescriptor, table);
            string  sqlTemplate = this.AppendInsertRangeSqlTemplate(dbTable, mappingPropertyDescriptors);

            Func <Task> insertAction = async() =>
            {
                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 < mappingPropertyDescriptors.Count; j++)
                    {
                        if (j > 0)
                        {
                            sqlBuilder.Append(",");
                        }

                        PrimitivePropertyDescriptor mappingPropertyDescriptor = mappingPropertyDescriptors[j];

                        if (mappingPropertyDescriptor.HasSequence())
                        {
                            string sequenceSchema = mappingPropertyDescriptor.Definition.SequenceSchema;
                            sequenceSchema = string.IsNullOrEmpty(sequenceSchema) ? dbTable.Schema : sequenceSchema;

                            sqlBuilder.Append("nextval('");

                            if (!string.IsNullOrEmpty(sequenceSchema))
                            {
                                sqlBuilder.Append(sequenceSchema).Append(".");
                            }

                            sqlBuilder.Append(mappingPropertyDescriptor.Definition.SequenceName);
                            sqlBuilder.Append("')");
                            continue;
                        }

                        object val = mappingPropertyDescriptor.GetValue(entity);

                        PublicHelper.NotNullCheck(mappingPropertyDescriptor, val);

                        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 (Utils.IsToStringableNumericType(valType))
                        {
                            sqlBuilder.Append(val.ToString());
                            continue;
                        }

                        if (val is bool)
                        {
                            if ((bool)val == true)
                            {
                                sqlBuilder.AppendFormat("true");
                            }
                            else
                            {
                                sqlBuilder.AppendFormat("false");
                            }
                            continue;
                        }

                        string  paramName = UtilConstants.ParameterNamePrefix + dbParams.Count.ToString();
                        DbParam dbParam   = new DbParam(paramName, val)
                        {
                            DbType = mappingPropertyDescriptor.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();
                        await this.Session.ExecuteNonQuery(sql, dbParams.ToArray(), @async);

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

            Func <Task> fAction = insertAction;

            if (this.Session.IsInTransaction)
            {
                await fAction();

                return;
            }

            /* 因为分批插入,所以需要开启事务保证数据一致性 */
            using (var tran = this.BeginTransaction())
            {
                await fAction();

                tran.Commit();
            }
        }
Exemple #6
0
        protected override async Task InsertRange <TEntity>(List <TEntity> entities, string table, bool @async)
        {
            /*
             * 将 entities 分批插入数据库
             * 每批生成 insert into TableName(...) select ... from dual union all select ... from dual...
             * 对于 oracle,貌似速度提升不了...- -
             * #期待各码友的优化建议#
             */

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

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

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

            List <PrimitivePropertyDescriptor> mappingPropertyDescriptors = typeDescriptor.PrimitivePropertyDescriptors.Where(a => a.IsAutoIncrement == false).ToList();
            int maxDbParamsCount = maxParameters - mappingPropertyDescriptors.Count; /* 控制一个 sql 的参数个数 */

            DbTable dbTable     = PublicHelper.CreateDbTable(typeDescriptor, table);
            string  sqlTemplate = AppendInsertRangeSqlTemplate(dbTable, mappingPropertyDescriptors);

            Func <Task> insertAction = async() =>
            {
                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 < mappingPropertyDescriptors.Count; j++)
                    {
                        if (j > 0)
                        {
                            sqlBuilder.Append(",");
                        }

                        PrimitivePropertyDescriptor mappingPropertyDescriptor = mappingPropertyDescriptors[j];

                        object val = mappingPropertyDescriptor.GetValue(entity);

                        PublicHelper.NotNullCheck(mappingPropertyDescriptor, val);

                        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 = mappingPropertyDescriptor.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);
                        sqlBuilder.Append(") T");

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

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

            Func <Task> fAction = insertAction;

            if (this.Session.IsInTransaction)
            {
                await fAction();

                return;
            }

            /* 因为分批插入,所以需要开启事务保证数据一致性 */
            using (var tran = this.BeginTransaction())
            {
                await fAction();

                tran.Commit();
            }
        }
Exemple #7
0
        protected override async Task <int> Update <TEntity>(TEntity entity, string table, bool @async)
        {
            PublicHelper.CheckNull(entity);

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

            PublicHelper.EnsureHasPrimaryKey(typeDescriptor);

            PairList <PrimitivePropertyDescriptor, object> keyValues = new PairList <PrimitivePropertyDescriptor, object>(typeDescriptor.PrimaryKeys.Count);

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

            foreach (PrimitivePropertyDescriptor propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors)
            {
                if (propertyDescriptor.IsPrimaryKey)
                {
                    var keyValue = propertyDescriptor.GetValue(entity);
                    PrimaryKeyHelper.KeyValueNotNull(propertyDescriptor, keyValue);
                    keyValues.Add(propertyDescriptor, keyValue);
                    continue;
                }

                if (propertyDescriptor.CannotUpdate())
                {
                    continue;
                }

                object val = propertyDescriptor.GetValue(entity);
                PublicHelper.NotNullCheck(propertyDescriptor, val);

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

                DbExpression valExp = DbExpression.Parameter(val, propertyDescriptor.PropertyType, propertyDescriptor.Column.DbType);
                updateColumns.Add(propertyDescriptor, valExp);
            }

            PrimitivePropertyDescriptor rowVersionDescriptor = null;
            object rowVersionValue    = null;
            object rowVersionNewValue = null;

            if (typeDescriptor.HasRowVersion())
            {
                rowVersionDescriptor = typeDescriptor.RowVersion;
                if (rowVersionDescriptor.IsTimestamp())
                {
                    rowVersionValue = rowVersionDescriptor.GetValue(entity);
                    this.EnsureRowVersionValueIsNotNull(rowVersionValue);
                    keyValues.Add(rowVersionDescriptor, rowVersionValue);
                }
                else
                {
                    rowVersionValue    = rowVersionDescriptor.GetValue(entity);
                    rowVersionNewValue = PublicHelper.IncreaseRowVersionNumber(rowVersionValue);
                    updateColumns.Add(rowVersionDescriptor, DbExpression.Parameter(rowVersionNewValue, rowVersionDescriptor.PropertyType, rowVersionDescriptor.Column.DbType));
                    keyValues.Add(rowVersionDescriptor, rowVersionValue);
                }
            }

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

            DbTable            dbTable      = PublicHelper.CreateDbTable(typeDescriptor, table);
            DbExpression       conditionExp = PublicHelper.MakeCondition(keyValues, dbTable);
            DbUpdateExpression e            = new DbUpdateExpression(dbTable, conditionExp);

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

            int rowsAffected = 0;

            if (rowVersionDescriptor == null)
            {
                rowsAffected = await this.ExecuteNonQuery(e, @async);

                if (entityState != null)
                {
                    entityState.Refresh();
                }
                return(rowsAffected);
            }

            if (rowVersionDescriptor.IsTimestamp())
            {
                List <Action <TEntity, IDataReader> > mappers = new List <Action <TEntity, IDataReader> >();
                mappers.Add(GetMapper <TEntity>(rowVersionDescriptor, e.Returns.Count));
                e.Returns.Add(rowVersionDescriptor.Column);

                IDataReader dataReader = await this.ExecuteReader(e, @async);

                using (dataReader)
                {
                    while (dataReader.Read())
                    {
                        rowsAffected++;
                        foreach (var mapper in mappers)
                        {
                            mapper(entity, dataReader);
                        }
                    }
                }

                PublicHelper.CauseErrorIfOptimisticUpdateFailed(rowsAffected);
            }
            else
            {
                rowsAffected = await this.ExecuteNonQuery(e, @async);

                PublicHelper.CauseErrorIfOptimisticUpdateFailed(rowsAffected);
                rowVersionDescriptor.SetValue(entity, rowVersionNewValue);
            }

            if (entityState != null)
            {
                entityState.Refresh();
            }

            return(rowsAffected);
        }