// ****************************************************** 
// 文件名称(File Name)：   Products.cs
// 项目名称(Project Name)：猛犸商贸演示系统
// 功能描述(Description)： 实现 产品 业务接口（此模块的功能描述与大概流程说明）
// 数据表(Tables)：        Products（所用到的数据表，视图，存储过程的说明，如关系比较复杂，则应说明哪些是可擦写的，哪些表为只读的）
// 作者(Author)：          zhaoshunlu@163.com
// 日期(Create Date)：     2014-10-21 21:48:52
// 参考文档(Reference)(可选)： （该档所对应的分析文档，设计文檔）
// 引用(Using) (可选)﹕        （开发的系统中引用其它系统的Dll、对象时，要列出其对应的出处，是否与系统有关﹙不清楚的可以不写﹚，以方便制作安装档）
// 修改记录(Revision History)：（若档案的所有者改变，则需要有修改人员的名字、修改日期及修改理由）
//****************************************************** 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Entity.Validation;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Linq.Dynamic;      //Linq to SQL Dynamic 动态查询
using System.Reflection;        //反射
using Northwind.IDAL;
using Northwind.Model;
using Northwind.DAL.Common;
namespace Northwind.DAL {

    /// <summary>
    /// 实现 产品 业务接口
    /// </summary>
    /// <remarks> 
    /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
    /// <para>修改人、日期及内容:</para>
    /// </remarks>
    public class ProductsDAL : IProducts {

        // 常量TableName和TableFields只有直接以SQL命令查询时（如GetListUseSQL、GetPages）才可能用到

        /// <summary>
        /// 表格名称       
        /// </summary>
        /// <value>string</value>
        const string TableName = "Products";
        /// <summary>
        /// 表格字段集合（字段名称首字母一律大写）
        /// </summary>
        /// <value>string</value>
        const string TableFields = "ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued";

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public ProductsDAL() {

        }

        #region 为用户返回底层错误、异常信息
        /// <summary>
        /// 缓存最后错误,为了返回底层错误给客户端
        /// </summary>
        /// <value>string</value>
        private string strLastErr = "";

        /// <summary>
        /// 获取最后的最内部的错误异常信息
        /// </summary>
        /// <returns>返回最后一条错误/异常信息</returns>
        /// <value>string</value> 
        public string GetLastError() {
            return strLastErr;
        }

        /// <summary>
        /// 获取最内部的异常信息   
        /// <see cref="Products.strLastErr"/> 缓存最后错误,为了返回底层错误给客户端.
        /// </summary>
        /// <param name="ex">异常对象</param>
        /// <param name="methodName">方法名称</param>
        /// <param name="companyCode">公司编码</param>
        /// <returns>返回最内部的异常信息 </returns>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>void</value>
        private void SetLastError(System.Exception ex, string methodName = "", string companyCode = "") {
            System.Exception baseEx = ex.GetBaseException();//获取最内部的异常信息
            strLastErr = (baseEx != null) ? baseEx.Message : ex.Message;
            //创建错误日记
            LogHelper.CreateLog(strLastErr, this.ToString(), methodName, companyCode);
        }
        #endregion

        #region 常规常用CRUD操作 公用成员方法组GetOne()、GetList()、GetListUseSQL、GetPage()、GetPages()、Insert()、Update()、Delete()、Save()

        #region 获取单个对象(一条记录)
        /// <summary>       
        /// 通过主键获取一条记录       
        /// </summary>
        /// <param name="ProductID">要查询的键值 如: 100</param>        
        /// <param name="state">自定义设置查询标志：如all 对象所有信息包括子对象（子表）信息，single 仅仅当前表信息</param>        
        /// <returns>返回一个Products对象或者null</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>  
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     Northwind.Model.Products model = bll.GetOne(10); 
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>Northwind.Model.Products</value>
        public Northwind.Model.Products GetOne(int ProductID, string state = "all") {

            using (NorthwindContext _context = new NorthwindContext()) {
                Northwind.Model.Products model = null;
                //if (state == "all"){
                //   //获取所有包括一至多个子表记录
                //   model = _context.Productss.Include("子表s").Single(o => o.ProductID == ProductID); //同时获取子表的写法：            
                //} else if (state == "single"){
                model = _context.Productss.Find(ProductID);
                //}                
                if (model == null) {
                    this.strLastErr = string.Format("没有找到ProductID={0}记录", ProductID);
                }
                return model;
            }
        }
        //YourAdminLoginExists
         
        #endregion

        #region 获取普通列表(无翻页)
        // 1、ALinq Dynamic (Linq to SQL Dynamic Query)
        /// <summary>
        /// 使用LINQ动态查询所有或部分记录         
        /// </summary>      
        /// <param name="conditionLinq">Linq Dynamic查询条件</param>    
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     //注意Linq to SQL Dynamic 动态查询,是查询对象属性名称而不是字段名称，有大小写区别。
        ///     //模糊查询EnCusCode.Contains(\"1002\")相对于SQL:EnCusCode like '%1002%',EnCusCode.Substring(0,4)==\"1002\"相对于SQL:EnCusCode like '1002%'
        ///     IList<Northwind.Model.Products> Productss = bll.GetList(" EnCusCode==\"" + enCusCode + "\" AND SaleDate>=DateTime(2013,9,10)");
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetList(string conditionLinq) {
            using (NorthwindContext _context = new NorthwindContext()) {
                if (!string.IsNullOrEmpty(conditionLinq)) {
                    return _context.Productss.Where(conditionLinq).ToList();
                } else {
                    return _context.Productss.ToList();
                }
                //排序：.OrderBy(o=>o.lineID);
            }
        }

