Entity Framework若干個擴展


聲明

這里有此東西是參考各大神修改和補充而來,有些地方就找不到原文章的地址了,一參考地址如下:

http://www.cnblogs.com/ahui/archive/2011/08/04/2127282.html

寄語

本着取之於大神,還之於大眾的精神,我把本人整理以及擴展的一些重要部分貼出來,希望你也積極把你覺得好的擴展回應到此貼中。

 

1、ExecuteSqlCommand和SqlQuery擴展

作用:擴展后省去寫大堆的new SqlParameter了

 #region 動態執行Sql語句擴展
        /// <summary>
        /// 根據sql語句和參數的值動態生成Sqlparameter
        /// </summary>
        /// <param name="sql">sql語句</param>
        /// <param name="values"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        private static SqlParameter[] MakeSqlParameter(string sql, object[] values)
        {
            var matches = Regex.Matches(sql, @"@\w+");
            List<string> paramNameList = new List<string>();

            foreach (Match m in matches)
            {
                if (paramNameList.Contains(m.Value) == false)
                {
                    paramNameList.Add(m.Value);
                }
            }

            if (values.Length != paramNameList.Count)
            {
                throw new ArgumentException("values的元素數目和Sql語句不匹配");
            }

            int i = 0;
            var parameters = new SqlParameter[values.Length];
            foreach (var pName in paramNameList)
            {
                parameters[i] = new SqlParameter(pName, values[i]);
                i++;
            }
            return parameters;
        }

        /// <summary>
        /// 執行Sql命令  
        /// <example>ExecuteSqlCommandEx("delete from [Table] where ID=@0", Guid.Empty)</example>
        /// </summary>
        /// <param name="database">數據庫</param>
        /// <param name="sql">sql語句</param>
        /// <param name="values"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static int ExecuteSqlCommandEx(this Database database, string sql, params object[] values)
        {
            var param = DbSetExtended.MakeSqlParameter(sql, values);
            return database.ExecuteSqlCommand(sql, param);
        }

        /// <summary>
        /// 執行Sql查詢
        /// <example>SqlQueryEx("select * from [Table] where name=@0 and password=@1", "abc", "123456")</example>
        /// </summary>
        /// <param name="database">數據庫</param>
        /// <param name="sql">sql語句</param>
        /// <param name="values"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IEnumerable<TElement> SqlQueryEx<TElement>(this Database database, string sql, params object[] values)
        {
            var param = DbSetExtended.MakeSqlParameter(sql, values);
            return database.SqlQuery<TElement>(sql, param);
        }
        #endregion
View Code

2、排序擴展

作用:支持用字符串直接描述排序,如:OrderBy("key1,key2,key3 desc,ke4"),方便和UI交互

