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; }
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); } } }
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); } } }
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); } } }
private static SyncResponse GetSyncResponseBlocking(SyncRequest request) { var responseLock = new System.Threading.AutoResetEvent(false); var response = default(SyncResponse); ServiceHelper.Instance.Queue<SyncRequest, SyncResponse>( "Sync", r => { response = r; responseLock.Set(); }, request); responseLock.WaitOne(); return response; }
/// <summary> /// The sync without lock. /// </summary> private void SyncWithoutLock() { var itemsToSync = this.items.ToList(); this.items.Clear(); var request = new SyncRequest { ClientChangeSetN = this.clientChangeSet, ExpenseUpdates = new List<ExpenseUpdate>(), TripUpdates = new List<TripUpdate>(), PersonUpdates = new List<PersonUpdate>() }; Debug.WriteLine("Syncing. Client change set is {0}.", request.ClientChangeSetN); foreach (var expense in itemsToSync.OfType<Expense>()) { var update = new ExpenseUpdate { ClientRowId = expense.RowId, Expense = expense }; expense.RowId = Guid.NewGuid(); request.ExpenseUpdates.Add(update); } foreach (var trip in itemsToSync.OfType<Trip>()) { var update = new TripUpdate { ClientRowId = trip.RowId, Trip = trip }; trip.RowId = Guid.NewGuid(); request.TripUpdates.Add(update); } foreach (var person in itemsToSync.OfType<Person>()) { var update = new PersonUpdate { ClientRowId = person.RowId, Person = person }; person.RowId = Guid.NewGuid(); request.PersonUpdates.Add(update); } ServiceHelper.Instance.Queue<SyncRequest, SyncResponse>("Sync", this.HandleSyncResponse, request); }