        /// <summary>
        /// 使用LINQ动态查询所有或部分记录
        /// ,参数selector和conditionLinq不能空   
        /// </summary>
        /// <param name="top">返回数量</param>
        /// <param name="selector">要查询的匿名对象属性集合字符串</param>
        /// <param name="conditionLinq">Linq Dynamic查询条件</param>
        /// <param name="order">Linq Dynamic排序属性及方式</param>
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     //注意Linq to SQL Dynamic 动态查询,是查询对象属性名称而不是字段名称，有大小写区别。
        ///     //模糊查询EnCusCode.Contains(\"1002\")相对于SQL:EnCusCode like '%1002%',EnCusCode.Substring(0,4)==\"1002\"相对于SQL:EnCusCode like '1002%'
        ///     IList<Northwind.Model.Products> Productss = bll.GetListWithLinq(-1, "new(ID,EnCusCode,OrderStatue,UserSeat,SaleDate,Mobile)", " EnCusCode==\"" + enCusCode + "\" AND SaleDate>=DateTime(2013,9,10)", "ID Desc");
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetList(int top, string selector, string conditionLinq, string order) {
            using (NorthwindContext _context = new NorthwindContext()) {
                //参数selector和conditionLinq 不能空
                IQueryable<Products> iquery = _context.Productss.Where(conditionLinq);
                if (!string.IsNullOrEmpty(order)) {
                    iquery = iquery.OrderBy(order);
                }
                if (top > 0) {
                    iquery = iquery.Take(top);
                }
                var query = iquery.Select(selector);

                IList<Northwind.Model.Products> list = new List<Northwind.Model.Products>();
                PropertyInfo[] props = new PropertyInfo[1];
                int len = 0;
                IEnumerator em = query.GetEnumerator();  //枚举器
                while (em.MoveNext()) {
                    Northwind.Model.Products model = new Northwind.Model.Products();
                    if (len == 0) {
                        //初始化属性组
                        props = em.Current.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                        len = props.Length;
                    }
                    //遍历属性赋值(要是一个一个属性赋值真心累)
                    for (int i = 0; i < len; i++) {
                        PropertyInfo pinfo = model.GetType().GetProperty(props[i].Name, BindingFlags.Public | BindingFlags.Instance);
                        if (pinfo != null)
                            pinfo.SetValue(model, props[i].GetValue(em.Current, null), null);
                    }
                    list.Add(model);
                }
                return list;
            }
        }

        //2、使用Lambda表达式
        /// <summary>    
        /// 使用Lambda表达式查询获取所有或部分记录       
        /// </summary>
        /// <param name="whereLambda">查询条件 Lambda表达式</param>
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     Func<Northwind.Model.Products, bool> whereLambda = w => w.ProductName.Contains("张");//"张"为查询关键字词        
        ///     IList<Northwind.Model.Products> Productss = bll.GetList(whereLambda);     
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetList(Expression<Func<Northwind.Model.Products, bool>> whereLambda) {
            using (NorthwindContext _context = new NorthwindContext()) {
                return _context.Productss.Where(whereLambda).ToList();//排序：.OrderBy(o=>o.lineID);
            }
        }
        /// <summary>    
        /// 使用Lambda表达式查询获指定行数的部分记录
        /// </summary>
        /// <typeparam name="S">排序键的数据类型</typeparam>
        /// <param name="top">指定返回记录条数</param>
        /// <param name="whereLambda">查询条件Lambda表达式</param>
        /// <param name="orderLambda">排序Lambda表达式</param>
        /// <param name="isAsc">是否按升序排序,默认false</param>
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     Func<Northwind.Model.Products, bool> whereLambda = w => w.ProductName.Contains("张");//"张"为查询关键字词 
        ///     Func<Northwind.Model.Products, int> whereLambda = w => w.ProductID;  //按主键排序    
        ///     IList<Northwind.Model.Products> Productss = bll.GetList(10,whereLambda,orderByLambda,false);     
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetList<S>(int top, Expression<Func<Northwind.Model.Products, bool>> whereLambda, Expression<Func<Northwind.Model.Products, S>> orderLambda, bool isAsc = false) {
            using (NorthwindContext _context = new NorthwindContext()) {
                if (top < 1) top = 1;
                //升序
                if (isAsc) {
                    return _context.Productss.Where(whereLambda).OrderBy<Northwind.Model.Products, S>(orderLambda).Take(top).ToList();
                } else {
                    return _context.Productss.Where(whereLambda).OrderByDescending<Northwind.Model.Products, S>(orderLambda).Take(top).ToList();
                }
            }
        }

        //3、使用原始SQL命令表达式查询
        //注意：
        //以下2个查询记录的方法调用时参数直接使用到了数据表字段名称
        //如果数据表字段名称修改了，那么原先调用的程序将会得不到期望的结果甚至导致程序异常。

