擴展MongoDB C# Driver的QueryBuilder
擴展MongoDB C# Driver的QueryBuilder
由於不想直接hardcode ClassA.MemberA.MemberB 這樣的字符串 ,寫了以下幾個類,用於以下常用的場景:
1. 表達式轉換成字符串函數: ExpToStr()
2. Collection函數:當有集合成員時,可以使用此類,將返回QueryCollection對象,這個類的代碼之後附上
3. CollectionAs函數:當使用了繼承,希望將基類轉換為子類並返回子類的QueryCollection
使用示例:
//獲得表達式的字符串形式
1. QueryEx.ExpToStr ((ClassA m)=> m.MemberA.MemberB.MemberC)
//集合.成員.字段
//PoppedSegments為集合,AssignedNetwork.Name為成員
//將返回PoppedSegments.AssignedNetwork.Name
2. QueryEx.Collection(x => x.PoppedSegments).Matches(p => p.AssignedNetwork.Name, bsonRegex),
//子類集合.成員.字段
//STPaymentTransaction為基類,STPaymentCompanyCredit為子類,Company字段在子類中
//將返回Payments.Company.Name
3. QueryEx.CollectionAs(x=>x.Payments).Matches(p=>p.Company.Name, bsonRegex)
//集合.集合.成員.字段
//Parcels為集合,STCustomPropertyRuntime為基類,STNumericPropertyRuntime為子類,CustomProps為STNumericPropertyRuntime中成員,Value為CustomProp中成員
//將返回Parcels.CustomProps.Value
4. QueryEx.Collection(x=>x.Parcels).CollectionMemberAs(p=>p.CustomProps).Matches(p=>p.Value, bsonRegex),
實現代碼:
public class QueryEx
{
public static QueryCollection Collection(
Expression(
Expression));
var exp = Expression.Lambda
/// return string value for a expression:
/// for s.Name.Val1.Val2 will return Name.Val1.Val2
///
///
///
///
///
public static string ExpToStr(Expression Member(Expression> exp)
{
var expStr = QueryEx.ExpToStr(exp);
var context = string.Format({0}.{1}, _collectionName, expStr);
var obj = new QueryMember(context);
return obj;
}
public QueryCollection CollectionMember(
Expression>> exp)
{
var expStr = QueryEx.ExpToStr(exp);
var obj = new QueryCollection(exp)
{
_collectionName = string.Format({0}.{1}, _collectionName, expStr)
};
return obj;
}
///
/// this method only support 1 layer nested(not for Query Collection.Collection , but for Collection.Member)
/// if member is collection and need convert to sub class
///
/// Base Type
/// Child Class Type
///
///
public QueryCollection CollectionMemberAs(
Expression>> collectionExpression)
where TMemberSub : TMember
{
var obj = QueryEx.CollectionAs(collectionExpression);
obj._collectionName = string.Format({0}.{1}, _collectionName, obj._collectionName);
return obj;
}
public IMongoQuery LT(Expression> memberExpression, TMember value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.LT(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery LT(Expression>> memberExpression, TValue value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.LT(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery EQ(Expression> memberExpression, TMember value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.EQ(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery EQ(Expression>> memberExpression, TValue value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.EQ(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery NE(Expression> memberExpression, TMember value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.NE(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery NE(Expression>> memberExpression, TValue value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.NE(string.Format({0}.{1}, _collectionName, memberName), BsonValue.Create(value));
}
public IMongoQuery In(Expression> memberExpression, params TMember[] values)
{
return In(memberExpression, new List(values));
}
public IMongoQuery In(Expression> memberExpression,
IEnumerable values)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.In(string.Format({0}.{1}, _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
}
public IMongoQuery In(Expression> memberExpression,
IEnumerable values) where TCastC : TCollection
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.In(string.Format({0}.{1}, _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
}
public IMongoQuery In(Expression>> memberExpression, IEnumerable values)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.In(string.Format({0}.{1}, _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
}
public IMongoQuery In(Expression>> memberExpression, IEnumerable values) where TCastC : TCollection
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.In(string.Format({0}.{1}, _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
}
public IMongoQuery Matches(Expression> memberExpression, BsonRegularExpression value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.Matches(string.Format({0}.{1}, _collectionName, memberName), value);
}
public IMongoQuery Matches(Expression>> memberExpression, BsonRegularExpression value)
{
var memberName = _queryExpression.MemberExpression(memberExpression);
return Query.Matches(string.Format({0}.{1}, _collectionName, memberName), value);
}
}
public class QueryMember
{
private readonly QueryExpressionHelper _queryExpression;
private string _collectionName;
public string Context
{
get { return _collectionName; }
}
public QueryMember(Expression(Expression expression)
{
MemberExpression me;
switch (expression.Body.NodeType)
{
case ExpressionType.MemberAccess:
me = expression.Body as MemberExpression;
break;
case ExpressionType.Convert:
dynamic convertedBody = expression.Body;
me = convertedBody.Operand as MemberExpression;
break;
default:
throw new NotSupportedException(string.Format(Member with node type {0} is not supported. expression {1}, expression.Body.NodeType, expression));
}
var stack = new Stack();
while (me != null)
{
stack.Push(me.Member.Name);
me = me.Expression as MemberExpression;
}
var expStr = string.Join(., stack.ToArray());
return expStr;
}
}
public static class QueryMoney
{
public static IMongoQuery Value(string name, double val)
{
var accuracy = 0.005;
return Query.And(
Query.LT(name, new BsonDouble(val + accuracy)),
Query.GT(name, new BsonDouble(val - accuracy)));
}
}