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 } }