        /// <summary>      
        /// 通过查询获取所有或部分记录   
        ///  <para>参数<paramref name="conditions"/> 必须是正确的SQL查询条件表达式.表格字段名称必须正确</para>       
        /// </summary>       
        /// <param name="conditionSQL">查询条件 如: Name like '%张%'；为空或者null就返回所有数据</param>
        /// <param name="orderSQL">排序方式，默认null，为空或者null则按默认排序</param>
        /// <param name="top">查询记录条数，默认0，小于1则不限制返回行数</param>
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>       
        ///     <![CDATA[
        ///         Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///         string conditionSQL = "ProductName like '%张%'";         
        ///         IList<Northwind.Model.Products> Productss = bll.GetList(conditionSQL);
        ///     ]]>          
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetListUseSQL(string conditionSQL, string orderSQL = null, int top = 0) {
            //拼装SQL命令
            StringBuilder sbSql = new StringBuilder();
            sbSql.Append("SELECT ");
            if (top > 0) sbSql.AppendFormat(" TOP {0} ", top);		// 
            //注意字段名称首字母一律大写
                        sbSql.Append(" [me].[ProductID]");		// 产品ID
            sbSql.Append(",[me].[ProductName]");		// 产品名称
            sbSql.Append(",[me].[SupplierID]");		// 供应商ID
            sbSql.Append(",[me].[CategoryID]");		// 类别ID
            sbSql.Append(",[me].[QuantityPerUnit]");		// 数量单位
            sbSql.Append(",[me].[UnitPrice]");		// 单价
            sbSql.Append(",[me].[UnitsInStock]");		// 库存量
            sbSql.Append(",[me].[UnitsOnOrder]");		// 订购量
            sbSql.Append(",[me].[ReorderLevel]");		// 再订购量
            sbSql.Append(",[me].[Discontinued]");		// 中止


            sbSql.Append(" FROM [Products] AS [me] ");
            //条件
            if (!string.IsNullOrEmpty(conditionSQL))
                sbSql.AppendFormat(" WHERE {0}", conditionSQL);
            //排序
            if (!string.IsNullOrEmpty(orderSQL))
                sbSql.AppendFormat(" ORDER BY {0}", orderSQL);
            //
            string sql = sbSql.ToString();
            DataTable dt = DBUtil.GetDataTable(sql, null);
            IList<Northwind.Model.Products> list = new List<Northwind.Model.Products>();
            if (dt != null && dt.Rows.Count > 0) {
                PropertyInfo[] props = new PropertyInfo[1];
                int columnCount = dt.Columns.Count;
                for (int i = 0; i < dt.Rows.Count; i++) {
                    Northwind.Model.Products model = new Northwind.Model.Products();
                    //遍历属性赋值
                    for (int j = 0; j < columnCount; j++) {
                        PropertyInfo pinfo = model.GetType().GetProperty(dt.Columns[j].ColumnName, BindingFlags.Public | BindingFlags.Instance);
                        if (pinfo != null) {
                            if (dt.Rows[i][j] != DBNull.Value) {
                                pinfo.SetValue(model, dt.Rows[i][j], null);
                            } else {
                                // 默认值
                            }
                        }
                    }
                    list.Add(model);
                }
            }
            return list;
        }

        /// <summary>
        /// 通过原始SQL命令查询获取所有或部分记录   
        /// 必须是正确的SQL查询条件表达式.
        /// </summary>        
        /// <param name="top">指定返回记录条数,小于1则不限制返回行数</param>
        /// <param name="selector">投影字段,null或者""或者"*"返回所有字段</param>
        /// <param name="conditionSQL">查询条件如：SaleItem like '%张%'</param>  
        /// <param name="order">排序如：ID Desc</param>          
        /// <returns>DataTable</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>       
        ///     <![CDATA[
        ///         Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();      
        ///         DataTable table = bll.GetTableUseSQL(10,"ID,Title,Date","Title like '%海南%'","ID Desc");
        ///     ]]>          
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>DataTable</value>
        public DataTable GetTableUseSQL(int top, string selector, string conditionSQL, string orderSQL) {
            StringBuilder sbSQL = new StringBuilder("SELECT ");
            if (top > 0) sbSQL.AppendFormat(" TOP {0} ", top);
            if (string.IsNullOrEmpty(selector) || selector == "*")
                sbSQL.Append(selector);
            else
                sbSQL.Append(selector);
            //
            sbSQL.AppendFormat(" FROM {0}", TableName);
            //条件
            if (!string.IsNullOrEmpty(conditionSQL))
                sbSQL.AppendFormat(" WHERE {0}", conditionSQL);
            //排序
            if (!string.IsNullOrEmpty(orderSQL))
                sbSQL.AppendFormat(" ORDER BY {0}", orderSQL);

            return DBUtil.GetDataTable(sbSQL.ToString(), null);
        }
        #endregion

        #region 获取翻页列表

