/// <summary> /// Executes an asynchronous query operation. /// </summary> /// <param name="query">The query to invoke.</param> /// <param name="callback">The callback to invoke when the query has been executed.</param> /// <param name="userState">Optional user state associated with this operation.</param> /// <returns>An asynchronous result that identifies this query.</returns> /// <remarks> /// Queries with side-effects may be invoked differently. For example, clients that invoke a DomainService /// over HTTP may use POST requests for queries with side-effects, while GET may be used otherwise. /// </remarks> public IAsyncResult BeginQuery(EntityQuery query, AsyncCallback callback, object userState) { if (query == null) { throw new ArgumentNullException("query"); } if (callback == null) { throw new ArgumentNullException("callback"); } DomainClientAsyncResult domainClientResult = DomainClientAsyncResult.CreateQueryResult(this, callback, userState); domainClientResult.InnerAsyncResult = this.BeginQueryCore( query, delegate(IAsyncResult result) { DomainClientAsyncResult clientResult = (DomainClientAsyncResult)result.AsyncState; clientResult.InnerAsyncResult = result; clientResult.Complete(); }, domainClientResult); return domainClientResult; }
public override LoadOperation Load(EntityQuery query, LoadBehavior loadBehavior, Action<LoadOperation> callback, object userState) { if (this._loadCallback != null) { this._loadCallback(query, loadBehavior, userState); } return base.Load(query, loadBehavior, callback, userState); }
public void TestQueryOperators_QueryComprehension() { // test where EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = from c in citiesQuery where c.CountyName == "Lucas" select c; List<ServiceQueryPart> parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("where", parts[0].QueryOperator); Assert.AreEqual("(it.CountyName==\"Lucas\")", parts[0].Expression); Assert.AreSame(typeof(City), citiesQuery.EntityType); // test orderby, thenby citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = from c in citiesQuery orderby c.Name, c.StateName select c; parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("orderby", parts[0].QueryOperator); Assert.AreEqual("it.Name, it.StateName", parts[0].Expression); // test orderby desc, thenby desc citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = from c in citiesQuery orderby c.Name descending, c.StateName descending select c; parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("orderby", parts[0].QueryOperator); Assert.AreEqual("it.Name desc, it.StateName desc", parts[0].Expression); // test skip and take citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = citiesQuery.Skip(20).Take(10); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(2, parts.Count); Assert.AreEqual("skip", parts[0].QueryOperator); Assert.AreEqual("20", parts[0].Expression); Assert.AreEqual("take", parts[1].QueryOperator); Assert.AreEqual("10", parts[1].Expression); // test all together citiesQuery = (from c in new EntityQuery<City>(_testClient, "GetCities", null, false, true) where c.CountyName == "Lucas" orderby c.Name descending, c.StateName descending select c ).Skip(20).Take(10); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(4, parts.Count); }
/// <summary> /// Initializes a new instance of the EntityQuery class based on an existing "base" /// query. The query is constructed with the same properties as the base query /// using the specified IQueryable as the new query. /// </summary> /// <param name="baseQuery">The existing query.</param> /// <param name="query">The new query.</param> internal EntityQuery(EntityQuery baseQuery, IQueryable query) { if (baseQuery == null) { throw new ArgumentNullException("baseQuery"); } if (query == null) { throw new ArgumentNullException("query"); } this._domainClient = baseQuery._domainClient; this._queryName = baseQuery._queryName; this._entityType = baseQuery._entityType; this._parameters = baseQuery._parameters; this._hasSideEffects = baseQuery._hasSideEffects; this._isComposable = baseQuery._isComposable; this._includeTotalCount = baseQuery._includeTotalCount; this._query = query; }
public void TestQueryOperators_QueryMethods() { // test where EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = citiesQuery.Where(c => c.CountyName == "Lucas"); List<ServiceQueryPart> parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("where", parts[0].QueryOperator); Assert.AreEqual("(it.CountyName==\"Lucas\")", parts[0].Expression); // test orderby, thenby citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = citiesQuery.OrderBy(c => c.Name).ThenBy(c => c.StateName); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("orderby", parts[0].QueryOperator); Assert.AreEqual("it.Name, it.StateName", parts[0].Expression); // test orderby desc, thenby desc citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = citiesQuery.OrderByDescending(c => c.Name).ThenByDescending(c => c.StateName); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(1, parts.Count); Assert.AreEqual("orderby", parts[0].QueryOperator); Assert.AreEqual("it.Name desc, it.StateName desc", parts[0].Expression); // test skip and take citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); citiesQuery = citiesQuery.Skip(20).Take(10); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(2, parts.Count); Assert.AreEqual("skip", parts[0].QueryOperator); Assert.AreEqual("20", parts[0].Expression); Assert.AreEqual("take", parts[1].QueryOperator); Assert.AreEqual("10", parts[1].Expression); // test all together citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true) .Where(c => c.CountyName == "Lucas") .OrderBy(c => c.Name).ThenBy(c => c.StateName) .Skip(20) .Take(10); parts = QuerySerializer.Serialize(citiesQuery.Query); Assert.AreEqual(4, parts.Count); }
protected override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState) { MockUser user = null; if (query.QueryName == "Login") { Assert.IsNotNull(query.Parameters, "Parameters should not be null."); Assert.IsTrue(query.Parameters.ContainsKey("UserName"), "Parameters should contain UserName."); Assert.IsTrue(query.Parameters.ContainsKey("Password"), "Parameters should contain Password."); Assert.IsTrue(query.Parameters.ContainsKey("IsPersistent"), "Parameters should contain IsPersistent."); if (AuthenticationDomainClient.ValidUserName == (string)query.Parameters["UserName"]) { user = new MockUser() { Type = UserType.LoggedIn, Name = "LoggedIn" }; } } else if (query.QueryName == "Logout") { Assert.IsTrue((query.Parameters == null) || (query.Parameters.Count == 0), "Logout operation is not expecting any parameters."); user = new MockUser() { Type = UserType.LoggedOut }; } else if (query.QueryName == "GetUser") { Assert.AreEqual("GetUser", query.QueryName, "Operation should be GetUser."); Assert.IsTrue((query.Parameters == null) || (query.Parameters.Count == 0), "GetUser operation is not expecting any parameters."); Assert.IsNull(query.Query, "GetUser operation is not expecting a query."); user = new MockUser() { Type = UserType.Loaded }; } else { Assert.Fail("Only Login, Logout, and GetUser methods are supported for queries."); } this.Result = new AdcAsyncResult(user, callback, userState); return this.Result; }
protected override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState) { return null; }
/// <summary> /// Modifies the provided EntityQuery to perform a Take operation. /// </summary> /// <param name="source">The EntityQuery to compose.</param> /// <param name="count">The number of items to take.</param> /// <returns>The composed EntityQuery.</returns> public static EntityQuery Take(EntityQuery source, int count) { Debug.Assert(source != null, "Unexpected null source"); MethodInfo take = GetEntityQueryMethod("Take"); MethodInfo takeT = take.MakeGenericMethod(source.EntityType); return (EntityQuery)takeT.Invoke(null, new object[] { source, count }); }
/// <summary> /// Modifies the provided EntityQuery to restrict the result set according to the <paramref name="filtersExpression"/> argument. /// </summary> /// <param name="source">EntityQuery to modify.</param> /// <param name="filtersExpression">Expression representing the filter to apply.</param> /// <returns>Composed EntityQuery</returns> public static EntityQuery Where(EntityQuery source, Expression filtersExpression) { Debug.Assert(source != null, "Unexpected null source"); Debug.Assert(filtersExpression != null, "Unexpected null filtersExpression"); MethodInfo where = GetEntityQueryMethod("Where"); MethodInfo whereT = where.MakeGenericMethod(source.EntityType); LambdaExpression lambda = Expression.Lambda(filtersExpression, new ParameterExpression[] { Expression.Parameter(source.EntityType, string.Empty) }); return (EntityQuery)whereT.Invoke(null, new object[] { source, lambda }); }
/// <summary> /// Compose an OrderBy, ThenBy, OrderByDescending, or ThenByDescending clause onto an EntityQuery. /// </summary> /// <param name="source">The source EntityQuery</param> /// <param name="orderMethodName">The order method name to use: OrderBy, ThenBy, OrderByDescending, or ThenByDescending.</param> /// <param name="sortExpression">The expression to use for sorting.</param> /// <returns>The composed EntityQuery.</returns> private static EntityQuery OrderBy(EntityQuery source, string orderMethodName, Expression sortExpression) { LambdaExpression lambda = Expression.Lambda(sortExpression, new ParameterExpression[] { Expression.Parameter(source.EntityType, string.Empty) }); MethodInfo orderBy = GetEntityQueryMethod(orderMethodName); MethodInfo orderByT = orderBy.MakeGenericMethod(source.EntityType, sortExpression.Type); return (EntityQuery)orderByT.Invoke(null, new object[] { source, lambda }); }
/// <summary> /// Modifies the provided EntityQuery to perform a Skip operation. /// </summary> /// <param name="source">The EntityQuery to compose.</param> /// <param name="count">The number of items to skip.</param> /// <returns>The composed EntityQuery.</returns> public static EntityQuery Skip(EntityQuery source, int count) { Debug.Assert(source != null, "Unexpected null source"); MethodInfo skip = GetEntityQueryMethod("Skip"); MethodInfo skipT = skip.MakeGenericMethod(source.EntityType); return (EntityQuery)skipT.Invoke(null, new object[] { source, count }); }
/// <summary> /// Method called by the framework to begin an asynchronous query operation /// </summary> /// <param name="query">The query to invoke.</param> /// <param name="callback">The callback to invoke when the query has been executed.</param> /// <param name="userState">Optional state associated with this operation.</param> /// <returns>An asynchronous result that identifies this query.</returns> /// <exception cref="InvalidOperationException">The specified query does not exist.</exception> protected sealed override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState) { MethodInfo beginQueryMethod = WebDomainClient <TContract> .ResolveBeginMethod(query.QueryName); MethodInfo endQueryMethod = WebDomainClient <TContract> .ResolveEndMethod(query.QueryName); // Pass query parameters. ParameterInfo[] parameterInfos = beginQueryMethod.GetParameters(); object[] realParameters = new object[parameterInfos.Length]; int parametersCount = (query.Parameters == null) ? 0 : query.Parameters.Count; for (int i = 0; i < parametersCount; i++) { realParameters[i] = query.Parameters[parameterInfos[i].Name]; } TContract channel = this.ChannelFactory.CreateChannel(); WebDomainClientAsyncResult <TContract> wcfAsyncResult = WebDomainClientAsyncResult <TContract> .CreateQueryResult(this, channel, endQueryMethod, callback, userState); // Pass async operation related parameters. realParameters[parameterInfos.Length - 2] = new AsyncCallback(delegate(IAsyncResult asyncResponseResult) { wcfAsyncResult.InnerAsyncResult = asyncResponseResult; wcfAsyncResult.Complete(); }); realParameters[parameterInfos.Length - 1] = userState; IAsyncResult asyncResult; try { // Pass the query as a message property. using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel)) { if (query.Query != null) { OperationContext.Current.OutgoingMessageProperties.Add(WebDomainClient <object> .QueryPropertyName, query.Query); } if (query.IncludeTotalCount) { OperationContext.Current.OutgoingMessageProperties.Add(WebDomainClient <object> .IncludeTotalCountPropertyName, true); } asyncResult = (IAsyncResult)beginQueryMethod.Invoke(channel, realParameters); } } catch (TargetInvocationException tie) { if (tie.InnerException != null) { throw tie.InnerException; } throw; } if (!asyncResult.CompletedSynchronously) { wcfAsyncResult.InnerAsyncResult = asyncResult; } return(wcfAsyncResult); }
/// <summary> /// Composes an <see cref="EntityQuery" /> for sorting and grouping purposes. /// </summary> /// <param name="source">The queryable source.</param> /// <param name="groupDescriptors">The group descriptors.</param> /// <param name="sortDescriptors">The sort descriptors.</param> /// <param name="expressionCache">Cache for storing built expressions</param> /// <returns>The composed <see cref="EntityQuery" />.</returns> public static EntityQuery OrderBy( EntityQuery source, GroupDescriptorCollection groupDescriptors, SortDescriptorCollection sortDescriptors, ExpressionCache expressionCache) { Debug.Assert(source != null, "Unexpected null source"); Debug.Assert(sortDescriptors != null, "Unexpected null sortDescriptors"); Debug.Assert(groupDescriptors != null, "Unexpected null groupDescriptors"); bool hasOrderBy = false; // check the GroupDescriptors first foreach (GroupDescriptor groupDescriptor in groupDescriptors) { if (groupDescriptor != null && groupDescriptor.PropertyPath != null) { Debug.Assert(expressionCache.ContainsKey(groupDescriptor), "There should be a cached group expression"); // check to see if we sort by the same parameter in desc order bool sortAsc = true; foreach (SortDescriptor sortDescriptor in sortDescriptors) { if (sortDescriptor != null) { string sortDescriptorPropertyPath = sortDescriptor.PropertyPath; string groupDescriptorPropertyPath = groupDescriptor.PropertyPath; if (sortDescriptorPropertyPath != null && sortDescriptorPropertyPath.Equals(groupDescriptorPropertyPath)) { if (sortDescriptor.Direction == ListSortDirection.Descending) { sortAsc = false; } break; } } } string orderMethodName = (!hasOrderBy ? "OrderBy" : "ThenBy"); if (!sortAsc) { orderMethodName += "Descending"; } source = OrderBy(source, orderMethodName, expressionCache[groupDescriptor]); hasOrderBy = true; } } // then check the SortDescriptors foreach (SortDescriptor sortDescriptor in sortDescriptors) { if (sortDescriptor != null) { Debug.Assert(expressionCache.ContainsKey(sortDescriptor), "There should be a cached sort expression"); string orderMethodName = (!hasOrderBy ? "OrderBy" : "ThenBy"); if (sortDescriptor.Direction == ListSortDirection.Descending) { orderMethodName += "Descending"; } source = OrderBy(source, orderMethodName, expressionCache[sortDescriptor]); hasOrderBy = true; } } return source; }
public void TestPropertyValues() { // Test Query property EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); Assert.IsNull(citiesQuery.Query); citiesQuery = citiesQuery.Where(p => p.StateName == "Ohio"); Assert.IsNotNull(citiesQuery.Query); // Test IsComposable property citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); Assert.AreEqual(true, citiesQuery.IsComposable); citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, false); Assert.AreEqual(false, citiesQuery.IsComposable); // Test Parameters property Dictionary<string, object> parameters = new Dictionary<string, object> { {"a", 1}, {"b", 2} }; citiesQuery = new EntityQuery<City>(_testClient, "GetCities", parameters, false, true); Assert.AreSame(parameters, citiesQuery.Parameters); citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); Assert.IsNull(citiesQuery.Parameters); // Test QueryName property citiesQuery = new EntityQuery<City>(_testClient, "GetCities", parameters, false, true); Assert.AreEqual("GetCities", citiesQuery.QueryName); }
/// <summary> /// Initializes a new instance of the <see cref="LoadingDataEventArgs"/> class. /// </summary> /// <param name="query">Default query that will be used for the load operation</param> /// <param name="loadBehavior">Default load behavior that will be used for the load operation</param> internal LoadingDataEventArgs(EntityQuery query, LoadBehavior loadBehavior) { this.Query = query; this.LoadBehavior = loadBehavior; this.RestoreLoadSettings = true; }
public void ParameterChecking() { Dictionary<string, object> parameters = new Dictionary<string, object> { {"a", 1}, {"b", 2} }; EntityQuery<City> baseQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, true); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, null, parameters, false, true); }, "queryName"); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, string.Empty, parameters, false, true); }, "queryName"); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(null, "GetCities", parameters, false, true); }, "domainClient"); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(null, new City[0].AsQueryable().Where(p => p.StateName == "Toledo")); }, "baseQuery"); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(baseQuery, null); }, "query"); ExceptionHelper.ExpectArgumentNullException(delegate { EntityQuery<City> citiesQuery = new EntityQuery<City>(baseQuery, null); }, "query"); }
public void NonComposableQuery() { EntityQuery<City> citiesQuery = new EntityQuery<City>(_testClient, "GetCities", null, false, false); IQueryable<City> queryable = new City[0].AsQueryable(); string expectedMessage = string.Format(Resource.EntityQuery_NotComposable, "City", "GetCities"); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.Where(p => p.StateName == "Toledo"); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.Skip(1); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.Take(1); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.OrderBy(p => p.CountyName); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.OrderByDescending(p => p.CountyName); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.ThenBy(p => p.CountyName); }, expectedMessage); ExceptionHelper.ExpectInvalidOperationException(delegate { citiesQuery.ThenByDescending(p => p.CountyName); }, expectedMessage); }
protected override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState) { // load test data and get query result IEnumerable<Entity> entities = GetQueryResult(query.QueryName, query.Parameters); if (query.Query != null) { entities = RebaseQuery(entities.AsQueryable(), query.Query).Cast<Entity>(); } MockAsyncResult ar = new MockAsyncResult(entities, userState, null); callback.Invoke(ar); return ar; }
public void TestMethodQueryMismatch() { WebDomainClient<TestDomainServices.LTS.Catalog.ICatalogContract> dc = new WebDomainClient<TestDomainServices.LTS.Catalog.ICatalogContract>(TestURIs.EF_Catalog) { EntityTypes = new Type[] { typeof(Product), typeof(PurchaseOrder), typeof(PurchaseOrderDetail) } }; QueryCompletedResult queryResults = null; var query = new EntityQuery<PurchaseOrder>(new EntityQuery<Product>(dc, "GetProducts", null, true, false), new PurchaseOrder[0].AsQueryable().Take(2)); query.IncludeTotalCount = true; dc.BeginQuery( query, delegate(IAsyncResult asyncResult) { queryResults = dc.EndQuery(asyncResult); }, null ); EnqueueConditional(() => queryResults != null); EnqueueCallback(delegate { Assert.AreEqual(2, queryResults.Entities.Concat(queryResults.IncludedEntities).Count()); Assert.AreEqual(504, queryResults.TotalCount); }); EnqueueTestComplete(); }
public void TestQuery() { QueryCompletedResult result = null; object userState = this; WebDomainClient<TestDomainServices.LTS.Catalog.ICatalogContract> dc = new WebDomainClient<TestDomainServices.LTS.Catalog.ICatalogContract>(TestURIs.LTS_Catalog) { EntityTypes = new Type[] { typeof(Product) } }; var query = from p in new Product[0].AsQueryable() where p.Weight < 10.5M orderby p.Weight select p; var entityQuery = new EntityQuery<Product>(new EntityQuery<Product>(dc, "GetProducts", null, true, false), query); entityQuery.IncludeTotalCount = true; dc.BeginQuery( entityQuery, delegate(IAsyncResult asyncResult) { result = dc.EndQuery(asyncResult); }, userState ); EnqueueConditional(delegate { return result != null; }); EnqueueCallback(delegate { Assert.AreEqual(79, result.Entities.Concat(result.IncludedEntities).Count()); Assert.AreEqual(result.Entities.Count(), result.TotalCount); }); EnqueueTestComplete(); }
/// <summary> /// Method called by the framework to begin the asynchronous query operation. /// </summary> /// <param name="query">The query to invoke.</param> /// <param name="callback">The callback to invoke when the query has been executed.</param> /// <param name="userState">Optional user state associated with this operation.</param> /// <returns>An asynchronous result that identifies this query.</returns> protected abstract IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState);