/// <summary>
        /// Saves pending changes asynchronously
        /// </summary>
        /// <remarks>Either use the task object returned or subscribe to the SaveChangesCompleted event to check for exeptions of the sync task.</remarks>
        /// <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>
        /// <param name="startImmediately">If set to true, async task is started automatically (has no effect if task sceduler is provided).</param>
        /// <param name="taskScheduler">If privided, async task is started automatically using task sceduler.</param>
        /// <param name="cancellationToken">Optional System.Threading.Tasks.Task.CancellationToken that the async task will observe.</param>
        /// <param name="taskCreationOptions">Optional System.Threading.Tasks.TaskCreationOptions used to customize the task's behavior.</param>
        /// <returns>The task being used for async execution</returns>
        public override Task SaveChangesAsync(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = true, bool failOnValidationErrors = true, ClientInfo clientInfo = null, bool startImmediately = true, TaskScheduler taskScheduler = null, CancellationToken cancellationToken = default(CancellationToken), TaskCreationOptions taskCreationOptions = TaskCreationOptions.None)
        {
            var task = new Task(
                () =>
            {
                // save operation
                Exception error = null;
                try
                {
                    SaveChanges(acceptOption, clearErrors, failOnValidationErrors, clientInfo);
                }
                catch (Exception e)
                {
                    if (!HasSaveChangesCompletedHandler && !cancellationToken.IsCancellationRequested)
                    {
                        // if error occurred and no completed event handler registered, exception is re-thrown and is required to be handled using the task instance
                        throw;
                    }

                    error = e;
                }

                // return upon cancellation
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                OnSaveChangesCompleted(error);
            },
                cancellationToken == default(CancellationToken) ? CancellationToken.None : cancellationToken,
                taskCreationOptions
                );

            if (taskScheduler != null)
            {
                task.Start(taskScheduler);
            }
            else if (startImmediately)
            {
                task.Start();
            }

            return(task);
        }
示例#2
0
 /// <summary>
 /// Saves pending changes asynchronously
 /// </summary>
 /// <remarks>Either use the task object returned or subscribe to the SaveChangesCompleted event to check for exeptions of the sync task.</remarks>
 /// <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>
 /// <param name="startImmediately">If set to true, async task is started automatically (has no effect if task sceduler is provided).</param>
 /// <param name="taskScheduler">If privided, async task is started automatically using task sceduler.</param>
 /// <param name="cancellationToken">Optional System.Threading.Tasks.Task.CancellationToken that the async task will observe.</param>
 /// <param name="taskCreationOptions">Optional System.Threading.Tasks.TaskCreationOptions used to customize the task's behavior.</param>
 /// <returns>The task being used for async execution</returns>
 public abstract Task SaveChangesAsync(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = true, bool failOnValidationErrors = true, ClientInfo clientInfo = null, bool startImmediately = true, TaskScheduler taskScheduler = null, CancellationToken cancellationToken = default(CancellationToken), TaskCreationOptions taskCreationOptions = TaskCreationOptions.None);
示例#3
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 abstract void SaveChanges(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = true, bool failOnValidationErrors = true, ClientInfo clientInfo = null);
        /// <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);
            }
                );
        }
 public abstract void SaveChangesAsync(AcceptOption acceptOption = AcceptOption.Default, bool clearErrors = false, bool failOnValidationErrors = true, ClientInfo clientInfo = null, Action <Exception> callback = null);