上周六,写了第一篇博客《按日期+6位顺序号生成订单编号(主要处理并发的情况)的方案,之前有客户要这样生成订单编号,我只能回复实现不了,因为当时只知道,每次获取最大的订单编号,处理不了并发的情况,惭愧。

  关于这个标题,我还是交代下背景吧。这个问题从2010年第一次实现时,就觉得当时那种方案太差了,自己都看不去,只因没有别的办法,从那以后,每每得空,就拿出来琢磨下,现在这个方案也许还有不少问题,也希望各位指点下。我们是做订餐系统的,主要实体就是商家(有坐标)和用户(有坐标)。所以就有这么个需求,返回距离N公里内的商家,按距离从近到远排序。先看下,数据库设计吧,如图(1):

                         订餐系统之按距离[根据经纬度]排序、搜索

                                                                                              图(1)

   下面我先介绍下这几个表的关系吧:

    ETogo :商家表,dataid表示商家编号,togoname表示商家名称。

    ETogoLocalInfo:商家定位表,togoid对应etogo.dataid,lat表示商家纬度,lng表示商家经度(经纬度在地图上标注所得)

        EAddress :用户地址表,保存用户的经纬度,lat表示用户纬度,lng表示用户经度(经纬度在地图上标注所得)

   生活的经验告诉我们:一条成功的路,背后总有数不完的错误的路。下面我把那些曾经错误的路也写下来,以作对比。

