using Ant.Descriptors;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace Ant.ORM
{
///
/// 自定义查询
///
public static class Predicates
{
///
/// Factory method that creates a new IFieldPredicate predicate: [FieldName] [Operator] [Value].
/// Example: WHERE FirstName = 'Foo'
///
/// The type of the entity.
/// An expression that returns the left operand [FieldName].
/// The comparison operator.
/// The value for the predicate.
/// Effectively inverts the comparison operator. Example: WHERE FirstName <> 'Foo'.
/// An instance of IFieldPredicate.
public static IFieldPredicate QueryField(Expression> expression, Operator op, object value, bool not = false) where T : class
{
PropertyInfo propertyInfo = ReflectionHelper.GetProperty(expression) as PropertyInfo;
MetaData typeDesc = new MetaData();
typeDesc.FiledMeta = MetaDataManager.GetMetaData(typeof(T));
string strtable = typeof(T).Name;
return new FieldPredicate
{
TableName = typeDesc.FiledMeta.Table.Name,
PropertyName = propertyInfo.Name,
Operators = op,
Value = value,
Not = not
};
}
///
/// Factory method that creates a new IPropertyPredicate predicate: [FieldName1] [Operator] [FieldName2]
/// Example: WHERE FirstName = LastName
///
/// The type of the entity for the left operand.
/// The type of the entity for the right operand.
/// An expression that returns the left operand [FieldName1].
/// The comparison operator.
/// An expression that returns the right operand [FieldName2].
/// Effectively inverts the comparison operator. Example: WHERE FirstName <> LastName
/// An instance of IPropertyPredicate.
public static IPropertyPredicate Property(Expression> expression, Operator op, Expression> expression2, bool not = false)
where T : class
where T2 : class
{
PropertyInfo propertyInfo = ReflectionHelper.GetProperty(expression) as PropertyInfo;
PropertyInfo propertyInfo2 = ReflectionHelper.GetProperty(expression2) as PropertyInfo;
return new PropertyPredicate
{
PropertyName = propertyInfo.Name,
PropertyName2 = propertyInfo2.Name,
Operators = op,
Not = not
};
}
///
/// 工厂方法创建一个新的ipredicategroup谓词。
/// Factory method that creates a new IPredicateGroup predicate.
/// Predicate groups can be joined together with other predicate groups.
///
/// The grouping operator to use when joining the predicates (AND / OR).
/// A list of predicates to group.
/// An instance of IPredicateGroup.
public static IPredicateGroup SqlGroup(GroupOperator op, params IPredicate[] predicate)
{
return new PredicateGroup
{
Operator = op,
Predicates = predicate
};
}
///
/// 把查询条件进行设置分组
///
///
///
///
public static IPredicateGroup SqlGroup(GroupOperator op, List predicate)
{
return new PredicateGroup
{
Operator = op,
Predicates = predicate
};
}
///
/// Factory method that creates a new IExistsPredicate predicate.
///
public static IExistsPredicate Exists(IPredicate predicate, bool not = false)
where TSub : class
{
string strtable = typeof(TSub).Name;
return new ExistsPredicate
{
Not = not,
TableName = strtable,
Predicate = predicate
};
}
///
/// Factory method that creates a new IBetweenPredicate predicate.
///
public static IBetweenPredicate Between(Expression> expression, BetweenValues values, bool not = false)
where T : class
{
PropertyInfo propertyInfo = ReflectionHelper.GetProperty(expression) as PropertyInfo;
string strtable = typeof(T).Name;
return new BetweenPredicate
{
Not = not,
TableName = (strtable.ToLower().StartsWith("ent")) ? strtable.Substring(3) : strtable,
PropertyName = propertyInfo.Name,
Value = values
};
}
///
/// 工厂方法,创建一个新的排序,控制结果将如何排序
/// Factory method that creates a new Sort which controls how the results will be sorted.
///
public static ISort Sort(Expression> expression, bool ascending = true)
{
PropertyInfo propertyInfo = ReflectionHelper.GetProperty(expression) as PropertyInfo;
string strtable = typeof(T).Name;
return new Sort
{
TableName = (strtable.ToLower().StartsWith("ent")) ? strtable.Substring(3) : strtable,
PropertyName = propertyInfo.Name,
Ascending = ascending
};
}
}
///
/// 自定义查询接口
///
public interface IPredicate
{
string GetSql(FieldValueCollection filewhere, QueryCommand parameters);
}
public interface IBasePredicate : IPredicate
{
///
/// 表名
///
string TableName { get; set; }
///
/// 列名
///
string PropertyName { get; set; }
}
public abstract class BasePredicate : IBasePredicate
{
///
/// 获取SQL语句
///
///
///
///
public abstract string GetSql(FieldValueCollection md, QueryCommand parameters);
///
/// 列名
///
public string PropertyName { get; set; }
///
/// 表名
///
public string TableName { get; set; }
protected virtual string GetColumnName(Type entityType, string propertyName)
{
return "";
//if (map == null)
//{
// throw new NullReferenceException(string.Format("Map was not found for {0}", entityType));
//}
//IPropertyMap propertyMap = map.Properties.SingleOrDefault(p => p.Name == propertyName);
//if (propertyMap == null)
//{
// throw new NullReferenceException(string.Format("{0} was not found for {1}", propertyName, entityType));
//}
//return sqlGenerator.GetColumnName(map, propertyMap, false);
}
}
public interface IComparePredicate : IBasePredicate
{
Operator Operators { get; set; }
bool Not { get; set; }
}
public abstract class ComparePredicate : BasePredicate
{
public Operator Operators { get; set; }
public bool Not { get; set; }
public virtual string GetOperatorString()
{
switch (Operators)
{
case Operator.EqualSmaller:
return Not ? "<=" : ">";
case Operator.EqualLarger:
return Not ? "<" : ">=";
case Operator.Smaller:
return Not ? ">=" : "<";
case Operator.Larger:
return Not ? ">" : "<=";
case Operator.Like:
return Not ? "NOT LIKE" : "LIKE";
case Operator.NotEqual:
return "<>";
case Operator.Equal:
return "=";
case Operator.In:
return "in";
default:
return Not ? "<>" : "=";
}
}
}
public interface IFieldPredicate : IComparePredicate
{
object Value { get; set; }
}
public class FieldPredicate : ComparePredicate, IFieldPredicate
where T : class
{
public object Value { get; set; }
///
/// 获取拼接SQL语句
///
///
///
public override string GetSql(FieldValueCollection md, QueryCommand parameters)
{
if (Value == null)
{
return string.Format("([{0}].{1} IS {2} NULL)", TableName, PropertyName, Not ? "NOT" : string.Empty);
}
if (Value is IEnumerable && !(Value is string))
{
List paramlist = new List();
foreach (var value in (IEnumerable)Value)
{
string valueParameterName = parameters.SetParameterName(this.PropertyName, value, md);
paramlist.Add(valueParameterName);
}
string paramStrings = paramlist.Aggregate(new StringBuilder(), (sb, s) => sb.Append((sb.Length != 0 ? ", " : string.Empty) + s), sb => sb.ToString());
return string.Format("([{0}].{1} {2} IN ({3}))", TableName, PropertyName, Not ? "NOT " : string.Empty, paramStrings);
}
string parameterName = parameters.SetParameterName(this.PropertyName, this.Value, md);
return string.Format("([{0}].{1} {2} {3})", TableName, PropertyName, GetOperatorString(), parameters.DbParmChar + parameterName);
}
}
public interface IPropertyPredicate : IComparePredicate
{
string PropertyName2 { get; set; }
}
public class PropertyPredicate : ComparePredicate, IPropertyPredicate
where T : class
where T2 : class
{
public string PropertyName2 { get; set; }
public override string GetSql(FieldValueCollection md, QueryCommand parameters)
{
string columnName = GetColumnName(typeof(T), PropertyName);
string columnName2 = GetColumnName(typeof(T2), PropertyName2);
return string.Format("({0} {1} {2})", columnName, GetOperatorString(), columnName2);
}
}
#region BetweenAnd
///
///
///
public struct BetweenValues
{
public object Value1 { get; set; }
public object Value2 { get; set; }
}
public interface IBetweenPredicate : IPredicate
{
string PropertyName { get; set; }
BetweenValues Value { get; set; }
bool Not { get; set; }
}
///
///
///
///
public class BetweenPredicate : BasePredicate, IBetweenPredicate
where T : class
{
public override string GetSql(FieldValueCollection md, QueryCommand parameters)
{
string propertyName1 = parameters.SetParameterName(this.PropertyName, this.Value.Value1, md);
string propertyName2 = parameters.SetParameterName(this.PropertyName, this.Value.Value2, md);
return string.Format("([{0}].{1} {2} BETWEEN {3} AND {4})", TableName, PropertyName, Not ? "NOT" : string.Empty, parameters.DbParmChar + propertyName1, parameters.DbParmChar + propertyName2);
}
public BetweenValues Value { get; set; }
public bool Not { get; set; }
}
#endregion
#region 查询条件分组
public interface IPredicateGroup : IPredicate
{
GroupOperator Operator { get; set; }
IList Predicates { get; set; }
}
///
/// 组装Predicate一起使用指定的组操作
///
public class PredicateGroup : IPredicateGroup
{
public GroupOperator Operator { get; set; }
public IList Predicates { get; set; }
public string GetSql(FieldValueCollection md, QueryCommand parameters)
{
string seperator = Operator == GroupOperator.And ? " AND " : " OR ";
List colum = new List();
return "(" + Predicates.Aggregate(new StringBuilder(), (sb, p) => (sb.Length == 0 ? sb : sb.Append(seperator)).Append(p.GetSql(md, parameters)),
sb =>
{
var s = sb.ToString();
if (s.Length == 0) return "";
return s;
}) + ")";
}
}
#endregion
public interface IExistsPredicate : IPredicate
{
IPredicate Predicate { get; set; }
bool Not { get; set; }
}
public class ExistsPredicate : IExistsPredicate
where TSub : class
{
public IPredicate Predicate { get; set; }
///
/// 表名
///
public string TableName { get; set; }
///
/// 非
///
public bool Not { get; set; }
///
/// 获取拼接SQL语句
///
///
///
///
public string GetSql(FieldValueCollection md, QueryCommand parameters)
{
string sql = string.Format("({0}EXISTS (SELECT 1 FROM [{1}] WHERE {2}))", Not ? "NOT " : string.Empty, TableName, Predicate.GetSql(md, parameters));
return sql;
}
}
///
/// 排序接口定义
///
public interface ISort
{
///
/// 表名
///
string TableName { get; set; }
///
/// 排序字段名
///
string PropertyName { get; set; }
///
/// 升序
///
bool Ascending { get; set; }
}
public class Sort : ISort
{
///
/// 表名
///
public string TableName { get; set; }
///
/// 排序字段名
///
public string PropertyName { get; set; }
///
/// 升序
///
public bool Ascending { get; set; }
}
///
/// 查询方式用and和or进行拼接枚举
///
public enum GroupOperator
{
And,
Or
}
}