        /// <summary>       
        /// 通过Linq 动态查询获取所有或部分记录,
        /// <para>按指定的字段或者属性名称进行排序，只能对一个字段进行排序,</para>
        /// <para>并将结果进行分页</para>       
        /// <para>参数<paramref name="propertyName"/> 是对象的属性名称,不是表格字段名称.</para>
        /// </summary>        
        /// <param name="pageSize">每页数据行数</param>
        /// <param name="pageIndex">当前页面</param>        
        /// <param name="conditionLinq">Linq查询条件表达式</param>
        /// <param name="isAsc">是否按升序排序</param>
        /// <param name="propertyName">要排序的属性名称(不是字段名称)</param>
        /// <param name="total">输出总记录条数</param>
        /// <returns>返回一组Products集合对象</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     string conditionLinq =" ProductName==\"" + enCusCode + "\" AND YourDate>=DateTime(2013,9,10) AND YourContent.Contains(\"" + enCusCode + "\")" //key为查询关键字词 如"张"        
        ///     string propertyName = "name";                                           //按字段 name 进行排序
        ///     bool isAsc = false;                                                     //默认按降序排序
        ///     int total = 0;                                                          //缓存方法输出的数据总行数        
        ///     IList<Northwind.Model.Products> Productss = bll.GetPage(pageSize, pageIndex, conditionLinq, isAsc, propertyName, out total);
        ///     //遍历所有记录
        ///     //foreach (Northwind.Model.Products model in Productss)
        ///     //{
        ///     //     model.
        ///     //}     
        ///     ]]>
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>IList<Northwind.Model.Products></value>
        public IList<Northwind.Model.Products> GetPage(int pageSize, int pageIndex, string conditionLinq, bool isAsc, string propertyName, out int total) {
            using (NorthwindContext _context = new NorthwindContext()) {
                total = 0;
                if (pageSize < 1) pageSize = 10;
                if (pageIndex < 0) pageIndex = 0;
                //先查询出数据              
                IQueryable<Northwind.Model.Products> query;
                if (string.IsNullOrEmpty(conditionLinq)) {
                    query = (isAsc) ? _context.Productss.OrderBy(propertyName + " ASC") : _context.Productss.OrderBy(propertyName + " DESC");
                    total = query.Count();
                } else {
                    query = (isAsc) ? _context.Productss.Where(conditionLinq).OrderBy(propertyName + " ASC") : _context.Productss.Where(conditionLinq).OrderBy(propertyName + " DESC");
                    total = query.Count();
                }
                //分页
                IList<Northwind.Model.Products> pageList = query.Skip(pageSize * pageIndex).Take(pageSize).ToList();
                return pageList;
            }
        }

