Ejemplo n.º 1
0
        static Action <TEntity, IDataReader> GetMapper <TEntity>(PrimitivePropertyDescriptor propertyDescriptor, int ordinal)
        {
            var dbValueReader = DataReaderConstant.GetDbValueReader(propertyDescriptor.PropertyType);

            Action <TEntity, IDataReader> mapper = (TEntity entity, IDataReader reader) =>
            {
                object value = dbValueReader.GetValue(reader, ordinal);
                if (value == null || value == DBNull.Value)
                {
                    throw new ChloeException($"Unable to get the {propertyDescriptor.Property.Name} value from data reader.");
                }

                propertyDescriptor.SetValue(entity, value);
            };

            return(mapper);
        }
Ejemplo n.º 2
0
        protected virtual async Task <TEntity> Insert <TEntity>(TEntity entity, string table, bool @async)
        {
            PublicHelper.CheckNull(entity);

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

            Dictionary <PrimitivePropertyDescriptor, object> keyValueMap = PrimaryKeyHelper.CreateKeyValueMap(typeDescriptor);

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

            foreach (PrimitivePropertyDescriptor propertyDescriptor in typeDescriptor.PrimitivePropertyDescriptors)
            {
                if (propertyDescriptor.IsAutoIncrement)
                {
                    continue;
                }

                object val = propertyDescriptor.GetValue(entity);

                if (propertyDescriptor.IsPrimaryKey)
                {
                    keyValueMap[propertyDescriptor] = val;
                }

                PublicHelper.NotNullCheck(propertyDescriptor, val);

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

            PrimitivePropertyDescriptor nullValueKey = keyValueMap.Where(a => a.Value == null && !a.Key.IsAutoIncrement).Select(a => a.Key).FirstOrDefault();

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

            DbTable            dbTable = PublicHelper.CreateDbTable(typeDescriptor, table);
            DbInsertExpression e       = new DbInsertExpression(dbTable);

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

            PrimitivePropertyDescriptor autoIncrementPropertyDescriptor = typeDescriptor.AutoIncrement;

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

                return(entity);
            }

            IDbExpressionTranslator translator    = this.DatabaseProvider.CreateDbExpressionTranslator();
            DbCommandInfo           dbCommandInfo = translator.Translate(e);

            dbCommandInfo.CommandText = string.Concat(dbCommandInfo.CommandText, ";", this.GetSelectLastInsertIdClause());

            //SELECT @@IDENTITY 返回的是 decimal 类型
            object retIdentity = await this.ExecuteScalar(dbCommandInfo, @async);

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

            retIdentity = PublicHelper.ConvertObjectType(retIdentity, autoIncrementPropertyDescriptor.PropertyType);
            autoIncrementPropertyDescriptor.SetValue(entity, retIdentity);
            return(entity);
        }
Ejemplo n.º 3
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);
        }