Ejemplo n.º 1
0
 protected override void Dispose(bool explicitDispose)
 {
     _referenceKeyProvider = null;
     _baseCtx = null;
     //
     base.Dispose(explicitDispose);
 }
Ejemplo n.º 2
0
            // TODO: Put strings into the resources.
            //
            async Task P_SaveAsync(TEntity[] entityCollection, SaveOpCode opCode, bool prohibitReferenceKeyAssignment, IContext ctx = default)
            {
                if (entityCollection is null)
                {
                    throw new ArgumentNullException(paramName: nameof(entityCollection));
                }
                //
                var entityCollectionLength = entityCollection.Length;

                if (entityCollectionLength > 0)
                {
                    var entityCollectionLowerBound = entityCollection.GetLowerBound(dimension: 0);
                    var locEntityCollection        = new P_EntityChangeTrackingStateWrap <TEntity> [entityCollectionLength];
                    var ct        = ctx.Ct();
                    var efContext = GetDataChangeEfDbContext();
                    switch (opCode)
                    {
                    case SaveOpCode.Write:
                        if (prohibitReferenceKeyAssignment)
                        {
                            for (var offset = 0; offset < entityCollectionLength; offset++)
                            {
                                var entity = entityCollection[offset + entityCollectionLowerBound];
                                if (entity is null)
                                {
                                    throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                                }
                                else
                                {
                                    locEntityCollection[offset].Entity = entity;
                                    locEntityCollection[offset].State  = entity.IsNew ? EntityState.Added : EntityState.Modified;
                                }
                            }
                        }
                        else
                        {
                            IReferenceKeyProvider <TReferenceKey> keyProvider = default;
                            for (var offset = 0; offset < entityCollectionLength; offset++)
                            {
                                var entity = entityCollection[offset + entityCollectionLowerBound];
                                if (entity is null)
                                {
                                    throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                                }
                                else
                                {
                                    locEntityCollection[offset].Entity = entity;
                                    if (entity.IsNew)
                                    {
                                        keyProvider = keyProvider ?? await P_RequireReferenceKeyProviderAsync(ctx : ctx).ConfigureAwait(false);

                                        entity.ReferenceKey = await keyProvider.NextKeyAsync(ctx : ctx).ConfigureAwait(false);

                                        locEntityCollection[offset].State = EntityState.Added;
                                    }
                                    else
                                    {
                                        locEntityCollection[offset].State = EntityState.Modified;
                                    }
                                }
                            }
                        }
                        break;

                    case SaveOpCode.Insert:
                        if (prohibitReferenceKeyAssignment)
                        {
                            for (var offset = 0; offset < entityCollectionLength; offset++)
                            {
                                var entity = entityCollection[offset + entityCollectionLowerBound];
                                if (entity is null)
                                {
                                    throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                                }
                                else
                                {
                                    locEntityCollection[offset].Entity = entity;
                                    locEntityCollection[offset].State  = EntityState.Added;
                                }
                            }
                        }
                        else
                        {
                            IReferenceKeyProvider <TReferenceKey> keyProvider = default;
                            for (var offset = 0; offset < entityCollectionLength; offset++)
                            {
                                var entity = entityCollection[offset + entityCollectionLowerBound];
                                if (entity is null)
                                {
                                    throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                                }
                                else
                                {
                                    if (entity.IsNew)
                                    {
                                        keyProvider = keyProvider ?? await P_RequireReferenceKeyProviderAsync(ctx : ctx).ConfigureAwait(false);

                                        entity.ReferenceKey = await keyProvider.NextKeyAsync(ctx : ctx).ConfigureAwait(false);
                                    }
                                    locEntityCollection[offset].Entity = entity;
                                    locEntityCollection[offset].State  = EntityState.Added;
                                }
                            }
                        }
                        break;

                    case SaveOpCode.Update:
                        for (var offset = 0; offset < entityCollectionLength; offset++)
                        {
                            var entity = entityCollection[offset + entityCollectionLowerBound];
                            if (entity is null)
                            {
                                throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                            }
                            else
                            {
                                locEntityCollection[offset].Entity = entity;
                                locEntityCollection[offset].State  = EntityState.Modified;
                            }
                        }
                        break;

                    case SaveOpCode.Delete:
                        for (var offset = 0; offset < entityCollectionLength; offset++)
                        {
                            var entity = entityCollection[offset + entityCollectionLowerBound];
                            if (entity is null)
                            {
                                throw new ArgumentNullException(paramName: $"{nameof(entityCollection)}[{offset + entityCollectionLowerBound:d}]");
                            }
                            else
                            {
                                locEntityCollection[offset].Entity = entity;
                                locEntityCollection[offset].State  = EntityState.Deleted;
                            }
                        }
                        break;

                    default:
                        throw new NotSupportedException(message: $"Store operation code '{opCode}' is not supported.");
                    }
                    // Сохранение.
                    //
                    var saveFault = default(Exception);
                    try {
                        for (var y = 0; y < entityCollectionLength; y++)
                        {
                            try {
                                (locEntityCollection[y].Entry = efContext.Entry(entity: locEntityCollection[y].Entity)).State = locEntityCollection[y].State;
                            }
                            catch (Exception exception) {
                                throw
                                    new EonException(
                                        message: $"An exception occurred while placing the entity in EF context (change tracker).{Environment.NewLine}\tEntity ({y + 1:d} from {entityCollectionLength:d}):{locEntityCollection[ y ].Entity.FmtStr().GNLI2()}{Environment.NewLine}\tPlacing entity state:{locEntityCollection[ y ].State.FmtStr().GNLI2()}{Environment.NewLine}\tStore operation code:{opCode.FmtStr().GNLI2()}",
                                        innerException: exception);
                            }
                        }
                        //
                        try {
                            await efContext.SaveChangesAsync(acceptAllChangesOnSuccess : true, ct : ct).ConfigureAwait(false);
                        }
                        catch (Exception exception) {
#if TRG_NETFRAMEWORK
                            if (exception is OptimisticConcurrencyException || exception is DbUpdateConcurrencyException)
#else
                            if (exception is DbUpdateConcurrencyException)
#endif
                            { throw new DataStorageOptimisticConcurrencyException(message: $"Объект:{(locEntityCollection.Length == 1 ? locEntityCollection[ 0 ].Entity?.ToString() : $"<коллекция из {locEntityCollection.Length:d} элементов>").FmtStr().GNLI2()}"); }
                            throw;
                        }
                    }
                    catch (Exception exception) {
                        saveFault = exception;
                        throw;
                    }
                    finally {
                        try {
                            for (var y = 0; y < entityCollectionLength; y++)
                            {
                                locEntityCollection[y].Entry.State = EntityState.Detached;
                            }
                        }
                        catch (Exception exception) {
                            if (saveFault is null)
                            {
                                throw;
                            }
                            else
                            {
                                throw new AggregateException(saveFault, exception);
                            }
                        }
                    }
                }
            }