Exemplo n.º 1
0
        /// <summary>
        /// Saves pending changes
        /// </summary>
        /// <param name="acceptOption">Defines when changes should be accepted locally</param>
        /// <param name="clearErrors">If set to true, all error entries are cleared before saving chnages</param>
        /// <param name="failOnValidationErrors">If set to true, exception is thrown if IsValid=false, otherwise invalid entities are skipped from saving silently</param>
        /// <param name="clientInfo">Optional client info object, to be submitted to the server</param>
        public override void SaveChanges(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = true, bool failOnValidationErrors = true, ClientInfo clientInfo = null)
        {
            if (acceptOption == AcceptOption.Default)
            {
                acceptOption = System.Transactions.Transaction.Current != null ? AcceptOption.AcceptChangesOnTransactionCompleted : AcceptOption.AcceptChangesAfterSave;
            }

            if (clearErrors)
            {
                ClearErrors();
            }

            if (failOnValidationErrors && !IsValid)
            {
                throw new ValidationException("Validation failed for one or more entities.");
            }

            // submit data
            TResultSet resultSet;

            try
            {
                resultSet = SubmitChanges(clientInfo ?? ClientInfo);
            }
            catch (FaultException ex)
            {
                var faultExceptionType = ex.GetType();
                if (faultExceptionType.IsGenericType)
                {
                    var detailType     = faultExceptionType.GetGenericArguments()[0];
                    var detailProperty = typeof(FaultException <>).MakeGenericType(detailType).GetProperty("Detail");
                    var detail         = detailProperty.GetValue(ex, null);
                    if (detail is OptimisticConcurrencyFault)
                    {
                        var stateEntries = GetStateEntries(((OptimisticConcurrencyFault)detail).Entities);
                        throw new OptimisticConcurrencyException(null, stateEntries);
                    }
                    if (detail is UpdateFault)
                    {
                        var stateEntries = GetStateEntries(((UpdateFault)detail).Entities);
                        throw new UpdateException(null, stateEntries);
                    }
                }
                throw;
            }

            // accept changes
            switch (acceptOption)
            {
            case AcceptOption.AcceptChangesAfterSave:
            {
                // refresh local data
                var hasValidationErrors = IsServerValidationExceptionSuppressed ? false : resultSet.Any(entity => entity.Errors.Any(e => e.IsError));
                Refresh(resultSet);
                if (hasValidationErrors)
                {
                    throw new ServerValidationException();
                }
                AcceptChanges(true);
            }
            break;

            case AcceptOption.None:
            {
                // store result in private list
                // allowes user to apply result (accept changes) asynchronousely
                ResultSets.Add(resultSet);

                // remove result from private list in case of a transaction rollback
                var transaction = System.Transactions.Transaction.Current;
                if (transaction != null)
                {
                    transaction.TransactionCompleted += (sender, e) =>
                    {
                        if (e.Transaction.TransactionInformation.Status != TransactionStatus.Committed)
                        {
                            ResultSets.Remove(resultSet);
                        }
                    };
                }
            }
            break;

            case AcceptOption.AcceptChangesOnTransactionCompleted:
            {
                var transaction = System.Transactions.Transaction.Current;
                if (transaction == null)
                {
                    throw new Exception(string.Format("{0}.{1} requires an active transaction scope.", acceptOption.GetType().Name, acceptOption));
                }

                // accept changes upon successfull completion of transaction
                transaction.TransactionCompleted += (sender, e) =>
                {
                    if (e.Transaction.TransactionInformation.Status == TransactionStatus.Committed)
                    {
                        // refresh local data
                        var hasValidationErrors = IsServerValidationExceptionSuppressed ? false : resultSet.Any(entity => entity.Errors.Any(error => error.IsError));
                        Refresh(resultSet);
                        if (hasValidationErrors)
                        {
                            throw new ServerValidationException();
                        }
                    }
                };
            }
            break;

            default:
                throw new Exception(string.Format("This {0} is not implemented: {1}", acceptOption.GetType().Name, acceptOption));
            }

            //if (resultSet.HasConcurrencyConflicts)
            //{
            //    HandleConcurrencyConflicts(resultSet);
            //}
        }
        /// <summary>
        /// Saves pending changes
        /// </summary>
        /// <param name="acceptOption">Defines when changes should be accepted locally</param>
        /// <param name="clearErrors">If set to true, all error entries are cleared before saving chnages</param>
        /// <param name="clientInfo">Optional client info object, to be submitted to the server</param>
        public override void SaveChangesAsync(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = true, bool failOnValidationErrors = true, ClientInfo clientInfo = null, Action <Exception> callback = null)
        {
            if (acceptOption == AcceptOption.Default)
            {
                //acceptOption = Transaction.Current != null ? AcceptOption.AcceptChangesOnTransactionCompleted : AcceptOption.AcceptChangesAfterSave;
                acceptOption = AcceptOption.AcceptChangesAfterSave;
            }

            if (clearErrors)
            {
                ClearErrors();
            }

            if (failOnValidationErrors && !IsValid)
            {
                throw new ValidationException("Validation failed for one or more entities.");
            }

            SubmitChangesAsync(
                clientInfo ?? ClientInfo,
                (resultSet, exception) =>
            {
                var error = exception;
                if (error == null)
                {
                    try
                    {
                        // accept changes
                        switch (acceptOption)
                        {
                        case AcceptOption.AcceptChangesAfterSave:
                            // refresh local data
                            var hasValidationErrors = IsServerValidationExceptionSuppressed ? false : resultSet.Any(entity => entity.Errors.Any(e => e.IsError));
                            Refresh(resultSet);
                            if (hasValidationErrors)
                            {
                                throw new ServerValidationException();
                            }
                            AcceptChanges(true);
                            break;

                        case AcceptOption.None:
                            // store result in private list
                            // allowes user to apply result (accept changes) asynchronousely
                            ResultSets.Add(resultSet);
                            break;

                        default:
                            throw new Exception(string.Format("This {0} is not implemented: {1}", acceptOption.GetType().Name, acceptOption));
                        }
                    }
                    catch (Exception ex)
                    {
                        error = ex;
                    }
                }

                if (error is FaultException)
                {
                    var ex = (FaultException)error;
                    var faultExceptionType = ex.GetType();
                    if (faultExceptionType.IsGenericType)
                    {
                        var detailType     = faultExceptionType.GetGenericArguments()[0];
                        var detailProperty = typeof(FaultException <>).MakeGenericType(detailType).GetProperty("Detail");
                        var detail         = detailProperty.GetValue(ex, null);
                        if (detail is OptimisticConcurrencyFault)
                        {
                            var stateEntries = GetStateEntries(((OptimisticConcurrencyFault)detail).Entities);
                            error            = new OptimisticConcurrencyException(null, stateEntries);
                        }
                        if (detail is UpdateFault)
                        {
                            var stateEntries = GetStateEntries(((UpdateFault)detail).Entities);
                            error            = new UpdateException(null, stateEntries);
                        }
                    }
                }

                if (callback != null)
                {
                    Invoke(delegate
                    {
                        callback(error);
                    });
                }
                OnSaveChangesCompleted(error);
            }
                );
        }