#region 排序擴展
        /// <summary>
        /// 排序公共方法
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderByKey">排序鍵排序鍵(不分大小寫)</param>
        /// <param name="orderByMethod">排序方法</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        private static IOrderedQueryable<T> OrderByCommon<T>(IQueryable<T> source, string orderByKey, string orderByMethod) where T : class
        {
            if (string.IsNullOrEmpty(orderByKey))
            {
                throw new ArgumentNullException("orderByKey");
            }

            Type sourceTtype = typeof(T);
            PropertyInfo keyProperty = sourceTtype.GetProperties().FirstOrDefault(p => p.Name.ToLower().Equals(orderByKey.Trim().ToLower()));
            if (keyProperty == null)
            {
                throw new ArgumentException("orderByKey不存在...");
            }

            var param = Expression.Parameter(sourceTtype, "item");
            var body = Expression.MakeMemberAccess(param, keyProperty);
            var orderByLambda = Expression.Lambda(body, param);

            var resultExp = Expression.Call(typeof(Queryable), orderByMethod, new Type[] { sourceTtype, keyProperty.PropertyType }, source.Expression, Expression.Quote(orderByLambda));
            var ordereQueryable = source.Provider.CreateQuery<T>(resultExp) as IOrderedQueryable<T>;
            return ordereQueryable;
        }

        /// <summary>
        /// 排序
        /// 選擇升序或降序
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderByKey">排序鍵排序鍵(不分大小寫)</param>
        /// <param name="ascending">是否升序</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderByKey, bool ascending) where T : class
        {
            var methodName = ascending ? "OrderBy" : "OrderByDescending";
            return DbSetExtended.OrderByCommon(source, orderByKey, methodName);
        }

        /// <summary>
        /// 排序次項
        /// 選擇升序或降序
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderByKey">排序鍵(不分大小寫)</param>
        /// <param name="ascending">是否升序</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string orderByKey, bool ascending) where T : class
        {
            var methodName = ascending ? "ThenBy" : "ThenByDescending";
            return DbSetExtended.OrderByCommon(source, orderByKey, methodName);
        }

        /// <summary>
        /// 多字段混合排序       
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderByString">排序字符串:例如CreateTime desc, ID asc 不區分大小寫</param>
        /// <exception cref="ArgumentNullException">orderByString</exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderByString) where T : class
        {
            Func<string[], bool> descFun = (item) => item.Length > 1 && item[1].Trim().ToLower().Equals("desc");

            var parameters = orderByString
                .Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                .Select(item => item.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries))
                .Select(item => new { Key = item.FirstOrDefault(), Asc = !descFun(item) })
                .ToList();

            if (parameters.Count == 0)
            {
                throw new ArgumentNullException("orderByString");
            }

            var firstP = parameters.FirstOrDefault();
            var orderQuery = source.OrderBy(firstP.Key, firstP.Asc);
            parameters.Skip(1).ToList().ForEach(p => orderQuery = orderQuery.ThenBy(p.Key, p.Asc));

            return orderQuery;
        }

        /// <summary>
        /// 排序
        /// 選擇升序或降序
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <typeparam name="TKey">排序鍵</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderKeySelector">排序器</param>
        /// <param name="ascending">是否升序</param>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey>> orderKeySelector, bool ascending)
        {
            if (ascending)
            {
                return source.OrderBy(orderKeySelector);
            }
            else
            {
                return source.OrderByDescending(orderKeySelector);
            }
        }

        /// <summary>
        /// 次項排序
        /// 選擇升序或降序
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <typeparam name="TKey">排序鍵</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="orderKeySelector">排序器</param>
        /// <param name="ascending">是否升序</param>
        /// <returns></returns>
        public static IOrderedQueryable<T> ThenBy<T, TKey>(this IOrderedQueryable<T> source, Expression<Func<T, TKey>> orderKeySelector, bool ascending)
        {
            if (ascending)
            {
                return source.ThenBy(orderKeySelector);
            }
            else
            {
                return source.ThenByDescending(orderKeySelector);
            }
        }
        #endregion
View Code

3、單張表省略式Select的擴展

作用:擴展后省去寫大堆的 item => new A(){A.key1 = item.key1....}

#region 查詢方法的擴展
        /// <summary>      
        /// Select方法的補充      
        /// rpy.SelectEx(item =>new TNew(){})等同rpy.Select(item => new TNew(){f1 = item.f1, f2 = item.f2 ,...})    
        /// rpy.SelectEx(item =>new TNew(){f1 = "something"})等同rpy.Select(item => new TNew(){ f1 ="something", f2 = item.f2 ,...})
        /// 其它選擇方法和原始Select方法一致
        /// </summary>        
        /// <typeparam name="T">源實體類型</typeparam>
        /// <typeparam name="TNew">新的實體類型</typeparam>
        /// <param name="source">數據源</param>
        /// <param name="selector">新對象實例</param>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IQueryable<TNew> SelectEx<T, TNew>(this IQueryable<T> source, Expression<Func<T, TNew>> selector) where T : class
        {
            if (selector == null)
            {
                throw new ArgumentNullException();
            }

            var body = selector.Body as MemberInitExpression;
            if (body != null)
            {
                var targetType = typeof(TNew);
                var targetProperties = targetType.GetProperties().ToList();
                var sourceProperties = typeof(T).GetProperties();

                var parameter = selector.Parameters[0];
                var bindedMembers = body.Bindings.Select(b => b.Member).ToList();
                var needBindProroties = targetProperties.Where(p => bindedMembers.Exists(m => m.Name.Equals(p.Name)) == false);

                var allBindings = body.Bindings.ToList();
                foreach (var property in needBindProroties)
                {
                    var sourceProperty = sourceProperties.FirstOrDefault(item => item.Name.Equals(property.Name));
                    if (sourceProperty != null)
                    {
                        var memberExp = Expression.MakeMemberAccess(parameter, sourceProperty);
                        var binding = Expression.Bind(property, memberExp);
                        allBindings.Add(binding);
                    }
                }

                var targetNew = Expression.New(targetType);
                var bodyNew = Expression.MemberInit(targetNew, allBindings);
                selector = (Expression<Func<T, TNew>>)Expression.Lambda(bodyNew, parameter);
            }

            return source.Select(selector);
        }
        #endregion
