Skip to content

Instantly share code, notes, and snippets.

@sakapon
Last active May 9, 2019 18:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sakapon/8614d8355c66914cd265 to your computer and use it in GitHub Desktop.
Save sakapon/8614d8355c66914cd265 to your computer and use it in GitHub Desktop.
ExpressionsSample / Azure Table
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.WindowsAzure.Storage.Table;
namespace ExpressionsConsole
{
public static class TableHelper
{
static readonly MethodInfo String_CompareTo = typeof(string).GetMethod("CompareTo", new[] { typeof(string) });
public static TableQuery<TElement> Select<TElement>(this TableQuery<TElement> query, Expression<Func<TElement, object>> selector)
{
if (query == null) throw new ArgumentNullException("query");
if (selector == null) throw new ArgumentNullException("selector");
var @new = selector.Body as NewExpression;
if (@new == null) throw new InvalidOperationException();
query.SelectColumns = @new.Constructor.GetParameters().Select(p => p.Name).ToArray();
return query;
}
public static TableQuery<TElement> Where<TElement>(this TableQuery<TElement> query, Expression<Func<TElement, bool>> predicate)
{
if (query == null) throw new ArgumentNullException("query");
if (predicate == null) throw new ArgumentNullException("predicate");
var binary = predicate.Body as BinaryExpression;
if (binary == null) throw new InvalidOperationException();
var filter = GenerateFilter(binary);
query.FilterString = string.IsNullOrWhiteSpace(query.FilterString) ? filter : TableQuery.CombineFilters(query.FilterString, TableOperators.And, filter);
return query;
}
static string GenerateFilter(BinaryExpression binary)
{
switch (binary.NodeType)
{
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
return CombineFilters(binary);
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
return (binary.Left is MethodCallExpression) ? GenerateFilterConditionForMethodCall(binary) : GenerateFilterCondition(binary);
default:
throw new InvalidOperationException();
}
}
static string CombineFilters(BinaryExpression binary)
{
var left = binary.Left as BinaryExpression;
if (left == null) throw new InvalidOperationException();
var right = binary.Right as BinaryExpression;
if (right == null) throw new InvalidOperationException();
var op = ToCombinationOperator(binary.NodeType);
return TableQuery.CombineFilters(GenerateFilter(left), op, GenerateFilter(right));
}
static string GenerateFilterCondition(BinaryExpression binary)
{
var left = binary.Left as MemberExpression;
if (left == null) throw new InvalidOperationException();
var op = ToComparisonOperator(binary.NodeType);
var rightValue = binary.Right.Invoke();
return
left.Type == typeof(byte[]) ? TableQuery.GenerateFilterConditionForBinary(left.Member.Name, op, (byte[])rightValue) :
left.Type == typeof(bool) ? TableQuery.GenerateFilterConditionForBool(left.Member.Name, op, (bool)rightValue) :
left.Type == typeof(DateTime) ? TableQuery.GenerateFilterConditionForDate(left.Member.Name, op, (DateTime)rightValue) :
left.Type == typeof(DateTimeOffset) ? TableQuery.GenerateFilterConditionForDate(left.Member.Name, op, (DateTimeOffset)rightValue) :
left.Type == typeof(double) ? TableQuery.GenerateFilterConditionForDouble(left.Member.Name, op, (double)rightValue) :
left.Type == typeof(Guid) ? TableQuery.GenerateFilterConditionForGuid(left.Member.Name, op, (Guid)rightValue) :
left.Type == typeof(int) ? TableQuery.GenerateFilterConditionForInt(left.Member.Name, op, (int)rightValue) :
left.Type == typeof(long) ? TableQuery.GenerateFilterConditionForLong(left.Member.Name, op, (long)rightValue) :
TableQuery.GenerateFilterCondition(left.Member.Name, op, rightValue.To<string>());
}
static string GenerateFilterConditionForMethodCall(BinaryExpression binary)
{
var methodCall = binary.Left as MethodCallExpression;
if (methodCall == null) throw new InvalidOperationException();
if (methodCall.Method != String_CompareTo) throw new InvalidOperationException();
var left = methodCall.Object as MemberExpression;
if (left == null) throw new InvalidOperationException();
var op = ToComparisonOperator(binary.NodeType);
var rightValue = methodCall.Arguments[0].Invoke();
return TableQuery.GenerateFilterCondition(left.Member.Name, op, rightValue.To<string>());
}
static string ToCombinationOperator(ExpressionType nodeType)
{
switch (nodeType)
{
case ExpressionType.AndAlso:
return TableOperators.And;
case ExpressionType.OrElse:
return TableOperators.Or;
default:
throw new InvalidOperationException();
}
}
static string ToComparisonOperator(ExpressionType nodeType)
{
switch (nodeType)
{
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
return (string)typeof(QueryComparisons).GetField(nodeType.ToString()).GetValue(null);
default:
throw new InvalidOperationException();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
namespace ExpressionsConsole
{
public static class TableTest
{
static readonly CloudTable PeopleTable;
static TableTest()
{
var accountString = ConfigurationManager.ConnectionStrings["StorageAccount"].ConnectionString;
var account = CloudStorageAccount.Parse(accountString);
var tableClient = account.CreateCloudTableClient();
PeopleTable = tableClient.GetTableReference("people");
}
public static void SelectTest()
{
var query = new TableQuery<Person>()
.Select(p => new { p.FirstName, p.Age });
var result = PeopleTable.ExecuteQuery(query).ToArray();
}
public static void WhereTest1()
{
// (PartitionKey eq '2015') and ((LastName ge 'W') or (Age lt 20))
var query = new TableQuery<Person>()
.Where(p => p.PartitionKey == "2015" && (p.LastName.CompareTo("W") >= 0 || p.Age < 20));
var result = PeopleTable.ExecuteQuery(query).ToArray();
}
public static void WhereTest2()
{
// (PartitionKey eq '2015') and ((LastName ge 'W') or (Age lt 20))
var query = new TableQuery<Person>()
.Where(p => p.PartitionKey == "2015")
.Where(p => p.LastName.CompareTo("W") >= 0 || p.Age < 20);
var result = PeopleTable.ExecuteQuery(query).ToArray();
}
public static void WhereSelectTest()
{
var query = new TableQuery<Person>()
.Where(p => p.PartitionKey == "2015")
.Where(p => p.LastName.CompareTo("W") >= 0 || p.Age < 20)
.Select(p => new { p.FirstName, p.Age });
var result = PeopleTable.ExecuteQuery(query).ToArray();
}
}
[DebuggerDisplay(@"\{{PartitionKey}/{RowKey}\}")]
public class Person : TableEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment