Exemple #1
0
        bool CanRemove(TEntity data, bool isThrow)
        {
            if (data == null)
            {
                if (isThrow)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                return(false);
            }
            if (_table.Primarys.Any() == false)
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotDelete_EntityHasNo_PrimaryKey(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);

            if (string.IsNullOrEmpty(key))
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotDelete_PrimaryKey_NotSet(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            //if (_states.TryGetValue(key, out var tryval) == false) {
            //	if (isThrow) throw new Exception($"不可删除,数据未被跟踪,应该先查询:{_fsql.GetEntityString(_entityType, data)}");
            //	return false;
            //}
            return(true);
        }
        protected override IUpdate <TEntity> OrmUpdate(IEnumerable <TEntity> entitys)
        {
            var update  = base.OrmUpdate(entitys).AsTable(_repo.AsTableValueInternal);
            var filters = (_repo.DataFilter as DataFilter <TEntity>)._filters;

            foreach (var filter in filters.Where(a => a.Value.IsEnabled == true))
            {
                if (entitys != null)
                {
                    foreach (var entity in entitys)
                    {
                        if (filter.Value.ExpressionDelegate?.Invoke(entity) == false)
                        {
                            throw new Exception(DbContextStrings.UpdateError_Filter(filter.Key, filter.Value.Expression, _db.OrmOriginal.GetEntityString(_entityType, entity)));
                        }
                    }
                }
                update.Where(filter.Value.Expression);
            }
            var disableFilter = filters.Where(a => a.Value.IsEnabled == false).Select(a => a.Key).ToList();

            disableFilter.AddRange((_repo.DataFilter as DataFilter <TEntity>)._filtersByOrm.Where(a => a.Value.IsEnabled == false).Select(a => a.Key));
            if (disableFilter.Any())
            {
                update.DisableGlobalFilter(disableFilter.ToArray());
            }
            return(update);
        }
Exemple #3
0
        /// <summary>
        /// 比较实体,计算出值发生变化的属性,以及属性变化的前后值
        /// </summary>
        /// <param name="newdata">最新的实体对象,它将与附加实体的状态对比</param>
        /// <returns>key: 属性名, value: [旧值, 新值]</returns>
        public Dictionary <string, object[]> CompareState(TEntity newdata)
        {
            if (newdata == null)
            {
                return(null);
            }
            if (_table.Primarys.Any() == false)
            {
                throw new Exception(DbContextStrings.Incomparable_EntityHasNo_PrimaryKey(_db.OrmOriginal.GetEntityString(_entityType, newdata)));
            }
            var key = _db.OrmOriginal.GetEntityKeyString(_entityType, newdata, false);

            if (string.IsNullOrEmpty(key))
            {
                throw new Exception(DbContextStrings.Incomparable_PrimaryKey_NotSet(_db.OrmOriginal.GetEntityString(_entityType, newdata)));
            }
            if (_states.TryGetValue(key, out var oldState) == false || oldState == null)
            {
                return(_table.ColumnsByCs.ToDictionary(a => a.Key, a => new object[]
                {
                    _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, newdata, a.Key),
                    null
                }));
            }

            return(_db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, oldState.Value, newdata, false).ToDictionary(a => a, a => new object[]
            {
                _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, newdata, a),
                _db.OrmOriginal.GetEntityValueWithPropertyName(_entityType, oldState.Value, a)
            }));
        }
Exemple #4
0
        public void AttachRange(IEnumerable <TEntity> data)
        {
            if (data == null || data.Any() == false)
            {
                return;
            }
            if (_table.Primarys.Any() == false)
            {
                throw new Exception(DbContextStrings.CannotAttach_EntityHasNo_PrimaryKey(_db.OrmOriginal.GetEntityString(_entityType, data.First())));
            }
            foreach (var item in data)
            {
                var key = _db.OrmOriginal.GetEntityKeyString(_entityType, item, false);
                if (string.IsNullOrEmpty(key))
                {
                    throw new Exception(DbContextStrings.CannotAttach_PrimaryKey_NotSet(_db.OrmOriginal.GetEntityString(_entityType, item)));
                }

                _states.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) =>
                {
                    _db.OrmOriginal.MapEntityValue(_entityType, item, ov.Value);
                    ov.Time = DateTime.Now;
                    return(ov);
                });
            }
        }
Exemple #5
0
 public UnitOfWorkManager(IFreeSql fsql)
 {
     if (fsql == null)
     {
         throw new ArgumentNullException(DbContextStrings.UnitOfWorkManager_Construction_CannotBeNull(nameof(UnitOfWorkManager), nameof(fsql)));
     }
     _ormScoped = DbContextScopedFreeSql.Create(fsql, null, () => this.Current);
 }
Exemple #6
0
        async Task <int> DbContextBatchUpdatePrivAsync(EntityState[] ups, bool isLiveUpdate, CancellationToken cancellationToken)
        {
            if (ups.Any() == false)
            {
                return(0);
            }
            var uplst1 = ups[ups.Length - 1];
            var uplst2 = ups.Length > 1 ? ups[ups.Length - 2] : null;

            if (_states.TryGetValue(uplst1.Key, out var lstval1) == false)
            {
                return(-999);
            }
            var lstval2 = default(EntityState);

            if (uplst2 != null && _states.TryGetValue(uplst2.Key, out lstval2) == false)
            {
                throw new Exception(DbContextStrings.SpecialError_UpdateFailedDataNotTracked(_db.OrmOriginal.GetEntityString(_entityType, uplst2.Value)));
            }

            var cuig1 = _db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst1.Value, lstval1.Value, true);
            var cuig2 = uplst2 != null?_db.OrmOriginal.CompareEntityValueReturnColumns(_entityType, uplst2.Value, lstval2.Value, true) : null;

            List <EntityState> data = null;

            string[] cuig = null;
            if (uplst2 != null && string.Compare(string.Join(",", cuig1), string.Join(",", cuig2)) != 0)
            {
                //最后一个不保存
                data = ups.ToList();
                data.RemoveAt(ups.Length - 1);
                cuig = cuig2;
            }
            else if (isLiveUpdate)
            {
                //立即保存
                data = ups.ToList();
                cuig = cuig1;
            }

            if (data?.Count > 0)
            {
                if (cuig.Length == _table.Columns.Count)
                {
                    return(ups.Length == data.Count ? -998 : -997);
                }

                var update  = this.OrmUpdate(null).SetSource(data.Select(a => a.Value)).IgnoreColumns(cuig);
                var affrows = await update.ExecuteAffrowsAsync(cancellationToken);

                _db._entityChangeReport.AddRange(data.Select(a => new DbContext.EntityChangeReport.ChangeInfo
                {
                    EntityType   = _entityType,
                    Object       = a.Value,
                    BeforeObject = _states.TryGetValue(a.Key, out var beforeVal) ? CreateEntityState(beforeVal.Value).Value : null,
                    Type         = DbContext.EntityChangeType.Update
                }));
        protected override IInsert <TEntity> OrmInsert(IEnumerable <TEntity> entitys)
        {
            var insert  = base.OrmInsert(entitys).AsTable(_repo.AsTableValueInternal);
            var filters = (_repo.DataFilter as DataFilter <TEntity>)._filters.Where(a => a.Value.IsEnabled == true);

            foreach (var filter in filters)
            {
                if (entitys != null)
                {
                    foreach (var entity in entitys)
                    {
                        if (filter.Value.ExpressionDelegate?.Invoke(entity) == false)
                        {
                            throw new Exception(DbContextStrings.InsertError_Filter(filter.Key, filter.Value.Expression, _db.OrmOriginal.GetEntityString(_entityType, entity)));
                        }
                    }
                }
            }
            return(insert);
        }
Exemple #8
0
        bool CanUpdate(TEntity data, bool isThrow)
        {
            if (data == null)
            {
                if (isThrow)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                return(false);
            }
            if (_table.Primarys.Any() == false)
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotUpdate_EntityHasNo_PrimaryKey(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            FreeSql.Internal.CommonProvider.UpdateProvider <TEntity> .AuditDataValue(this, data, _db.OrmOriginal, _table, null);

            var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, false);

            if (string.IsNullOrEmpty(key))
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotUpdate_PrimaryKey_NotSet(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            if (_states.TryGetValue(key, out var tryval) == false)
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotUpdate_DataShouldQueryOrAttach(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            return(true);
        }
Exemple #9
0
        async public Task SaveManyAsync(TEntity item, string propertyName, CancellationToken cancellationToken = default)
        {
            if (item == null)
            {
                return;
            }
            if (string.IsNullOrEmpty(propertyName))
            {
                return;
            }
            if (_table.Properties.TryGetValue(propertyName, out var prop) == false)
            {
                throw new KeyNotFoundException(DbContextStrings.NotFound_Property(_table.Type.FullName, propertyName));
            }
            if (_table.ColumnsByCsIgnore.ContainsKey(propertyName))
            {
                throw new ArgumentException(DbContextStrings.TypeHasSetProperty_IgnoreAttribute(_table.Type.FullName, propertyName));
            }

            var tref = _table.GetTableRef(propertyName, true);

            if (tref == null)
            {
                return;
            }
            switch (tref.RefType)
            {
            case Internal.Model.TableRefType.OneToOne:
            case Internal.Model.TableRefType.ManyToOne:
                throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName));
            }

            await DbContextFlushCommandAsync(cancellationToken);

            var oldEnable = _db.Options.EnableCascadeSave;

            _db.Options.EnableCascadeSave = false;
            try
            {
                await AddOrUpdateNavigateAsync(item, false, propertyName, cancellationToken);

                if (tref.RefType == Internal.Model.TableRefType.OneToMany)
                {
                    await DbContextFlushCommandAsync(cancellationToken);

                    //删除没有保存的数据,求出主体的条件
                    var        deleteWhereParentParam = Expression.Parameter(typeof(object), "a");
                    Expression whereParentExp         = null;
                    for (var colidx = 0; colidx < tref.Columns.Count; colidx++)
                    {
                        var whereExp = Expression.Equal(
                            Expression.MakeMemberAccess(Expression.Convert(deleteWhereParentParam, tref.RefEntityType), tref.RefColumns[colidx].Table.Properties[tref.RefColumns[colidx].CsName]),
                            Expression.Constant(
                                FreeSql.Internal.Utils.GetDataReaderValue(
                                    tref.Columns[colidx].CsType,
                                    _db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType)
                            );
                        if (whereParentExp == null)
                        {
                            whereParentExp = whereExp;
                        }
                        else
                        {
                            whereParentExp = Expression.AndAlso(whereParentExp, whereExp);
                        }
                    }
                    var propValEach = GetItemValue(item, prop) as IEnumerable;
                    var subDelete   = _db.OrmOriginal.Delete <object>().AsType(tref.RefEntityType)
                                      .WithTransaction(_uow?.GetOrBeginTransaction())
                                      .Where(Expression.Lambda <Func <object, bool> >(whereParentExp, deleteWhereParentParam));
                    foreach (var propValItem in propValEach)
                    {
                        subDelete.WhereDynamic(propValEach, true);
                        break;
                    }
                    await subDelete.ExecuteAffrowsAsync(cancellationToken);
                }
            }
            finally
            {
                _db.Options.EnableCascadeSave = oldEnable;
            }
        }
Exemple #10
0
        async public Task AddRangeAsync(IEnumerable <TEntity> data, CancellationToken cancellationToken = default)
        {
            if (CanAdd(data, true) == false)
            {
                return;
            }
            if (data.ElementAtOrDefault(1) == default(TEntity))
            {
                await AddAsync(data.First(), cancellationToken);

                return;
            }
            if (_tableReturnColumns.Length > 0)
            {
                //有自增,马上执行
                switch (_db.OrmOriginal.Ado.DataType)
                {
                case DataType.SqlServer:
                case DataType.OdbcSqlServer:
                case DataType.PostgreSQL:
                case DataType.OdbcPostgreSQL:
                case DataType.KingbaseES:
                case DataType.OdbcKingbaseES:
                case DataType.ShenTong:
                    await DbContextFlushCommandAsync(cancellationToken);

                    var rets = await this.OrmInsert(data).ExecuteInsertedAsync(cancellationToken);

                    if (rets.Count != data.Count())
                    {
                        throw new Exception(DbContextStrings.SpecialError_BatchAdditionFailed(_db.OrmOriginal.Ado.DataType));
                    }
                    _db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeReport.ChangeInfo {
                        Object = a, Type = DbContext.EntityChangeType.Insert
                    }));
                    var idx = 0;
                    foreach (var s in data)
                    {
                        _db.OrmOriginal.MapEntityValue(_entityType, rets[idx++], s);
                    }
                    IncrAffrows(rets.Count);
                    AttachRange(rets);
                    if (_db.Options.EnableCascadeSave)
                    {
                        foreach (var item in data)
                        {
                            await AddOrUpdateNavigateAsync(item, true, null, cancellationToken);
                        }
                    }
                    return;

                default:
                    if (_tableIdentitys.Length == 1)
                    {
                        foreach (var s in data)
                        {
                            await AddPrivAsync(s, false, cancellationToken);
                        }
                        return;
                    }
                    break;
                }
            }
            //进入队列,等待 SaveChanges 时执行
            foreach (var item in data)
            {
                EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(item));
            }
            AttachRange(data);
            if (_db.Options.EnableCascadeSave)
            {
                foreach (var item in data)
                {
                    await AddOrUpdateNavigateAsync(item, true, null, cancellationToken);
                }
            }
        }
Exemple #11
0
        bool CanAdd(TEntity data, bool isThrow)
        {
            if (data == null)
            {
                if (isThrow)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                return(false);
            }
            if (_table.Primarys.Any() == false)
            {
                if (isThrow)
                {
                    throw new Exception(DbContextStrings.CannotAdd_EntityHasNo_PrimaryKey(_db.OrmOriginal.GetEntityString(_entityType, data)));
                }
                return(false);
            }
            FreeSql.Internal.CommonProvider.InsertProvider <TEntity> .AuditDataValue(this, data, _db.OrmOriginal, _table, null);

            var key = _db.OrmOriginal.GetEntityKeyString(_entityType, data, true);

            if (string.IsNullOrEmpty(key))
            {
                switch (_db.OrmOriginal.Ado.DataType)
                {
                case DataType.SqlServer:
                case DataType.OdbcSqlServer:
                case DataType.PostgreSQL:
                case DataType.OdbcPostgreSQL:
                case DataType.KingbaseES:
                case DataType.OdbcKingbaseES:
                case DataType.ShenTong:
                case DataType.ClickHouse:
                    return(true);

                default:
                    if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1)
                    {
                        return(true);
                    }
                    if (isThrow)
                    {
                        throw new Exception(DbContextStrings.CannotAdd_PrimaryKey_NotSet(_db.OrmOriginal.GetEntityString(_entityType, data)));
                    }
                    return(false);
                }
            }
            else
            {
                if (_states.ContainsKey(key))
                {
                    if (isThrow)
                    {
                        throw new Exception(DbContextStrings.CannotAdd_AlreadyExistsInStateManagement(_db.OrmOriginal.GetEntityString(_entityType, data)));
                    }
                    return(false);
                }
                if (_db.OrmOriginal.Ado.DataType == DataType.ClickHouse)
                {
                    return(true);
                }
                var idval = _db.OrmOriginal.GetEntityIdentityValueWithPrimary(_entityType, data);
                if (idval > 0)
                {
                    if (isThrow)
                    {
                        throw new Exception(DbContextStrings.CannotAdd_SelfIncreasingHasValue(_db.OrmOriginal.GetEntityString(_entityType, data)));
                    }
                    return(false);
                }
            }
            return(true);
        }