View Code

4、動態復雜的Where條件邏輯表達式生成的擴展

作用:生成復雜的過濾條件表達式,條件字段可以從UI上傳過來再動態生成Func<T,boo>表達式

 /// <summary>
    /// Where條件擴展
    /// 用於分步實現不確定條件個數的邏輯運算組織
    /// <remarks>作者:陳國偉 日期:2013/05/07</remarks>
    /// </summary>
    public static class Where
    {
        /// <summary>
        /// 邏輯枚舉
        /// </summary>
        public enum LogicEnum
        {
            /// <summary>
            /// 相等
            /// </summary>
            Equal,
            /// <summary>
            /// 不等
            /// </summary>
            NotEqual,
            /// <summary>
            /// 大於
            /// </summary>
            GreaterThan,
            /// <summary>
            /// 大於等於
            /// </summary>
            GreaterThanOrEqual,
            /// <summary>
            /// 小於
            /// </summary>
            LessThan,
            /// <summary>
            /// 小於等於
            /// </summary>
            LessThanOrEqual,
            /// <summary>
            /// 字條串的Contains
            /// </summary>
            Contains
        }

        /// <summary>
        /// 參數替換對象
        /// </summary>
        private class ParameterReplacer : ExpressionVisitor
        {
            /// <summary>
            /// 表達式的參數
            /// </summary>
            public ParameterExpression ParameterExpression { get; private set; }

            /// <summary>
            /// 參數替換對象
            /// </summary>
            /// <param name="paramExp">表達式的參數</param>
            public ParameterReplacer(ParameterExpression paramExp)
            {
                this.ParameterExpression = paramExp;
            }

            /// <summary>
            /// 將表達式調度到此類中更專用的訪問方法之一
            /// </summary>
            /// <param name="exp">表達式</param>
            /// <returns></returns>
            public Expression Replace(Expression exp)
            {
                return this.Visit(exp);
            }

            /// <summary>
            /// 獲取表達式的參數
            /// </summary>
            /// <param name="p"></param>
            /// <returns></returns>
            protected override Expression VisitParameter(ParameterExpression p)
            {
                return this.ParameterExpression;
            }
        }

        /// <summary>
        /// 返回默認為True的條件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Expression<Func<T, bool>> True<T>()
        {
            return item => true;
        }

        /// <summary>
        /// 返回默認為False的條件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Expression<Func<T, bool>> False<T>()
        {
            return item => false;
        }

        /// <summary>
        /// 與邏輯運算
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="expLeft">表達式1</param>
        /// <param name="expRight">表達式2</param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expLeft, Expression<Func<T, bool>> expRight)
        {
            var candidateExpr = Expression.Parameter(typeof(T), "item");
            var parameterReplacer = new ParameterReplacer(candidateExpr);

            var left = parameterReplacer.Replace(expLeft.Body);
            var right = parameterReplacer.Replace(expRight.Body);
            var body = Expression.And(left, right);

            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }

        /// <summary>
        /// 或邏輯運算
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="expLeft">表達式1</param>
        /// <param name="expRight">表達式2</param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expLeft, Expression<Func<T, bool>> expRight)
        {
            var candidateExpr = Expression.Parameter(typeof(T), "item");
            var parameterReplacer = new ParameterReplacer(candidateExpr);

            var left = parameterReplacer.Replace(expLeft.Body);
            var right = parameterReplacer.Replace(expRight.Body);
            var body = Expression.Or(left, right);

            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }

        /// <summary>
        /// 動態生成Where邏輯表達式
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="member">實體的成員(不區分大小寫)</param>
        /// <param name="logic">邏輯關系</param>
        /// <param name="matchValue">要匹配的值</param>     
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static Expression<Func<T, bool>> Parse<T>(string member, LogicEnum logic, string matchValue)
        {
            if (string.IsNullOrEmpty(member))
            {
                throw new ArgumentNullException("member");
            }

            var keyProperty = typeof(T).GetProperties().FirstOrDefault(item => item.Name.ToLower().Equals(member.Trim().ToLower()));
            if (keyProperty == null)
            {
                throw new ArgumentException("member不存在");
            }

            // item
            var pExp = Expression.Parameter(typeof(T), "item");
            // item.CreateTime
            Expression memberExp = Expression.MakeMemberAccess(pExp, keyProperty);

            if (logic != LogicEnum.Contains)
            {
                // 是否是可空類型
                bool memberIsNullableType = keyProperty.PropertyType.IsGenericType && keyProperty.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
                // 是可空類型則取類型的Value屬性
                if (memberIsNullableType == true)
                {
                    // item.CreateTime.Value
                    memberExp = Expression.MakeMemberAccess(memberExp, keyProperty.PropertyType.GetProperty("Value"));
                }

                // 目標值類型
                Type valueType = keyProperty.PropertyType;
                if (memberIsNullableType == true)
                {
                    valueType = valueType.GetGenericArguments().FirstOrDefault();
                }

                object value = matchValue;
                if (valueType.Equals(typeof(string)) == false)
                {
                    // value = DateTime.Parse(matchValue)
                    value = valueType.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(null, new object[] { value });
                }

                var valueExp = Expression.Constant(value, valueType);
                // Expression.Equal
                var expMethod = typeof(Expression).GetMethod(logic.ToString(), new Type[] { typeof(Expression), typeof(Expression) });

                // item.CreateTime.Value == value
                var body = expMethod.Invoke(null, new object[] { memberExp, valueExp }) as Expression;
                return Expression.Lambda(body, pExp) as Expression<Func<T, bool>>;
            }
            else
            {
                // item.Member.Contains("something")
                var body = Expression.Call(memberExp, typeof(string).GetMethod(logic.ToString()), Expression.Constant(matchValue, typeof(string)));
                return Expression.Lambda(body, pExp) as Expression<Func<T, bool>>;
            }
        }

        /// <summary>
        /// 動態生成和匹配參數數目相同的邏輯表達式並用Or關聯起來
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="member">實體成員</param>
        /// <param name="logic">邏輯關系</param>
        /// <param name="matchValues">匹配值</param>       
        /// <returns></returns>
        public static Expression<Func<T, bool>> ParseOr<T>(string member, LogicEnum logic, params string[] matchValues)
        {
            var where = Where.Parse<T>(member, logic, matchValues.FirstOrDefault());
            matchValues.Skip(1).ToList().ForEach(value => where = where.Or(Where.Parse<T>(member, logic, value)));
            return where;
        }

        /// <summary>
        /// 動態生成和成員目相同的邏輯表達式並用Or關聯起來
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="members">實體成員</param>
        /// <param name="logic">邏輯關系</param>
        /// <param name="matchValue">匹配值</param>       
        /// <returns></returns>
        public static Expression<Func<T, bool>> ParseOr<T>(string[] members, LogicEnum logic, string matchValue)
        {
            var where = Where.Parse<T>(members.FirstOrDefault(), logic, matchValue);
            members.Skip(1).ToList().ForEach(member => where = where.Or(Where.Parse<T>(member, logic, matchValue)));
            return where;
        }

        /// <summary>
        /// 動態生成和匹配參數數目相同的邏輯表達式並用And關聯起來
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="member">實體成員</param>
        /// <param name="logic">邏輯關系</param>
        /// <param name="matchValues">匹配值</param>       
        /// <returns></returns>
        public static Expression<Func<T, bool>> ParseAnd<T>(string member, LogicEnum logic, params string[] matchValues)
        {
            var where = Where.Parse<T>(member, logic, matchValues.FirstOrDefault());
            matchValues.Skip(1).ToList().ForEach(value => where = where.And(Where.Parse<T>(member, logic, value)));
            return where;
        }

        /// <summary>
        /// 動態生成和成員目相同的邏輯表達式並用And關聯起來
        /// </summary>
        /// <typeparam name="T">實體類型</typeparam>
        /// <param name="members">實體成員</param>
        /// <param name="logic">邏輯關系</param>
        /// <param name="matchValue">匹配值</param>       
        /// <returns></returns>
        public static Expression<Func<T, bool>> ParseAnd<T>(string[] members, LogicEnum logic, string matchValue)
        {
            var where = Where.Parse<T>(members.FirstOrDefault(), logic, matchValue);
            members.Skip(1).ToList().ForEach(member => where = where.And(Where.Parse<T>(member, logic, matchValue)));
            return where;
        }
    }
View Code

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM