public static TableOperation Retrieve <TElement>(string partitionKey, string rowkey) where TElement : ITableEntity { CommonUtility.AssertNotNull("partitionKey", partitionKey); CommonUtility.AssertNotNull("rowkey", rowkey); // Create and return the table operation. return(new TableOperation(null /* entity */, TableOperationType.Retrieve) { RetrievePartitionKey = partitionKey, RetrieveRowKey = rowkey, RetrieveResolver = (pk, rk, ts, prop, etag) => EntityUtilities.ResolveEntityByType <TElement>( pk, rk, ts, prop, etag) }); }
internal ExecutionInfo Bind() { ExecutionInfo retVal = new ExecutionInfo(); // IQueryable impl if (this.Expression != null) { Dictionary <Expression, Expression> normalizerRewrites = new Dictionary <Expression, Expression>(ReferenceEqualityComparer <Expression> .Instance); // Step 1. Evaluate any local evaluatable expressions ( lambdas etc) Expression partialEvaluatedExpression = Evaluator.PartialEval(this.Expression); // Step 2. Normalize expression, replace String Comparisons etc. Expression normalizedExpression = ExpressionNormalizer.Normalize(partialEvaluatedExpression, normalizerRewrites); // Step 3. Bind Expression, Analyze predicates and create query option expressions. End result is a single ResourceSetExpression Expression boundExpression = ResourceBinder.Bind(normalizedExpression); // Step 4. Parse the Bound expression into sub components, i.e. take count, filter, select columns, request options, opcontext, etc. ExpressionParser parser = new ExpressionParser(); parser.Translate(boundExpression); // Step 5. Store query components & params this.TakeCount = parser.TakeCount; this.FilterString = parser.FilterString; this.SelectColumns = parser.SelectColumns; retVal.RequestOptions = parser.RequestOptions; retVal.OperationContext = parser.OperationContext; // Step 6. If projection & no resolver then generate a resolver to perform the projection if (parser.Resolver == null) { if (parser.Projection != null && parser.Projection.Selector != ProjectionQueryOptionExpression.DefaultLambda) { Type intermediateType = parser.Projection.Selector.Parameters[0].Type; // Convert Expression to take type object as input to allow for direct invocation. ParameterExpression paramExpr = Expression.Parameter(typeof(object)); Func <object, TElement> projectorFunc = Expression.Lambda <Func <object, TElement> >( Expression.Invoke(parser.Projection.Selector, Expression.Convert(paramExpr, intermediateType)), paramExpr).Compile(); // Generate a resolver to do the projection. retVal.Resolver = (pk, rk, ts, props, etag) => { // Parse to intermediate type ITableEntity intermediateObject = (ITableEntity)EntityUtilities.InstantiateEntityFromType(intermediateType); intermediateObject.PartitionKey = pk; intermediateObject.RowKey = rk; intermediateObject.Timestamp = ts; intermediateObject.ReadEntity(props, parser.OperationContext); intermediateObject.ETag = etag; // Invoke lambda expression return(projectorFunc(intermediateObject)); }; } else { // No op - No resolver or projection specified. } } else { retVal.Resolver = (EntityResolver <TElement>)parser.Resolver.Value; } } retVal.RequestOptions = TableRequestOptions.ApplyDefaults(retVal.RequestOptions, this.queryProvider.Table.ServiceClient); retVal.OperationContext = retVal.OperationContext ?? new OperationContext(); return(retVal); }
/// <summary> /// Adds a table operation that retrieves an entity with the specified partition key and row key to the batch operation. The entity will be deserialized into the specified class type which extends <see cref="ITableEntity"/>. /// </summary> /// <typeparam name="TElement">The class of type for the entity to retrieve.</typeparam> /// <param name="batch">The input <see cref="TableBatchOperation"/>, which acts as the <c>this</c> instance for the extension method.</param> /// <param name="partitionKey">A string containing the partition key of the entity to be retrieved.</param> /// <param name="rowkey">A string containing the row key of the entity to be retrieved.</param> /// <param name="selectedColumns">List of column names for projection.</param> public void Retrieve <TElement>(string partitionKey, string rowkey, List <string> selectedColumns = null) where TElement : ITableEntity { CommonUtility.AssertNotNull("partitionKey", partitionKey); CommonUtility.AssertNotNull("rowkey", rowkey); // Add the table operation. this.Add(new TableOperation(null /* entity */, TableOperationType.Retrieve) { RetrievePartitionKey = partitionKey, RetrieveRowKey = rowkey, SelectColumns = selectedColumns, RetrieveResolver = (pk, rk, ts, prop, etag) => EntityUtilities.ResolveEntityByType <TElement>(pk, rk, ts, prop, etag) }); }
/// <summary> /// Adds a table operation that retrieves an entity with the specified partition key and row key to the batch operation. The entity will be de-serialized into the specified class type which extends <see cref="ITableEntity"/>. /// </summary> /// <typeparam name="TElement">The class of type for the entity to retrieve.</typeparam> /// <param name="batch">The input <see cref="TableBatchOperation"/>, which acts as the <c>this</c> instance for the extension method.</param> /// <param name="partitionKey">A string containing the partition key of the entity to be retrieved.</param> /// <param name="rowkey">A string containing the row key of the entity to be retrieved.</param> public static void Retrieve <TElement>(this TableBatchOperation batch, string partitionKey, string rowkey) where TElement : ITableEntity { CommonUtils.AssertNotNull("partitionKey", partitionKey); CommonUtils.AssertNotNull("rowkey", rowkey); // Add the table operation. batch.Add(new TableOperation(null /* entity */, TableOperationType.Retrieve) { RetrievePartitionKey = partitionKey, RetrieveRowKey = rowkey, RetrieveResolver = (pk, rk, ts, prop, etag) => EntityUtilities.ResolveEntityByType <TElement>(pk, rk, ts, prop, etag) }); }