Example #1
0
        public SyncResponse Sync(SyncRequest request)
        {
            lock (this.changeSetLock)
            {
                if (this.sharedChangeSetN == 0)
                {
                    using (var db = new BrennContext())
                    {
                        this.sharedChangeSetN =
                            new[]
                                {
                                    db.Expenses.Max<Expense, int?>(e => e.ChangeSetN),
                                    db.Trips.Max<Trip, int?>(e => e.ChangeSetN),
                                    db.People.Max<Person, int?>(e => e.ChangeSetN)
                                }.Max().GetValueOrDefault(1);
                    }
                }
            }

            var anyUpdates = (request.ExpenseUpdates == null ? 0 : request.ExpenseUpdates.Count) +
                             (request.TripUpdates == null ? 0 : request.TripUpdates.Count) +
                             (request.PersonUpdates == null ? 0 : request.PersonUpdates.Count) > 0;

            var changeSetN = anyUpdates ? Interlocked.Increment(ref this.sharedChangeSetN) : this.sharedChangeSetN;

            var response = new SyncResponse
                {
                    ExpenseUpdateResults = new List<UpdateResult>(),
                    TripUpdateResults = new List<UpdateResult>(),
                    PersonUpdateResults = new List<UpdateResult>(),
                    ServerChangeSetN = changeSetN
                };

            var updatedExpenseIds = new List<int>();
            var updatedTripIds = new List<int>();
            var updatedPersonIds = new List<int>();

            PerformExpenseUpdates(request, response, updatedExpenseIds);
            PerformTripUpdates(request, response, updatedTripIds);
            PerformPersonUpdates(request, response, updatedPersonIds);

            using (var db = new BrennContext())
            {
                ((IObjectContextAdapter)db).ObjectContext.ContextOptions.ProxyCreationEnabled = false;

                response.Expenses =
                    new List<Expense>(
                        db.Expenses.Include("Receivers").Where(
                            e => e.ChangeSetN > request.ClientChangeSetN && !updatedExpenseIds.Contains(e.ExpenseId)));

                response.Trips =
                    new List<Trip>(
                        db.Trips
                        .Where(
                            e => e.ChangeSetN > request.ClientChangeSetN && !updatedTripIds.Contains(e.TripId)));

                response.Trips.ForEach(t => t.Expenses = null);

                response.People =
                    new List<Person>(
                        db.People
                        .Where(e => e.ChangeSetN > request.ClientChangeSetN && !updatedPersonIds.Contains(e.PersonId)));
            }

            return response;
        }
Example #2
0
        private static void PerformTripUpdates(
            SyncRequest request, SyncResponse response, ICollection<int> updatedTripIds)
        {
            if (request.TripUpdates == null)
            {
                return;
            }

            foreach (var tripUpdate in request.TripUpdates)
            {
                if (tripUpdate.ClientRowId == default(Guid))
                {
                    throw new Exception("The client row id must be set.");
                }

                using (var db = new BrennContext())
                {
                    using (var scope = new TransactionScope())
                    {
                        if (tripUpdate.Trip.TripId == default(int))
                        {
                            db.Trips.Add(tripUpdate.Trip);
                        }
                        else
                        {
                            var trip = db.Trips.Find(tripUpdate.Trip.TripId);

                            if (trip == null)
                            {
                                response.TripUpdateResults.Add(
                                    new UpdateResult
                                        {
                                            Error = UpdateError.DeletedOnServer, ClientRowId = tripUpdate.Trip.RowId
                                        });
                                continue;
                            }

                            if (trip.RowId != tripUpdate.ClientRowId)
                            {
                                response.TripUpdateResults.Add(
                                    new UpdateResult
                                        {
                                            Error = UpdateError.ModifiedOnServer, ClientRowId = tripUpdate.Trip.RowId
                                        });
                                continue;
                            }

                            var entry = db.Entry(trip);
                            entry.CurrentValues.SetValues(tripUpdate.Trip);
                        }

                        db.SaveChanges();

                        scope.Complete();
                    }

                    response.TripUpdateResults.Add(
                        new UpdateResult { Error = null, ClientRowId = tripUpdate.Trip.RowId });

                    updatedTripIds.Add(tripUpdate.Trip.TripId);
                }
            }
        }
Example #3
0
        private static void PerformPersonUpdates(
            SyncRequest request, SyncResponse response, ICollection<int> updatedPersonIds)
        {
            if (request.PersonUpdates == null)
            {
                return;
            }

            foreach (var personUpdate in request.PersonUpdates)
            {
                using (var db = new BrennContext())
                {
                    using (var scope = new TransactionScope())
                    {
                        var person = db.People.Find(personUpdate.Person.PersonId);

                        if (person == null)
                        {
                            response.PersonUpdateResults.Add(
                                new UpdateResult { Error = UpdateError.DeletedOnServer, ClientRowId = personUpdate.Person.RowId });
                            continue;
                        }

                        if (person.RowId != personUpdate.ClientRowId)
                        {
                            response.PersonUpdateResults.Add(
                                new UpdateResult { Error = UpdateError.ModifiedOnServer, ClientRowId = personUpdate.Person.RowId });
                            continue;
                        }

                        var entry = db.Entry(person);
                        entry.CurrentValues.SetValues(personUpdate.Person);

                        db.SaveChanges();

                        scope.Complete();
                    }

                    response.PersonUpdateResults.Add(
                        new UpdateResult { Error = null, ClientRowId = personUpdate.Person.RowId });

                    updatedPersonIds.Add(personUpdate.Person.PersonId);
                }
            }
        }
Example #4
0
        private static void PerformExpenseUpdates(
            SyncRequest request, SyncResponse response, List<int> updatedExpenseIds)
        {
            if (request.ExpenseUpdates == null)
            {
                return;
            }

            foreach (ExpenseUpdate expenseUpdate in request.ExpenseUpdates)
            {
                using (var db = new BrennContext())
                {
                    using (var scope = new TransactionScope())
                    {
                        var expense = db.Expenses.Find(expenseUpdate.Expense.ExpenseId);

                        if (expense == null)
                        {
                            response.ExpenseUpdateResults.Add(
                                new UpdateResult
                                    { Error = UpdateError.DeletedOnServer, ClientRowId = expenseUpdate.Expense.RowId });
                            continue;
                        }

                        if (expense.RowId != expenseUpdate.ClientRowId)
                        {
                            response.ExpenseUpdateResults.Add(
                                new UpdateResult
                                    { Error = UpdateError.ModifiedOnServer, ClientRowId = expenseUpdate.Expense.RowId });
                            continue;
                        }

                        var entry = db.Entry(expense);
                        entry.CurrentValues.SetValues(expenseUpdate.Expense);

                        db.SaveChanges();

                        scope.Complete();
                    }

                    response.ExpenseUpdateResults.Add(
                        new UpdateResult { Error = null, ClientRowId = expenseUpdate.Expense.RowId });

                    updatedExpenseIds.Add(expenseUpdate.Expense.ExpenseId);
                }
            }
        }
Example #5
0
        /// <summary>
        /// The handle sync response without lock.
        /// </summary>
        /// <param name="response">
        /// The response.
        /// </param>
        private void HandleSyncResponseWithoutLock(SyncResponse response)
        {
            Debug.WriteLine("Handling sync response with server change set {0}.", response.ServerChangeSetN);

            if (response.ServerChangeSetN <= this.clientChangeSet)
            {
                Debug.WriteLine(
                    "Warning: The changeset number of the sync response is {0}, which is lower than or equal to the client version, {1}.",
                    response.ServerChangeSetN,
                    this.clientChangeSet);
            }
            else
            {
                this.clientChangeSet = response.ServerChangeSetN;
            }

            foreach (var update in response.ExpenseUpdateResults)
            {
                if (update.Error.HasValue)
                {
                    Debug.WriteLine("Failed to update expense: {0}", update.Error);
                }
                else
                {
                    Debug.WriteLine("Successful update of expense.");
                }
            }

            foreach (var update in response.TripUpdateResults)
            {
                if (update.Error.HasValue)
                {
                    Debug.WriteLine("Failed to update trip: {0}", update.Error);
                }
                else
                {
                    Debug.WriteLine("Successful update of trip.");
                }
            }

            foreach (var update in response.PersonUpdateResults)
            {
                if (update.Error.HasValue)
                {
                    Debug.WriteLine("Failed to update person: {0}", update.Error);
                }
                else
                {
                    Debug.WriteLine("Successful update of person.");
                }
            }

            if (response.People != null)
            {
                response.People.ForEach(p => Repository.Instance.AddOrUpdate(p));
            }

            if (response.Trips != null)
            {
                foreach (var t in response.Trips)
                {
                    Debug.Assert(t.Expenses == null, "The trip included its expenses.");

                    Repository.Instance.AddOrUpdate(t);
                }
            }

            if (response.Expenses != null)
            {
                foreach (var expense in response.Expenses)
                {
                    Debug.Assert(expense.Receivers != null, "Receivers was not included from the service.");
                    Debug.Assert(expense.Trip == null, "The trip should not be defined by the expense.");
                    Debug.Assert(expense.TripId > 0, "The trip id must be included.");

                    Repository.Instance.AddOrUpdate(expense);
                }
            }
        }
Example #6
0
        /// <summary>
        /// The handle sync response.
        /// </summary>
        /// <param name="response">
        /// The response.
        /// </param>
        private void HandleSyncResponse(SyncResponse response)
        {
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            lock (this.items)
            {
                this.HandleSyncResponseWithoutLock(response);
            }
        }