public async Task DeleteAsync_WithQuery_SendsNotification() { var store = new MobileServiceLocalStoreMock(); var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty); var eventManager = new MobileServiceEventManagerMock <IMobileServiceEvent>(); var settings = new MobileServiceSyncSettingsManager(store); var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings); JObject item = EnqueueSimpleObjectResponse(store); StoreOperationCompletedEvent operationEvent = null; eventManager.PublishAsyncFunc = t => { operationEvent = t as StoreOperationCompletedEvent; return(Task.FromResult(0)); }; MobileServiceTableQueryDescription query = new MobileServiceTableQueryDescription("test"); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode("123")); await changeTracker.DeleteAsync(query); Assert.IsNotNull(operationEvent); Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete); Assert.AreEqual(operationEvent.Operation.RecordId, "123"); Assert.AreEqual(operationEvent.Operation.TableName, "test"); }
public async virtual Task <MobileServiceTableOperation> PeekAsync(long prevSequenceId, MobileServiceTableKind tableKind, IEnumerable <string> tableNames) { MobileServiceTableQueryDescription query = CreateQuery(); var tableKindNode = Compare(BinaryOperatorKind.Equal, "tableKind", (int)tableKind); var sequenceNode = Compare(BinaryOperatorKind.GreaterThan, "sequence", prevSequenceId); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.And, tableKindNode, sequenceNode); if (tableNames != null && tableNames.Any()) { BinaryOperatorNode nameInList = tableNames.Select(t => Compare(BinaryOperatorKind.Equal, "tableName", t)) .Aggregate((first, second) => new BinaryOperatorNode(BinaryOperatorKind.Or, first, second)); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.And, query.Filter, nameInList); } query.Ordering.Add(new OrderByNode(new MemberAccessNode(null, "sequence"), OrderByDirection.Ascending)); query.Top = 1; JObject op = await this.store.FirstOrDefault(query); if (op == null) { return(null); } return(MobileServiceTableOperation.Deserialize(op)); }
public async Task DoesNotSaveTheMaxUpdatedAt_IfThereAreNoResults() { var query = new MobileServiceTableQueryDescription("test"); var result = new JArray(); string expectedOdata = "$filter=(updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00')&$orderby=updatedAt&$skip=0&$top=50"; await TestIncrementalSync(query, result, DateTime.MinValue, savesMax: false, firstQuery: expectedOdata, secondQuery: null); }
/// <summary> /// Deletes items from local table that match the given query. /// </summary> /// <param name="query">A query to find records to delete.</param> /// <returns>A task that completes when delete query has executed.</returns> /// <exception cref="ArgumentNullException">You must supply a query value</exception> public override Task DeleteAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } this.EnsureInitialized(); var formatter = new SqlQueryFormatter(query); string sql = formatter.FormatDelete(); return(this.operationSemaphore.WaitAsync() .ContinueWith(t => { try { this.ExecuteNonQueryInternal(sql, formatter.Parameters); } finally { this.operationSemaphore.Release(); } })); }
public async Task ReadAsync_ReadsItems() { await PrepareTodoTable(); // insert rows and make sure they are inserted TestUtilities.ExecuteNonQuery(TestDbName, "INSERT INTO todo (id, __createdAt) VALUES ('abc', 1), ('def', 2), ('ghi', 3)"); long count = TestUtilities.CountRows(TestDbName, TestTable); Assert.AreEqual(count, 3L); using (var store = new MobileServiceSQLiteStore(TestDbName)) { DefineTestTable(store); await store.InitializeAsync(); var query = MobileServiceTableQueryDescription.Parse(TestTable, "$filter=__createdAt gt 1&$inlinecount=allpages"); JToken item = await store.ReadAsync(query); Assert.IsNotNull(item); var results = item["results"].Value <JArray>(); long resultCount = item["count"].Value <long>(); Assert.AreEqual(results.Count, 2); Assert.AreEqual(resultCount, 2L); } }
public virtual async Task <long> CountPending(string tableName) { MobileServiceTableQueryDescription query = CreateQuery(); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, "tableName"), new ConstantNode(tableName)); return(await this.store.CountAsync(query)); }
/// <summary> /// Reads data from local store by executing the query. /// </summary> /// <param name="query">The query to execute on local store.</param> /// <returns>A task that will return with results when the query finishes.</returns> public override Task <JToken> ReadAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } this.EnsureInitialized(); var formatter = new SqlQueryFormatter(query); string sql = formatter.FormatSelect(); IList <JObject> rows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters); JToken result = new JArray(rows.ToArray()); if (query.IncludeTotalCount) { sql = formatter.FormatSelectCount(); IList <JObject> countRows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters); long count = countRows[0].Value <long>("count"); result = new JObject() { { "results", result }, { "count", count } }; } return(Task.FromResult(result)); }
private async Task TestIncrementalSync(MobileServiceTableQueryDescription query, JArray result, DateTime maxUpdatedAt, bool savesMax, string firstQuery, string secondQuery) { var action = new PullAction(this.table.Object, MobileServiceTableKind.Table, this.context.Object, "latestItems", query, null, null, this.opQueue.Object, this.settings.Object, this.store.Object, MobileServiceRemoteTableOptions.All, null, CancellationToken.None); this.opQueue.Setup(q => q.LockTableAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <IDisposable>(null)); this.opQueue.Setup(q => q.CountPending(It.IsAny <string>())).Returns(Task.FromResult(0L)); this.table.Setup(t => t.ReadAsync(firstQuery, It.IsAny <IDictionary <string, string> >(), It.IsAny <MobileServiceFeatures>())) .Returns(Task.FromResult(QueryResult.Parse(result, null, false))); if (result.Any()) { this.table.Setup(t => t.ReadAsync(secondQuery, It.IsAny <IDictionary <string, string> >(), It.IsAny <MobileServiceFeatures>())) .Returns(Task.FromResult(QueryResult.Parse(new JArray(), null, false))); } if (result.Any()) { this.store.Setup(s => s.UpsertAsync("test", It.IsAny <IEnumerable <JObject> >(), true)).Returns(Task.FromResult(0)); } this.settings.Setup(s => s.GetDeltaTokenAsync("test", "latestItems")).Returns(Task.FromResult(new DateTimeOffset(2013, 1, 1, 0, 0, 0, TimeSpan.Zero))); if (savesMax) { this.settings.Setup(s => s.SetDeltaTokenAsync("test", "latestItems", maxUpdatedAt)).Returns(Task.FromResult(0)); } await action.ExecuteAsync(); this.store.VerifyAll(); this.opQueue.VerifyAll(); this.table.VerifyAll(); this.settings.VerifyAll(); store.Verify(s => s.DeleteAsync("test", It.IsAny <IEnumerable <string> >()), Times.Never(), "There shouldn't be any call to delete"); }
public async Task DeleteAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } string[] recordIds = null; if (!query.TableName.StartsWith(MobileServiceLocalSystemTables.Prefix) && this.trackingContext.Source != StoreOperationSource.LocalPurge) { QueryResult result = await this.store.QueryAsync(query); recordIds = result.Values.Select(j => this.objectReader.GetId((JObject)j)).ToArray(); } await this.store.DeleteAsync(query); if (recordIds != null) { foreach (var id in recordIds) { TrackStoreOperation(query.TableName, id, LocalStoreOperationKind.Delete); } } }
public void ToODataString_EscapesThe_Uri() { //updatedat gt datetimeoffset'2014-04-04T07:00:00.0000000+00:00' var datetime1 = new ConstantNode(new DateTimeOffset(2014, 4, 4, 7, 0, 0, TimeSpan.FromHours(0))); var updatedAt = new MemberAccessNode(null, "updatedat"); var gt1 = new BinaryOperatorNode(BinaryOperatorKind.GreaterThan, updatedAt, datetime1); // updatedat gt datetime'2014-04-04T07:0:0.000Z' var datetime2 = new ConstantNode(new DateTime(2014, 4, 4, 7, 0, 0, DateTimeKind.Utc)); var someDate = new MemberAccessNode(null, "someDate"); var gt2 = new BinaryOperatorNode(BinaryOperatorKind.GreaterThan, someDate, datetime2); // startswith(text,'this&''%%=,?#') var text = new MemberAccessNode(null, "text"); var value = new ConstantNode("this&'%%=,?#"); var startswith = new FunctionCallNode("startswith", new QueryNode[] { text, value }); //updatedat gt datetimeoffset'2014-04-04T07:00:00.0000000+00:00' and startswith(text,'this&''%%=,?#') var and2 = new BinaryOperatorNode(BinaryOperatorKind.And, gt2, startswith); var and1 = new BinaryOperatorNode(BinaryOperatorKind.And, gt1, and2); var desc = new MobileServiceTableQueryDescription("someTable") { Filter = and1 }; Assert.AreEqual(desc.ToODataString(), EscapedODataString); }
public void Projection() { // Query syntax MobileServiceTableQueryDescription odata = Compile <Product, string>(table => from p in table select p.Name); Assert.AreEqual(1, odata.Selection.Count); Assert.AreEqual("Name", odata.Selection[0]); Assert.AreEqual(typeof(Product), odata.ProjectionArgumentType); Assert.AreEqual( "ZUMO", odata.Projection.DynamicInvoke( new Product { Name = "ZUMO", Price = 0, InStock = true })); // Chaining odata = Compile <Product, string>(table => table.Select(p => p.Name)); Assert.AreEqual(1, odata.Selection.Count); Assert.AreEqual("Name", odata.Selection[0]); Assert.AreEqual(typeof(Product), odata.ProjectionArgumentType); Assert.AreEqual( "ZUMO", odata.Projection.DynamicInvoke( new Product { Name = "ZUMO", Price = 0, InStock = true })); // Verify that we don't blow up by trying to include the Foo // property in the compiled query Compile((IMobileServiceTable <Product> table) => from p in table select new { Foo = p.Name }); }
public async Task DoesNotUpsertAnObject_IfItDoesNotHaveAnId() { var query = new MobileServiceTableQueryDescription("test"); var action = new PullAction(this.table.Object, MobileServiceTableKind.Table, this.context.Object, null, query, null, null, this.opQueue.Object, this.settings.Object, this.store.Object, MobileServiceRemoteTableOptions.All, pullOptions: null, reader: null, cancellationToken: CancellationToken.None); var itemWithId = new JObject() { { "id", "abc" }, { "text", "has id" } }; var itemWithoutId = new JObject() { { "text", "no id" } }; var result = new JArray(new[]{ itemWithId, itemWithoutId }); this.opQueue.Setup(q => q.LockTableAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<IDisposable>(null)); this.opQueue.Setup(q => q.CountPending(It.IsAny<string>())).Returns(Task.FromResult(0L)); this.table.SetupSequence(t => t.ReadAsync(It.IsAny<string>(), It.IsAny<IDictionary<string, string>>(), It.IsAny<MobileServiceFeatures>())) .Returns(Task.FromResult(QueryResult.Parse(result, null, false))) .Returns(Task.FromResult(QueryResult.Parse(new JArray(), null, false))); this.store.Setup(s => s.UpsertAsync("test", It.IsAny<IEnumerable<JObject>>(), true)) .Returns(Task.FromResult(0)) .Callback<string, IEnumerable<JObject>, bool>((tableName, items, fromServer) => { Assert.AreEqual(1, items.Count()); Assert.AreEqual(itemWithId, items.First()); }); await action.ExecuteAsync(); store.VerifyAll(); opQueue.VerifyAll(); table.VerifyAll(); store.Verify(s => s.DeleteAsync("test", It.IsAny<IEnumerable<string>>()), Times.Never(), "There shouldn't be any call to delete"); }
public void Bug466610UsingShorts() { MobileServiceTableQueryDescription query = Compile <Product, Product>(table => table.Where(p => p.DisplayAisle == 2)); Assert.AreEqual(query.Filter, "(DisplayAisle eq 2)"); query = Compile <Product, Product>(table => from p in table where p.DisplayAisle == (short)3 select p); Assert.AreEqual(query.Filter, "(DisplayAisle eq 3)"); short closedOverVariable = (short)5; query = Compile <Product, Product>(table => from p in table where p.DisplayAisle == closedOverVariable select p); Assert.AreEqual(query.Filter, "(DisplayAisle eq 5)"); query = Compile <Product, Product>(table => table.Where(p => p.OptionFlags == 7)); Assert.AreEqual(query.Filter, "(OptionFlags eq 7)"); // Verify non-numeric conversions still aren't supported object aisle = 12.0; Throws <NotSupportedException>(() => Compile <Product, Product>(table => from p in table where (object)p.DisplayAisle == aisle select p)); }
private static async Task <T> Query <T>(string query) where T : JToken { using (MobileServiceSQLiteStore store = await SetupTestTable()) { return((T)await store.ReadAsync(MobileServiceTableQueryDescription.Parse(TestTable, query))); } }
protected async override Task <bool> HandleDirtyTable() { if (this.Query.Filter != null || !this.force) { throw new InvalidOperationException("The table cannot be purged because it has pending operations."); } var delOperationsQuery = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.OperationQueue); delOperationsQuery.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, "tableName"), new ConstantNode(this.Table.TableName)); // count ops to be deleted delOperationsQuery.IncludeTotalCount = true; delOperationsQuery.Top = 0; long toRemove = QueryResult.Parse(await this.Store.ReadAsync(delOperationsQuery), null, validate: false).TotalCount; // delete operations delOperationsQuery.Top = null; await this.Store.DeleteAsync(delOperationsQuery); // delete errors var delErrorsQuery = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.SyncErrors); delErrorsQuery.Filter = delOperationsQuery.Filter; await this.Store.DeleteAsync(delErrorsQuery); // update queue operation count this.OperationQueue.UpdateOperationCount(-toRemove); return(true); }
private async Task Delete(MobileServiceTableQueryDescription query) { await this.store.DeleteAsync(query); OperationsInfo operationsInfo = this.operationsInfo.Value; Interlocked.Decrement(ref operationsInfo.Count); }
public async Task <IEnumerable <MobileServiceFileMetadata> > GetMetadataAsync(string tableName, string objectId) { var query = MobileServiceTableQueryDescription.Parse(FileMetadataTableName, string.Format("$filter=parentDataItemType eq '{0}' and parentDataItemId eq '{1}'", tableName, objectId)); var result = await this.store.ReadAsync(query); return(result.ToObject <List <MobileServiceFileMetadata> >()); }
public void FormatSelect_InvalidQuery() { string odata = "$filter=(2 ! ??)"; var ex = Assert.Throws <MobileServiceODataException>(() => MobileServiceTableQueryDescription.Parse("test", odata)); Assert.Equal("The specified odata query has syntax errors.", ex.Message); Assert.Equal(3, ex.ErrorPosition); }
public PullStrategy(MobileServiceTableQueryDescription query, PullCursor cursor, MobileServiceRemoteTableOptions options) { this.Query = query; this.Cursor = cursor; this.SupportsSkip = options.HasFlag(MobileServiceRemoteTableOptions.Skip); this.SupportsTop = options.HasFlag(MobileServiceRemoteTableOptions.Top); }
public async Task RemoveAsync(string id) { var query = new MobileServiceTableQueryDescription(FileOperationTableName); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode(id)); query.Top = 1; await Delete(query); }
public Task <JToken> ReadAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } return(this.store.ReadAsync(query)); }
public void Ordering() { // Query syntax MobileServiceTableQueryDescription odata = Compile <Product, Product>(table => from p in table orderby p.Price ascending select p); Assert.AreEqual(1, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsTrue(odata.Ordering[0].Value); // Chaining odata = Compile <Product, Product>(table => table.OrderBy(p => p.Price)); Assert.AreEqual(1, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsTrue(odata.Ordering[0].Value); // Query syntax descending odata = Compile <Product, Product>(table => from p in table orderby p.Price descending select p); Assert.AreEqual(1, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsFalse(odata.Ordering[0].Value); // Chaining descending odata = Compile <Product, Product>(table => table.OrderByDescending(p => p.Price)); Assert.AreEqual(1, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsFalse(odata.Ordering[0].Value); // Query syntax with multiple odata = Compile <Product, Product>(table => from p in table orderby p.Price ascending orderby p.Name descending select p); Assert.AreEqual(2, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsTrue(odata.Ordering[0].Value); Assert.AreEqual("Name", odata.Ordering[1].Key); Assert.IsFalse(odata.Ordering[1].Value); // Chaining with multiple odata = Compile <Product, Product>(table => table .OrderBy(p => p.Price) .OrderByDescending(p => p.Name)); Assert.AreEqual(2, odata.Ordering.Count); Assert.AreEqual("Price", odata.Ordering[0].Key); Assert.IsTrue(odata.Ordering[0].Value); Assert.AreEqual("Name", odata.Ordering[1].Key); Assert.IsFalse(odata.Ordering[1].Value); }
private static MobileServiceTableQueryDescription Compile <T, U>(Func <IMobileServiceTable <T>, MobileServiceTableQuery <U> > getQuery) { MobileServiceClient service = new MobileServiceClient("http://www.test.com"); IMobileServiceTable <T> table = service.GetTable <T>(); MobileServiceTableQuery <U> query = getQuery(table); MobileServiceTableQueryDescription odata = query.Compile(); App.Harness.Log(">>> " + odata.ToString()); return(odata); }
public override async Task DeleteAsync(MobileServiceTableQueryDescription query) { // ignore operations on system tables as we are in readthru mode if (IsSystemTable(query.TableName)) { return; } await this.store.DeleteAsync(query); }
public async Task PurgeAsync(string tableName, MobileServiceTableKind tableKind, string queryId, string query, bool force, CancellationToken cancellationToken) { await this.EnsureInitializedAsync(); var table = await this.GetTable(tableName); var queryDescription = MobileServiceTableQueryDescription.Parse(tableName, query); var action = new PurgeAction(table, tableKind, queryId, queryDescription, force, this, this.opQueue, this.settings, this.Store, cancellationToken); await this.ExecuteSyncAction(action); }
public async Task <JToken> ReadAsync(string tableName, string query) { await this.EnsureInitializedAsync(); var queryDescription = MobileServiceTableQueryDescription.Parse(tableName, query); using (await this.storeQueueLock.ReaderLockAsync()) { return(await this.Store.ReadAsync(queryDescription)); } }
public async Task <List <Patient> > GetItemsAsync() { var query = new MobileServiceTableQueryDescription("Patient"); JToken jtoken = await database.ReadAsync(query); ObservableCollection <Patient> patientlist = new ObservableCollection <Patient>(); var converted_result = jtoken.Select(x => JsonConvert.DeserializeObject <Patient>(x.ToString())); return(converted_result.ToList()); }
public async Task <MobileServiceTableOperation> GetOperationByItemIdAsync(string tableName, string itemId) { MobileServiceTableQueryDescription query = CreateQuery(); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.And, Compare(BinaryOperatorKind.Equal, "tableName", tableName), Compare(BinaryOperatorKind.Equal, "itemId", itemId)); JObject op = await this.store.FirstOrDefault(query); return(MobileServiceTableOperation.Deserialize(op)); }
public void BasicQuery() { // Query syntax MobileServiceTableQueryDescription odata = Compile <Product, Product>(table => from p in table select p); Assert.AreEqual("Product", odata.TableName); Assert.IsNull(odata.Filter); Assert.AreEqual(0, odata.Selection.Count); Assert.AreEqual(0, odata.Ordering.Count); }
public async Task DoesNotSaveTheMaxUpdatedAt_IfResultsHaveOlderUpdatedAt() { var query = new MobileServiceTableQueryDescription("test"); query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(4), new ConstantNode(3)); var result = new JArray(new[] { new JObject() { { "id", "abc" }, { "text", "has id"}, { "updatedAt", "1985-07-17" } }, }); string firstQuery = "$filter=((4 eq 3) and (updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00'))&$orderby=updatedAt&$skip=0&$top=50"; string secondQuery = "$filter=((4 eq 3) and (updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00'))&$orderby=updatedAt&$skip=1&$top=50"; await TestIncrementalSync(query, result, new DateTime(2014, 07, 09), savesMax: false, firstQuery: firstQuery, secondQuery: secondQuery); }
public async Task DoesNotSaveTheMaxUpdatedAt_IfThereAreNoResults() { string testName = "test"; string queryName = "latestItems"; var store = new Mock <IMobileServiceLocalStore>(MockBehavior.Strict); var settings = new Mock <MobileServiceSyncSettingsManager>(MockBehavior.Strict); var opQueue = new Mock <OperationQueue>(MockBehavior.Strict, store.Object); var handler = new Mock <IMobileServiceSyncHandler>(MockBehavior.Strict); var client = new Mock <MobileServiceClient>(); client.Object.Serializer = new MobileServiceSerializer(); var context = new Mock <MobileServiceSyncContext>(client.Object); var table = new Mock <MobileServiceTable <ToDoWithSystemPropertiesType> >(testName, client.Object); var query = new MobileServiceTableQueryDescription(testName); var result = new JArray(); string firstQuery = "$filter=(updatedAt ge 2013-01-01T00%3A00%3A00.0000000%2B00%3A00)&$orderby=updatedAt&$skip=0&$top=50"; var action = new PullAction( table.Object, MobileServiceTableKind.Table, context.Object, queryName, query, null, null, opQueue.Object, settings.Object, store.Object, MobileServiceRemoteTableOptions.All, pullOptions: null, reader: null, cancellationToken: CancellationToken.None); opQueue .Setup(q => q.LockTableAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <IDisposable>(null)); opQueue .Setup(q => q.CountPending(It.IsAny <string>())) .Returns(Task.FromResult(0L)); table .Setup(t => t.ReadAsync(firstQuery, It.IsAny <IDictionary <string, string> >(), It.IsAny <MobileServiceFeatures>())) .Returns(Task.FromResult(QueryResult.Parse(result, null, false))); settings .Setup(s => s.GetDeltaTokenAsync(testName, queryName)) .Returns(Task.FromResult(new DateTimeOffset(2013, 1, 1, 0, 0, 0, TimeSpan.Zero))); await action.ExecuteAsync(); store.VerifyAll(); opQueue.VerifyAll(); table.VerifyAll(); settings.VerifyAll(); }
public override async Task<JToken> ReadAsync(MobileServiceTableQueryDescription query) { // first lookup in local store JToken result = await this.store.ReadAsync(query); JArray items = GetItems(result); // if local store does not have results if ((items == null || items.Count == 0) && !IsSystemTable(query.TableName)) { // then lookup the server result = await this.client.GetTable(query.TableName).ReadAsync(query.ToODataString()); items = GetItems(result); // insert the results in the local store await this.store.UpsertAsync(query.TableName, items.Cast<JObject>(), fromServer: true); } return result; }
/// <summary> /// Deletes items from local table that match the given query. /// </summary> /// <param name="query">A query to find records to delete.</param> /// <returns>A task that completes when delete query has executed.</returns> public override Task DeleteAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } this.EnsureInitialized(); var formatter = new SqlQueryFormatter(query); string sql = formatter.FormatDelete(); this.ExecuteNonQuery(sql, formatter.Parameters); return Task.FromResult(0); }
/// <summary> /// Reads data from local store by executing the query. /// </summary> /// <param name="query">The query to execute on local store.</param> /// <returns>A task that will return with results when the query finishes.</returns> public override Task<JToken> ReadAsync(MobileServiceTableQueryDescription query) { if (query == null) { throw new ArgumentNullException("query"); } this.EnsureInitialized(); var formatter = new SqlQueryFormatter(query); string sql = formatter.FormatSelect(); IList<JObject> rows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters); JToken result = new JArray(rows.ToArray()); if (query.IncludeTotalCount) { sql = formatter.FormatSelectCount(); IList<JObject> countRows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters); long count = countRows[0].Value<long>("count"); result = new JObject() { { "results", result }, { "count", count} }; } return Task.FromResult(result); }