2010年方案

   当时年少,对sql基本只会简单的select,更多的东西依赖于应用程序,于是有了下面的代码,由于对第二页的处理不了,所以用了方法:getDistancetogoid获取前N页的id然后再处理,里面关于距离的语句每次同事用到都抱怨,如果再加的N公里内的,这个语句就麻烦了。

        /// <summary>
        /// 获取列表,返回距离排序(出现商家重复的现象目前不采用)
        /// </summary>
        /// <param name="pagesize">每页大小</param>
        /// <param name="pageindex">当前页数</param>
        /// <param name="strWhere">搜索条件</param>
        /// <param name="orderName">排序字段</param>
        /// <param name="orderType">排序类型</param>
        /// <param name="mylat">用户纬度</param>
        /// <param name="mylng">用户经度</param>
        /// <returns></returns>
        public IList<TogoInfo> GetDistanceList(int pagesize, int pageindex, string strWhere, string orderName, int orderType, string mylat, string mylng)
        {
            IList<TogoInfo> infos = new List<TogoInfo>();
            string ids = "";
            if (pageindex > 1)
            {
                ids = getDistancetogoid(pagesize, pageindex, strWhere, orderName, orderType, mylat, mylng);
                if (ids == "")
                {
                    return infos;
                }
            }
            SqlParameter[] parameters = 
            {
                new SqlParameter("@tblName", SqlDbType.VarChar,255),
                new SqlParameter("@strGetFields", SqlDbType.VarChar,2000),
                new SqlParameter("@primary", SqlDbType.VarChar,255),
                new SqlParameter("@orderName", SqlDbType.VarChar,255),
                new SqlParameter("@PageSize", SqlDbType.Int),
                new SqlParameter("@PageIndex", SqlDbType.Int),
                new SqlParameter("@OrderType", SqlDbType.Bit),
                new SqlParameter("@strWhere", SqlDbType.VarChar,4500),
                new SqlParameter("@ids", SqlDbType.VarChar,2000)
            };
            string orderstr = orderType > 0 ? "desc" : "asc";
            parameters[0].Value = "etogo";
            string field = "*, (select Lat from ETogoLocalInfo where togoid = etogo.dataid) as lat ,(select lng from ETogoLocalInfo where togoid = etogo.dataid) as lng, (select lastlogindate from ETogoPrinter where ETogoPrinter.togoid =  etogo.dataid ) lastlogindate,(select (Case when DateDiff(mi,LastLoginDate,getdate()) < 5 then 1 else 0 end) from etogoprinter where ETogoPrinter.togoid =  etogo.dataid)  as online";
            field += ",(( 6371 * acos( cos( radians(" + mylat + ") ) * cos( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) )) * cos( radians( (select lng from ETogoLocalInfo where togoid = etogo.dataid) ) - radians(" + mylng + ") ) + sin( radians(" + mylat + ") ) * sin( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) ) ) ) )) as Distance ";
            field += " ,CASE WHEN( ( CONVERT(varchar(12) , Time1Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time1End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") or  ( CONVERT(varchar(12) , Time2Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time2End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") )THEN 1 ELSE 0 END AS havenew ";

            parameters[1].Value = field;
            parameters[2].Value = "DataID";
            parameters[3].Value = orderName;
            parameters[4].Value = pagesize;
            parameters[5].Value = pageindex;
            parameters[6].Value = orderType;
            parameters[7].Value = strWhere;
            parameters[8].Value = ids;
            using (SqlDataReader dr = SQLHelper.ExecuteReader(CommandType.StoredProcedure, "pageselectpri_togo", parameters))
            {
                while (dr.Read())
                {
                    TogoInfo info = new TogoInfo();
                    info.DataID = HJConvert.ToInt32(dr["DataID"]);
                    info.Picture = HJConvert.ToString(dr["Picture"]);
                    info.TogoName = HJConvert.ToString(dr["TogoName"]);
                    int isonline = HJConvert.ToInt32(dr["havenew"]);

                    if (togostatus == 1 && isonline == 1)
                    {
                        info.Status = 1;
                    }
                    else
                    {
                        info.Status = 0;
                    }
                    string _distance = HJConvert.ToString(dr["Distance"]);

                    if (mylat == "0" || _distance == "")
                    {
                        info.mydistance = "0";
                    }
                    else
                    {
                        info.mydistance = Convert.ToString(Convert.ToInt32(Convert.ToDecimal(_distance) * 1000));
                    }

                    info.Lat = HJConvert.ToString(dr["Lat"]);
                    if (info.Lat == "")
                    {
                        info.Lat = "0";
                    }
                    info.Lng = HJConvert.ToString(dr["Lng"]);
                    if (info.Lng == "")
                    {
                        info.Lng = "0";
                    }

                    infos.Add(info);
                }
            }
            return infos;
        }

        /// <summary>
        /// 获取所有商家的名称和对应的编号
        /// </summary>
        /// <param name="pagesize">每页大小</param>
        /// <param name="pageindex">当前页数</param>
        /// <param name="strWhere">搜索条件</param>
        /// <param name="orderName">排序字段</param>
        /// <param name="orderType">排序类型</param>
        /// <param name="mylat">用户纬度</param>
        /// <param name="mylng">用户经度</param>
        public string getDistancetogoid(int pagesize, int pageindex, string sqlwhere, string sortname, int ordertype, string mylat, string mylng)
        {
            string ids = "";
            string orderstr = ordertype > 0 ? "desc" : "asc";
            int top = (pageindex - 1) * pagesize;
            string field = "select top " + top + " dataid";
            field += ",(( 6371 * acos( cos( radians(" + mylat + ") ) * cos( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) )) * cos( radians( (select lng from ETogoLocalInfo where togoid = etogo.dataid) ) - radians(" + mylng + ") ) + sin( radians(" + mylat + ") ) * sin( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) ) ) ) )) as Distance ";
            field += " from etogo where " + sqlwhere + " order by " + sortname + " " + orderstr + " , dataid desc";
            using (SqlDataReader dr = SQLHelper.ExecuteReader(CommandType.Text, field, null))
            {
                while (dr.Read())
                {
                    ids += dr["dataid"] + ",";
                }
            }
            ids = System.Text.RegularExpressions.Regex.Replace(ids, @",$", "");
            return ids;
        }
dal层代码

相关文章: