/// <summary> /// Get News with a LINQ expression. /// </summary> /// <param name="action"></param> /// <returns></returns> public async Task <IQueryResultEnumerable <News> > GetNewsAsync(System.Linq.Expressions.Expression <System.Func <BKNews.News, bool> > action, int skip, int take) { try { #if OFFLINE_SYNC_ENABLED if (syncItems) { await this.SyncAsync(); } #endif IMobileServiceTableQuery <News> query = NewsTable.Where(action).OrderByDescending(news => news.NewsDate).Skip(skip).Take(take); query = query.IncludeTotalCount(); IQueryResultEnumerable <News> items = (IQueryResultEnumerable <News>) await query.ToListAsync(); return(items); } catch (MobileServiceInvalidOperationException msioe) { Debug.WriteLine(@"Invalid sync operation: {0}", msioe.Message); } catch (Exception e) { Debug.WriteLine(@"Sync error: {0}", e.Message); } return(null); }
public async Task TotalCountBasics() { // Insert a few records IMobileServiceTable <ToDo> table = GetClient().GetTable <ToDo>(); ToDo first = new ToDo { Title = "ABC", Complete = false }; await table.InsertAsync(first); await table.InsertAsync(new ToDo { Title = "DEF", Complete = true }); await table.InsertAsync(new ToDo { Title = "GHI", Complete = false }); ITotalCountProvider countProvider = null; IMobileServiceTableQuery <ToDo> query = table.Where(t => t.Id >= first.Id); // Run a simple query and verify we get all 3 items, but the // TotalCount is not provided. List <ToDo> items = await query.ToListAsync(); countProvider = items as ITotalCountProvider; Assert.AreEqual(3, items.Count); Assert.IsNotNull(countProvider); Assert.AreEqual(-1L, countProvider.TotalCount); IEnumerable <ToDo> sequence = await query.ToEnumerableAsync(); countProvider = sequence as ITotalCountProvider; Assert.IsNotNull(countProvider); Assert.AreEqual(-1L, countProvider.TotalCount); // Now use IncludeTotalCount and make sure we get the expected // number of results query = query.IncludeTotalCount(); items = await query.ToListAsync(); countProvider = items as ITotalCountProvider; Assert.AreEqual(3, items.Count); Assert.IsNotNull(countProvider); Assert.AreEqual(3L, countProvider.TotalCount); sequence = await query.ToEnumerableAsync(); countProvider = sequence as ITotalCountProvider; Assert.IsNotNull(countProvider); Assert.AreEqual(3L, countProvider.TotalCount); // Verify that IncludeTotalCount is correctly propagated with // projections List <string> titles = await query.Select(t => t.Title).ToListAsync(); countProvider = titles as ITotalCountProvider; Assert.AreEqual(3, titles.Count); Assert.IsNotNull(countProvider); Assert.AreEqual(3L, countProvider.TotalCount); }
public async static Task <List <T> > LoadAllAsync <T>(this IMobileServiceTableQuery <T> table, int bufferSize = 1000) { var query = table.IncludeTotalCount(); var results = await query.ToEnumerableAsync(); long count = ((ITotalCountProvider)results).TotalCount; var updates = new List <T>(); if (results != null && count > 0) { while (updates.Count < count) { var next = await query.Skip(updates.Count).Take(bufferSize).ToListAsync(); updates.AddRange(next); } } return(updates); }
private async Task CreateQueryTest <MovieType, TExpectedException>( string name, Expression <Func <MovieType, bool> > whereClause, int?top = null, int?skip = null, OrderByClause[] orderBy = null, Expression <Func <MovieType, string> > selectExpression = null, bool?includeTotalCount = null, string odataExpression = null, bool useStringIdTable = false, Func <MovieType, bool> whereLambda = null) where MovieType : class, IMovie where TExpectedException : Exception { Log("### Executing {0}.", name); if (whereClause == null && whereLambda != null) { Assert.Fail("The argument 'whereLambda' is optional and can only be specified if 'whereClause' is also specified."); } try { var table = this.GetClient().GetTable <MovieType>(); IEnumerable <MovieType> readMovies = null; IEnumerable <string> readProjectedMovies = null; if (odataExpression == null) { IMobileServiceTableQuery <MovieType> query = null; IMobileServiceTableQuery <string> selectedQuery = null; if (whereClause != null) { query = table.Where(whereClause); } if (orderBy != null) { if (query == null) { query = table.Where(m => m.Duration == m.Duration); } query = ApplyOrdering(query, orderBy); } if (top.HasValue) { query = query == null?table.Take(top.Value) : query.Take(top.Value); } if (skip.HasValue) { query = query == null?table.Skip(skip.Value) : query.Skip(skip.Value); } if (selectExpression != null) { selectedQuery = query == null?table.Select(selectExpression) : query.Select(selectExpression); } if (includeTotalCount.HasValue) { query = query.IncludeTotalCount(); } if (selectedQuery == null) { // Both ways of querying should be equivalent, so using both with equal probability here. // TODO: Make it deterministic var tickCount = Environment.TickCount; if ((tickCount % 2) == 0) { Log("Querying using MobileServiceTableQuery<T>.ToEnumerableAsync"); readMovies = await query.ToEnumerableAsync(); } else { Log("Querying using IMobileServiceTable<T>.ReadAsync(MobileServiceTableQuery<U>)"); readMovies = await table.ReadAsync(query); } } else { readProjectedMovies = await selectedQuery.ToEnumerableAsync(); } } else { Log("Using the OData query directly"); JToken result = await table.ReadAsync(odataExpression); readMovies = result.ToObject <IEnumerable <MovieType> >(); } long actualTotalCount = -1; ITotalCountProvider totalCountProvider = (readMovies as ITotalCountProvider) ?? (readProjectedMovies as ITotalCountProvider); if (totalCountProvider != null) { actualTotalCount = totalCountProvider.TotalCount; } IEnumerable <MovieType> expectedData; if (useStringIdTable) { var movies = QueryTestData.TestMovies(); expectedData = new MovieType[movies.Length]; for (var i = 0; i < movies.Length; i++) { ((MovieType[])expectedData)[i] = (MovieType)(IMovie)movies[i]; } } else { expectedData = QueryTestData.TestIntIdMovies.Select(s => (MovieType)(IMovie)s); } // Due to a Xamarin.iOS bug, Expression.Compile() does not work for some expression trees, // in which case we allow the caller to provide a lambda directly and we use it instead of // compiling the expression tree. if (whereLambda != null) { expectedData = expectedData.Where(whereLambda); } else if (whereClause != null) { expectedData = expectedData.Where(whereClause.Compile()); } long expectedTotalCount = -1; if (includeTotalCount.HasValue && includeTotalCount.Value) { expectedTotalCount = expectedData.Count(); } if (orderBy != null) { expectedData = ApplyOrdering(expectedData, orderBy); } if (skip.HasValue) { expectedData = expectedData.Skip(skip.Value); } if (top.HasValue) { expectedData = expectedData.Take(top.Value); } if (includeTotalCount.HasValue) { if (expectedTotalCount != actualTotalCount) { Log("Total count was requested, but the returned value is incorrect: expected={0}, actual={1}", expectedTotalCount, actualTotalCount); Assert.Fail(""); return; } } List <string> errors = new List <string>(); bool expectedDataIsSameAsReadData; if (selectExpression != null) { string[] expectedProjectedData = expectedData.Select(selectExpression.Compile()).ToArray(); expectedDataIsSameAsReadData = Utilities.CompareArrays(expectedProjectedData, readProjectedMovies.ToArray(), errors); } else { expectedDataIsSameAsReadData = Utilities.CompareArrays(expectedData.ToArray(), readMovies.ToArray(), errors); } if (!expectedDataIsSameAsReadData) { foreach (var error in errors) { Log(error); } Log("Expected data is different"); Assert.Fail(""); return; } else { if (typeof(TExpectedException) == typeof(ExceptionTypeWhichWillNeverBeThrown)) { return; } else { Log("Error, test should have failed with {0}, but succeeded.", typeof(TExpectedException).FullName); Assert.Fail(""); return; } } } catch (TExpectedException ex) { Log("Caught expected exception - {0}: {1}", ex.GetType().FullName, ex.Message); return; } }
private static ZumoTest CreateQueryTest <TExpectedException>( string name, Expression <Func <Movie, bool> > whereClause, int?top = null, int?skip = null, OrderByClause[] orderBy = null, Expression <Func <Movie, string> > selectExpression = null, bool?includeTotalCount = null, string odataExpression = null) where TExpectedException : Exception { return(new ZumoTest(name, async delegate(ZumoTest test) { try { var table = ZumoTestGlobals.Instance.Client.GetTable <Movie>(); IEnumerable <Movie> readMovies = null; IEnumerable <string> readProjectedMovies = null; if (odataExpression == null) { IMobileServiceTableQuery <Movie> query = null; IMobileServiceTableQuery <string> selectedQuery = null; if (whereClause != null) { query = table.Where(whereClause); } if (orderBy != null) { if (query == null) { query = table.Where(m => m.Duration == m.Duration); } query = ApplyOrdering(query, orderBy); } if (top.HasValue) { query = query == null ? table.Take(top.Value) : query.Take(top.Value); } if (skip.HasValue) { query = query == null ? table.Skip(skip.Value) : query.Skip(skip.Value); } if (selectExpression != null) { selectedQuery = query == null ? table.Select(selectExpression) : query.Select(selectExpression); } if (includeTotalCount.HasValue) { query = query.IncludeTotalCount(); } if (selectedQuery == null) { // Both ways of querying should be equivalent, so using both with equal probability here. var tickCount = Environment.TickCount; if ((tickCount % 2) == 0) { test.AddLog("Querying using MobileServiceTableQuery<T>.ToEnumerableAsync"); readMovies = await query.ToEnumerableAsync(); } else { test.AddLog("Querying using IMobileServiceTable<T>.ReadAsync(MobileServiceTableQuery<U>)"); readMovies = await table.ReadAsync(query); } } else { readProjectedMovies = await selectedQuery.ToEnumerableAsync(); } } else { test.AddLog("Using the OData query directly"); JToken result = await table.ReadAsync(odataExpression); readMovies = result.ToObject <IEnumerable <Movie> >(); } long actualTotalCount = -1; ITotalCountProvider totalCountProvider = (readMovies as ITotalCountProvider) ?? (readProjectedMovies as ITotalCountProvider); if (totalCountProvider != null) { actualTotalCount = totalCountProvider.TotalCount; } IEnumerable <Movie> expectedData = ZumoQueryTestData.AllMovies; if (whereClause != null) { expectedData = expectedData.Where(whereClause.Compile()); } long expectedTotalCount = -1; if (includeTotalCount.HasValue && includeTotalCount.Value) { expectedTotalCount = expectedData.Count(); } if (orderBy != null) { expectedData = ApplyOrdering(expectedData, orderBy); } if (skip.HasValue) { expectedData = expectedData.Skip(skip.Value); } if (top.HasValue) { expectedData = expectedData.Take(top.Value); } if (includeTotalCount.HasValue) { if (expectedTotalCount != actualTotalCount) { test.AddLog("Total count was requested, but the returned value is incorrect: expected={0}, actual={1}", expectedTotalCount, actualTotalCount); return false; } } List <string> errors = new List <string>(); bool expectedDataIsSameAsReadData; if (selectExpression != null) { string[] expectedProjectedData = expectedData.Select(selectExpression.Compile()).ToArray(); expectedDataIsSameAsReadData = Util.CompareArrays(expectedProjectedData, readProjectedMovies.ToArray(), errors); } else { expectedDataIsSameAsReadData = Util.CompareArrays(expectedData.ToArray(), readMovies.ToArray(), errors); } if (!expectedDataIsSameAsReadData) { foreach (var error in errors) { test.AddLog(error); } test.AddLog("Expected data is different"); return false; } else { if (typeof(TExpectedException) == typeof(ExceptionTypeWhichWillNeverBeThrown)) { return true; } else { test.AddLog("Error, test should have failed with {0}, but succeeded.", typeof(TExpectedException).FullName); return false; } } } catch (TExpectedException ex) { test.AddLog("Caught expected exception - {0}: {1}", ex.GetType().FullName, ex.Message); return true; } })); }
private async Task CreateQueryTest <MovieType, TExpectedException>( string name, Expression <Func <MovieType, bool> > whereClause, int?top = null, int?skip = null, OrderByClause[] orderBy = null, Expression <Func <MovieType, string> > selectExpression = null, bool?includeTotalCount = null, string odataExpression = null, bool useStringIdTable = false, Func <MovieType, bool> whereLambda = null) where MovieType : class, IMovie where TExpectedException : Exception { Assert.False(whereClause == null && whereLambda != null); try { var table = this.GetClient().GetTable <MovieType>(); IEnumerable <MovieType> readMovies = null; IEnumerable <string> readProjectedMovies = null; if (odataExpression == null) { IMobileServiceTableQuery <MovieType> query = null; IMobileServiceTableQuery <string> selectedQuery = null; if (whereClause != null) { query = table.Where(whereClause); } if (orderBy != null) { if (query == null) { query = table.Where(m => m.Duration == m.Duration); } query = ApplyOrdering(query, orderBy); } if (top.HasValue) { query = query == null?table.Take(top.Value) : query.Take(top.Value); } if (skip.HasValue) { query = query == null?table.Skip(skip.Value) : query.Skip(skip.Value); } if (selectExpression != null) { selectedQuery = query == null?table.Select(selectExpression) : query.Select(selectExpression); } if (includeTotalCount.HasValue) { query = query.IncludeTotalCount(); } if (selectedQuery == null) { // Both ways of querying should be equivalent, so using both with equal probability here. // TODO: Make it deterministic var tickCount = Environment.TickCount; if ((tickCount % 2) == 0) { readMovies = await query.ToEnumerableAsync(); } else { readMovies = await table.ReadAsync(query); } } else { readProjectedMovies = await selectedQuery.ToEnumerableAsync(); } } else { JToken result = await table.ReadAsync(odataExpression); readMovies = result.ToObject <IEnumerable <MovieType> >(); } long actualTotalCount = -1; #pragma warning disable CS0618 // Type or member is obsolete ITotalCountProvider totalCountProvider = (readMovies as ITotalCountProvider) ?? (readProjectedMovies as ITotalCountProvider); #pragma warning restore CS0618 // Type or member is obsolete if (totalCountProvider != null) { actualTotalCount = totalCountProvider.TotalCount; } IEnumerable <MovieType> expectedData; if (useStringIdTable) { var movies = QueryTestData.TestMovies(); expectedData = new MovieType[movies.Length]; for (var i = 0; i < movies.Length; i++) { ((MovieType[])expectedData)[i] = (MovieType)(IMovie)movies[i]; } } else { expectedData = QueryTestData.TestIntIdMovies.Select(s => (MovieType)(IMovie)s); } // Due to a Xamarin.iOS bug, Expression.Compile() does not work for some expression trees, // in which case we allow the caller to provide a lambda directly and we use it instead of // compiling the expression tree. if (whereLambda != null) { expectedData = expectedData.Where(whereLambda); } else if (whereClause != null) { expectedData = expectedData.Where(whereClause.Compile()); } long expectedTotalCount = -1; if (includeTotalCount.HasValue && includeTotalCount.Value) { expectedTotalCount = expectedData.Count(); } if (orderBy != null) { expectedData = ApplyOrdering(expectedData, orderBy); } if (skip.HasValue) { expectedData = expectedData.Skip(skip.Value); } if (top.HasValue) { expectedData = expectedData.Take(top.Value); } if (includeTotalCount.HasValue) { Assert.Equal(expectedTotalCount, actualTotalCount); } List <string> errors = new List <string>(); bool expectedDataIsSameAsReadData; if (selectExpression != null) { string[] expectedProjectedData = expectedData.Select(selectExpression.Compile()).ToArray(); expectedDataIsSameAsReadData = Utilities.CompareArrays(expectedProjectedData, readProjectedMovies.ToArray(), errors); } else { expectedDataIsSameAsReadData = Utilities.CompareArrays(expectedData.ToArray(), readMovies.ToArray(), errors); } Assert.True(expectedDataIsSameAsReadData); if (typeof(TExpectedException) != typeof(ExceptionTypeWhichWillNeverBeThrown)) { Assert.True(false, "Test should have failed"); return; } } catch (TExpectedException) { return; } }