        //注意：
        //以下查询翻页记录的方法调用时参数直接使用到了数据表字段名称
        //如果数据表字段名称修改了，那么原先调用的程序将会得不到期望的结果甚至导致程序异常。
        /// <summary>      
        /// <para>通过原始的SQL命令查询获取所有或部分记录,可以从表格或者视图获取记录,</para>
        /// <para>按指定的字段或者属性名称进行排序，只能对一个字段进行排序,</para>
        /// <para>并将结果进行分页</para>      
        /// <para>参数<paramref name="conditionSQL"/> 必须是正确的SQL查询条件表达式.表格字段名称必须正确</para>
        /// <para>参数<paramref name="sortField"/> 必须是表格字段名称.</para>
        /// </summary>  
        /// <param name="pageSize">每页数据行数</param>
        /// <param name="pageIndex">当前页面</param>        
        /// <param name="conditionSQL">SQL查询条件表达式</param>
        /// <param name="isAsc">是否按升序排序</param>
        /// <param name="sortField">要排序的属性名称(字段名称)</param>
        /// <param name="total">总记录条数,如果pageIndex=0 或者total=0，就查询总记录数，否则就不查询总记录数</param>
        /// <param name="bStatistics">是否进行服务端统计,默认false不统计</param>
        /// <returns>返回一个哈希表</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>  
        ///     <![CDATA[
        ///    Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     string conditionSQL = "ProductName like '%"+key+"%'";   //key为查询关键字词 如"张"
        ///     string sortField = "name";                                      //按字段 name 进行排序
        ///     bool isAsc = false;                                                     //默认按降序排序
        ///     int total = 0;                                                          //缓存方法输出的数据总行数        
        ///     Hashtable result = bll.GetPages(pageSize, pageIndex, conditionSQL, isAsc, sortField, total);
        ///     //result["data"]  是 IList<Hashtable>每一项一行数据;
        ///     //result["total"] 是 总记录数;
        ///     ]]>   
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>Hashtable</value>
        public Hashtable GetPages(int pageSize, int pageIndex, string conditionSQL, bool isAsc, string sortField, int total, bool bStatistics = false) {

            //拼装SQL命令
            StringBuilder sbSql = new StringBuilder();
            sbSql.Append("SELECT ");
            //注意字段名称首字母一律大写
                        sbSql.Append(" [me].[ProductID]");		// 产品ID
            sbSql.Append(",[me].[ProductName]");		// 产品名称
            sbSql.Append(",[me].[SupplierID]");		// 供应商ID
            sbSql.Append(",[me].[CategoryID]");		// 类别ID
            sbSql.Append(",[me].[QuantityPerUnit]");		// 数量单位
            sbSql.Append(",[me].[UnitPrice]");		// 单价
            sbSql.Append(",[me].[UnitsInStock]");		// 库存量
            sbSql.Append(",[me].[UnitsOnOrder]");		// 订购量
            sbSql.Append(",[me].[ReorderLevel]");		// 再订购量
            sbSql.Append(",[me].[Discontinued]");		// 中止

            sbSql.Append(" FROM [Products] AS [me] ");
            //
            string sql = sbSql.ToString();

            //统计总记录的SQL命令
            StringBuilder sbSQLCnt = new StringBuilder("Select Count(*) FROM [Products] AS [me] ");
            //
            string sqlCnt = sbSQLCnt.ToString();

            if (!string.IsNullOrEmpty(conditionSQL)) {
                sql += " WHERE " + conditionSQL;
                sqlCnt += " WHERE " + conditionSQL;
            }
            string strOrderBy = "";
            if (!string.IsNullOrEmpty(sortField)) {
                strOrderBy = " ORDER BY " + sortField;
                if (!isAsc) strOrderBy += " desc";
            }
            //
            Hashtable result = new Hashtable();
            //查询数据库 //调用公共数据库操作类DBUtil获取记录(支持翻页)        
            IList<Hashtable> data = new List<Hashtable>();
            if (pageIndex == 0 || total == 0) {
                //第一页               
                data = DBUtil.GetPages(pageSize, pageIndex, sql, sqlCnt, strOrderBy, out total);
                //
                if (bStatistics) {
                    //进行服务端统计
                    Hashtable tjTab = GetStatistics(conditionSQL);
                    foreach (DictionaryEntry de in tjTab) {
                        result[de.Key.ToString()] = de.Value;
                    }
                }
            } else {
                //第二页及之后就不需要再次获取总记录行数            
                data = DBUtil.GetPages(pageSize, pageIndex, sql, strOrderBy);
            }
            //准备返回值 
            result["data"] = data;   //一个页面的数据集
            result["total"] = total; //总记录条数

            //返回结果
            return result;
        }
        /// <summary>
        /// 所有翻页内的数据统计，如果没有用到统计业务就可以删除此方法
        /// </summary>
        /// <param name="conditionSQL"></param>
        /// <returns></returns>    
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>Hashtable</value>
        private Hashtable GetStatistics(string conditionSQL) {

            Hashtable result = new Hashtable();
            /* 应用举例 查询订单 人数及销售金额及利润
             * 如果没有用到统计业务就可以删除此方法
             * 
            //拼装查询SQL命令 
            //在查询条件“conditionSQL”中可能用到查询的字段都要列出来
            StringBuilder sbSql = new StringBuilder();
            sbSql.Append("SELECT * FROM ("); 
            sbSql.Append("SELECT ");
            //注意字段名称首字母一律大写
            //要统计的字段
            bSql.Append(" ,[me].[AdultNum]");               // 大人数
            sbSql.Append(",[me].[Childnum]");	            // 小孩数
            sbSql.Append(",[me].[BranchSaleTotal]");        // 销售金额
            sbSql.Append(",[me].[SaleTotal]");		        // 地接金额
            sbSql.Append(",[me].[Profit]");                 // 毛利 
            //要查询参数的字段
            sbSql.Append(",[me].[OtherDate]");              // 消费日期
            sbSql.Append(",[T_SaleHoliday].[Customer]");    //客人姓名
            //来源表格
            sbSql.Append(" FROM [T_SaleHoliday_other] AS [me] ");
            sbSql.Append(" LEFT JOIN [T_SaleHoliday] ON  T_SaleHoliday.SaleOrderID = me.SaleOrderID");
            //
            sbSql.Append(" ) AS My_View "); //创建视图
            //接上查询条件
            if (!string.IsNullOrEmpty(conditionSQL)) {
                sbSql.Append(" WHERE " + conditionSQL);
            }
            string sql = sbSql.ToString();

            //拼装统计SQL命令
            StringBuilder orSQL = new StringBuilder();
            orSQL.Append("select sum(AdultNum) as AdultNum,sum(Childnum) as Childnum,sum(BranchSaleTotal) as BranchSaleTotal,sum(SaleTotal) as SaleTotal,sum(Profit) as Profit from (");
            orSQL.Append(sql);
            orSQL.Append(" ) as T");
            //
            DataTable dt = DBUtil.GetDataTable(orSQL.ToString(), null);
            if (dt != null && dt.Rows.Count > 0) {
                result["AdultNum"] = (dt.Rows[0]["AdultNum"] != DBNull.Value) ? Convert.ToInt32(dt.Rows[0]["AdultNum"].ToString()) : 0; // 大人统计数
                result["Childnum"] = (dt.Rows[0]["Childnum"] != DBNull.Value) ? Convert.ToInt32(dt.Rows[0]["Childnum"].ToString()) : 0; // 小孩统计数
                //
                result["BranchSaleTotal"] = (dt.Rows[0]["BranchSaleTotal"] != DBNull.Value) ? Convert.ToDecimal(dt.Rows[0]["BranchSaleTotal"].ToString()) : 0; // 销售统计金额
                result["SaleTotal"] = (dt.Rows[0]["SaleTotal"] != DBNull.Value) ? Convert.ToDecimal(dt.Rows[0]["SaleTotal"].ToString()) : 0;                   // 地接统计金额
                result["Profit"] = (dt.Rows[0]["Profit"] != DBNull.Value) ? Convert.ToDecimal(dt.Rows[0]["Profit"].ToString()) : 0;                            // 毛利统计
            }
            */
            //准备返回
            return result;

        }
        #endregion
        //
        #region 增删改操作
        /// <summary>       
        /// 插入一条新记录  
        /// </summary>
        /// <param name="model">要添加的实体对象</param>
        /// <returns>插入成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///      Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///      bll.Insert(model);  
        ///     ]]> 
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Insert(Northwind.Model.Products model) {
            if (model == null) {
                this.strLastErr = "要保存的对象为null";
                return false;
            }
            using (NorthwindContext _context = new NorthwindContext()) {
                //-- 插入前判断（如属性/字段值是否已经存在）
                //if (_context.Productss.Any(o => o.属性名称 == model.属性名称)) {
                //    this.strLastErr = "已经存在" + model.属性名称 + "的记录";
                //    return false;
                //}
                //如果有子表记录，_context.SaveChanges()将以事务方式同时保存

                //一是直接创建对象，然后调用“DbSet”的”Add()”方法进行添加
                _context.Productss.Add(model);

                //二是调用数据库上下文的”Entry()”方法并设置对应的状态。
                //DbEntityEntry<Northwind.Model.Products> entity = _context.Entry(model);  //此时entity的State 是 System.Data.EntityState.Detached    
                //entity.State = EntityState.Added;//于_context而言，model是一个全新、外来、陌生的对象，所以把状态强制更改为EntityState.Added，               
                //或者直接写成
                //_context.Entry(model).State = EntityState.Added;

                try {
                    return _context.SaveChanges() > 0;
                } catch (DbEntityValidationException dvEx) {
                    DbValidationError dvError = dvEx.EntityValidationErrors.First().ValidationErrors.First();
                    this.strLastErr = "属性" + dvError.PropertyName + "错误：" + dvError.ErrorMessage;
                    //创建错误日记
                    LogHelper.CreateLog(strLastErr, this.ToString(), "Insert()");
                    //
                    return false;
                } catch (System.Exception ex) {
                    SetLastError(ex);
                    return false;
                }
            }
        }

        /// <summary>      
        /// 修改原有的一条记录 
        /// <para>注意如果只设置了对象部分属性值请勿使用此方法保存数据，保存后会导致记录行原来字段数据丢失</para>
        /// </summary>
        /// <param name="model">要修改的实体对象</param>
        /// <returns>更新成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     bll.Update(model);     
        ///     ]]> 
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Update(Northwind.Model.Products model) {
            if (model == null) {
                this.strLastErr = "要保存的对象为null";
                return false;
            }
            using (NorthwindContext _context = new NorthwindContext()) {
                //-- 更新前判断（如属性/字段值是否已经存在）
                //if (_context.Productss.Any(o => o.ProductID != model.ProductID && o.属性名称 == model.属性名称 )) {
                //    this.strLastErr = "已经存在" + model.属性名称 + "的记录";
                //    return false;
                //}
                try {
                    //如果有子表记录，_context.SaveChanges()不会保存更新子表记录，
                    //这个问题目前只好手动保存更新子表了。

                    // //无子表对象可删除下面多余代码           
                    //for (int i = 0; i < model.子表s.Count; i++) {
                    //    子表 mod = model.子表s[i];
                    //    //如果不是新建，而是修改或者删除状态，就要先查找到对象
                    //    //判断是否新增，最好判断自动编号是否为0                   
                    //    if ((mod._state == "null" || mod._state == "added")) {
                    //        _context.子表s.Add(mod);
                    //    } else if (mod._state == "modified") {
                    //        //方式1、直接修改状态
                    //        _context.Entry(mod).State = EntityState.Modified;
                    //        //方式2、通过复制对象值
                    //        //DbEntityEntry<子表> entity = _context.Entry(_context.子表s.Find(mod.ID));
                    //        //entity.CurrentValues.SetValues(mod);//如果是修改状态就要重新复制对象值 
                    //    } else if (mod._state == "removed") {
                    //        //方式1、直接删除
                    //        //_context.子表.Remove(mod);
                    //        //方式2、实体实例使用Attach方法
                    //        _context.子表.Remove(_context.子表.Attach(mod)); 
                    //    }
                    //}
                    //model.子表s.Clear();//清除过期的子表记录

                    //保存记录
                    //方式1、直接修改状态，更新所有字段
                    //_context.Entry(model).State = EntityState.Modified;                           
                    //方式2、新旧记录进行对比，只更新有修改的字段                 
                    Products thisModel = _context.Productss.Find(model.ProductID);
                    string[] names = DataValidator.UpdateDifferent(thisModel, model);                      
                    //
                    return _context.SaveChanges() > 0;

                } catch (DbEntityValidationException dvEx) {
                    DbValidationError dvError = dvEx.EntityValidationErrors.First().ValidationErrors.First();
                    this.strLastErr = "属性" + dvError.PropertyName + "错误：" + dvError.ErrorMessage;
                    //创建错误日记
                    LogHelper.CreateLog(strLastErr, this.ToString(), "Update()");
                    return false;
                } catch (System.Exception ex) {
                    SetLastError(ex);
                    return false;
                }
            }
        }

        /// <summary>      
        /// 更新表单提交的数据 
        /// <para>必须指定要修改的属性名称集合</para>
        /// </summary>
        /// <param name="model">要修改的实体对象</param>
        /// <param name="SetKes">要修改的属性名称集合</param>
		/// <param name="FilterKeys">特别指定需要排除的属性键集合,默认为null</param>
        /// <returns>更新成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     bll.Update(model,new string[]{"Name","Sex"});     
        ///     ]]> 
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool UpdateForm(Northwind.Model.Products model, string[] SetKes = null, string[] FilterKeys = null) {
            if (model == null) {
                this.strLastErr = "要保存的对象为null";
                return false;
            }
            if (SetKes == null || (SetKes != null && SetKes.Length==0)) {
                this.strLastErr = "没有指订要修改的属性名称集合";
                return false;
            }
            using (NorthwindContext _context = new NorthwindContext()) {
                //-- 更新前判断（如属性/字段值是否已经存在）
                //if (_context.Productss.Any(o => o.ProductID != model.ProductID && o.属性名称 == model.属性名称 )) {
                //    this.strLastErr = "已经存在" + model.属性名称 + "的记录";
                //    return false;
                //}
                try {
                    //如果有子表记录，_context.SaveChanges()不会保存更新子表记录，
                    //这个问题目前只好手动保存更新子表了。

                    // //无子表对象可删除下面多余代码           
                    //for (int i = 0; i < model.子表s.Count; i++) {
                    //    子表 mod = model.子表s[i];
                    //    //如果不是新建，而是修改或者删除状态，就要先查找到对象
                    //    //判断是否新增，最好判断自动编号是否为0                   
                    //    if ((mod._state == "null" || mod._state == "added")) {
                    //        _context.子表s.Add(mod);
                    //    } else if (mod._state == "modified") {
                    //        //方式1、直接修改状态
                    //        _context.Entry(mod).State = EntityState.Modified;
                    //        //方式2、通过复制对象值
                    //        //DbEntityEntry<子表> entity = _context.Entry(_context.子表s.Find(mod.ID));
                    //        //entity.CurrentValues.SetValues(mod);//如果是修改状态就要重新复制对象值 
                    //    } else if (mod._state == "removed") {
                    //        //方式1、直接删除
                    //        //_context.子表.Remove(mod);
                    //        //方式2、实体实例使用Attach方法
                    //        _context.子表.Remove(_context.子表.Attach(mod)); 
                    //    }
                    //}
                    //model.子表s.Clear();//清除过期的子表记录
                    //

                    //添加到EF管理容器中
                    DbEntityEntry<Products> entity = _context.Entry<Products>(model);
                    entity.State = System.Data.EntityState.Unchanged;
                    //标识 实体对象 某些属性 已经被修改了
                    for (int i = 0; i < SetKes.Length; i++) {
                        if (!string.IsNullOrEmpty(SetKes[i])) {
                            //怎么判断他是无映射到属性？非映射属性不能存，目前暂时靠 FilterKeys 来跳过了
                            if (FilterKeys != null && FilterKeys.Contains(SetKes[i])){
                                //跳过指定要排除的属性
                            }else {
                                entity.Property(SetKes[i]).IsModified = true; //做修改标志
                            }
                        }
                    }
                    // 
                    return _context.SaveChanges() > 0;

                } catch (DbEntityValidationException dvEx) {
                    DbValidationError dvError = dvEx.EntityValidationErrors.First().ValidationErrors.First();
                    this.strLastErr = "属性" + dvError.PropertyName + "错误：" + dvError.ErrorMessage;
                    //创建错误日记
                    LogHelper.CreateLog(strLastErr, this.ToString(), "UpdateForm()");
                    return false;
                } catch (System.Exception ex) {
                    SetLastError(ex);
                    return false;
                }
            }
        }

        /// <summary>      
        /// 通过主键删除一条或多条记录（通过判断参数中的逗号分隔符来决定是否删除多条记录）
        /// </summary>
        /// <param name="ProductID">要删除的键值，如24，或者是以逗号分隔的主键集合，如：2,34,50,36</param>
        /// <param name="CompanyCode">公司编码</param>
        /// <param name="OpMaker">操作人名称</param>
        /// <returns>删除成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///         Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///         bll.Delete(23);  
        ///     ]]> 
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Delete(string Keys, string CompanyCode = null, string OpMaker = null) {
            if (string.IsNullOrEmpty(Keys)) {
                this.strLastErr = "参数为空值";
                return false;
            }
            using (NorthwindContext _context = new NorthwindContext()) {
                //int
                bool ischg = false;
                if (Keys.IndexOf(",") < 1) {
                    //删除一条记录
                    //if (DataValidator.IsNumber(Keys)) { //如果主键是数字类型，启用参数验证
                    int ProductID = Convert.ToInt32(Keys);
                    Northwind.Model.Products model = _context.Productss.Find(ProductID);
                    if (model != null) {
                        //--  删除前判断（如记录是否被使用或者存在子表数据）
                        //if (_context.子表类名s.Any(o => o.ProductID == ProductID)) {
                        //    //已经有子表，不能删除
                        //    this.strLastErr = mod.标题 + "已经有子表记录，不能删除";                  
                        //}else{
                        //--删除
                        _context.Productss.Remove(model);
                        ischg = true;
                        //}
                    } else {
                        this.strLastErr = string.Format("没有找到ProductID={0}记录", Keys);
                    }
                    //} else {
                    //    this.strLastErr = string.Format("参数ProductID={0}错误", Keys);
                    //}
                } else {
                    // 删除多条记录
                    string[] ids = Keys.Split(new char[] { ',' });
                    int ProductID;
                    for (int i = ids.Length - 1; i >= 0; i--) {
                        //if (DataValidator.IsNumber(ids[i])) {//如果主键是数字类型，启用参数验证
                        ProductID = Convert.ToInt32(ids[i]);
                        Northwind.Model.Products model = _context.Productss.Find(ProductID);
                        if (model != null) {
                            //--  删除前判断（如记录是否被使用或者存在子表数据）
                            //if (_context.子表类名s.Any(o => o.ProductID == mod.ProductID)) {
                            //    //已经有子表，不能删除
                            //    this.strLastErr = mod.标题 + "已经有子表记录，不能删除";
                            //    ischg = false;
                            //    break;
                            //}else{
                            //--删除
                            _context.Productss.Remove(model);
                            if (!ischg) ischg = true;
                            //}
                        }
                        //} else {
                        //    this.strLastErr = string.Format("参数ProductID={0}错误", ids[i]);
                        //    ischg = false;
                        //    break;
                        //}
                    }
                }
                if (ischg) {//需要提交更新                
                    try {
                        return _context.SaveChanges() > 0;
                    } catch (System.Exception ex) {
                        SetLastError(ex);
                        return false;
                    }
                } else
                    return false;
            }
        }

        /// <summary>      
        /// 通过主键删除一条或多条记录（通过判断参数中的逗号分隔符来决定是否删除多条记录）,并输出要删除的文件列表
        /// </summary>
        /// <param name="Keys">要删除的主键集合（以逗号,分隔）</param>
        /// <param name="files">输出要删除的文件列表</param>
        /// <param name="OpMaker">操作人名称</param>
        /// <returns>删除成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///     IList<string> files = new List<string>();
        ///     Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///     bll.Delete("2,34,50,36",out files);   
        ///     ]]> 
        ///     </code>
        /// </example>
        /// <remarks> 
        /// 创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Delete(string Keys, out IList<string> files, string OpMaker = null) {
            files = new List<string>();
            //需要时请重新编写方法输出要删除的文件列表
            //你的代码
            return Delete(Keys);
        }

        #endregion

        #region 保存与批量保存操作
        /// <summary>    
        /// 保存数据单个对象（一条记录）   
        /// </summary>
        /// <param name="model"></param>
        /// <returns>保存成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>
        ///     <![CDATA[
        ///         Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///         bll.Save(model);  
        ///     ]]>   
        ///     </code>
        /// </example>
        /// <remarks> 
        /// <para>使用页面：</para>
        /// <para>创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52</para>
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Save(Northwind.Model.Products model) {
            if (model == null)
                return false;

            //判断主键是否为0或者为空
            //要求表必须有自动增长字段,如果没有自增字段，主键为字符串字段，请自行判断           
            //if (string.IsNullOrEmpty(model.ProductID))
            if (model.ProductID == 0) {
                return Insert(model);
            } else {
                return Update(model);
            }
        }

        /// <summary>        
        /// 批量保存多条记录(可以混合删除、新增、修改操作) 
        /// </summary>
        /// <param name="models"></param>    
        /// <returns>保存成功返回true,失败返回false</returns>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>   
        ///     <![CDATA[
        ///         Northwind.BLL.ProductsBLL bll = new Northwind.BLL.ProductsBLL();
        ///         bll.Save(models);  
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <remarks> 
        /// <para>使用页面：</para>
        /// <para>创建人及日期：zhaoshunlu@163.com 2014-10-21 21:48:52</para>
        /// <para>修改人、日期及内容:</para>
        /// </remarks>
        /// <value>bool</value>
        public bool Save(IList<Northwind.Model.Products> models) {
            if (models == null || models.Count == 0) {
                this.strLastErr = "要保存的对象为null或者数量为0";
                return false;
            }
            using (NorthwindContext _context = new NorthwindContext()) {
                int cnt = 0;//计数器
                for (int i = models.Count - 1; i >= 0; i--) {
                    Northwind.Model.Products mod = models[i];
                    //如果不是新建，而是修改或者删除状态，就要先查找到对象
                    //判断是否新增，最好判断自动编号是否为0                   
                    if ((mod._state == "null" || mod._state == "added")) {
                        _context.Productss.Add(mod);
                        cnt++;
                    } else if (mod._state == "modified") {
                        //直接修改状态
                        _context.Entry(mod).State = EntityState.Modified;
                        //通过复制对象值
                        //DbEntityEntry<Northwind.Model.Products> entity = _context.Entry(_context.Productss.Find(mod.ProductID));
                        //entity.CurrentValues.SetValues(mod);//如果是修改状态就要重新复制对象值
                        cnt++;
                    } else if (mod._state == "removed") {
                        //直接删除
                        //_context.Productss.Remove(mod);
                        //实体实例使用Attach方法
                        _context.Productss.Remove(_context.Productss.Attach(mod));
                        cnt++;
                    }
                    mod._state = "null";//生成静态Json数据时需要重置这个状态值，
                }
                //提交保存
                try {
                    if (cnt > 0) {
                        return _context.SaveChanges() > 0;
                    } else {
                        strLastErr = "没有需要更新的数据";
                        return false;
                    }
                } catch (System.Exception ex) {
                    SetLastError(ex);
                    return false;
                }
            }
        }

        #endregion

        #endregion

        //以下是 你的自定义业务逻辑
        #region 你的自定义业务逻辑
        //
        //
        //
        #endregion
    }
}
