• MongoDB结合Flexgrid的简单数据呈现


    本示例以常用的:用户,帖子,评论为基础模型,实现了一个简单的MongoDB结合Flexgrid数据呈现的Demo。由于时间所限,功能上仅提供对MongoDB数据的常用查询操作(分页,排序,查询等)。高手请对我这种菜鸟多些包容。

    一,准备工作:

    MongoDB官方下载:
    http://www.mongodb.org/
    当前最新版本是2.2.0版本。话说,MongoDB的版本更新是相当的快。

     

    本示例使用的MongoDB C#版驱动下载:
    https://github.com/samus/mongodb-csharp
    该驱动附源码和示例程序,有兴趣的朋友可以研究一下,对自己的编码能力会有很大的提高。用VS打开Source文件夹,编译后得到程序集,在自己的项目中引用即可。

     

    这是官方邮件提供的 C#版驱动:
    https://github.com/mongodb/mongo-csharp-driver/downloads
    版本很多,而且基本上都是十多兆的东西,然后,没有然后。

     

    如果你不习惯以命令行的方式对MongoDB进行操作和管理。推荐以下客户端管理工具:
    1,MongoVUE。这应该是目前应用最广的了。
    下载地址:http://www.mongovue.com/

    2,博客园高手自己开发的MongoDB管理工具:
    http://www.cnblogs.com/texteditor/archive/2012/03/31/2427195.html
    试用了一下,也是相当不错的!

     

    虽然上述管理工具能够以图形化的方式与MongoDB交互,但强烈建议你运行mongo.exe客户端,以命令行的方式对MongoDB进行操作和管理,这会让你对MongoDB有更加直观而深刻的体会。另外,Windows8依然内置了DOS。

     

    这里有MongoDB的常用命令:
    http://blog.csdn.net/shirdrn/article/details/7105539

     

    这是Flexgrid的官方网站:
    http://flexigrid.info/
    页面顶部有一个硕大的红色Download按钮。

    TestDriven.net,必不可少的开发和测试工具。本示例需要用它向MongoDB中初始化测试数据。下载地址:

    http://www.testdriven.net/

     

    二,项目结构:

    麻雀虽小,五脏俱全。整个项目结构是一个最原始的三层。直接上图:

    三,技术细节:

    1,MongoDB数据库操作。
    ADO.NET虽然很强大,但我们通常需要自己动手写一个SqlHelper。MongoDB也一样,我们仍有必要在驱动的基础上对常用的数据操作进行封装。下面贴出本鸟写的MongoDB数据库操作类。大多数方法都与数据查询相关。贴出主要代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Configuration;
    using MongoDB;
    using MongoDB.Linq;
    using Mcmurphy.Commons.Enumerations;
    namespace Mcmurphy.DAL
    {
        public class MongoDBHelper
        {
            #region 基本信息
            private static readonly string ConnectionString;
            private static readonly string DatabaseName;
    
            /// <summary>
            /// 当前Mongo引用
            /// </summary>
            private static Mongo mongo;
    
            /// <summary>
            /// 初始化数据库配置
            /// </summary>
            static MongoDBHelper()
            {
                ConnectionString = ConfigurationManager.AppSettings["connString"];
                DatabaseName = ConfigurationManager.AppSettings["currentDB"];
            }
    
            /// <summary>
            /// 当前Mongo对象
            /// </summary>
            private static Mongo CurrentMongo
            {
                get
                {
                    return new Mongo(ConnectionString);
                }
            }
    
            /// <summary>
            /// 当前操作集合
            /// </summary>
            private static IMongoCollection<T> GetCollection<T>() where T:class
            {
                try
                {
                    mongo = CurrentMongo;
                    mongo.Connect();
                    IMongoDatabase db = GetCurrentDataBase();
                    IMongoCollection<T> collection = db.GetCollection<T>();
                    return collection;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            /// <summary>
            /// 获取当前Mongo数据库对象
            /// </summary>
            /// <returns>当前Mongo数据库对象</returns>
            private static IMongoDatabase GetCurrentDataBase()
            {
                return mongo.GetDatabase(DatabaseName);
            }
    
            #endregion
    
            #region 数据查询
    
            /// <summary>
            /// 获取排序规则
            /// </summary>
            private static IndexOrder GetIndexOrder(DataOrder order)
            {
                IndexOrder @orderby = order == DataOrder.Ascending ? 
                    IndexOrder.Ascending : IndexOrder.Descending;
                return orderby;
            }
    
            /// <summary>
            /// 根据条件进行查询,并进行分页
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="selector">条件Lamda表达式</param>
            /// <param name="pageIndex">当前页索引</param>
            /// <param name="pageSize">分页大小</param>
            /// <returns>结果集</returns>
            public static IEnumerable<T> GetBySearch<T>(System.Linq.Expressions.Expression<Func<T, bool>> selector, int pageIndex, int pageSize) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    return currentCollection.Find<T>(selector).Skip((pageIndex - 1) * pageSize).Limit(pageSize).Documents.ToList();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
            }
    
            /// <summary>
            /// 根据条件进行查询,并进行分页和排序
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="selector">条件Lamda表达式</param>
            /// <param name="pageIndex">当前页索引</param>
            /// <param name="pageSize">分页大小</param>
            /// <param name="order">排序规则</param>
            /// <param name="orderField">排序字段</param>
            /// <returns>结果集</returns>
            public static IEnumerable<T> GetBySearch<T>(System.Linq.Expressions.Expression<Func<T, bool>> selector, int pageIndex, int pageSize, DataOrder order, string orderField) where T : class
            {
                try
                {
                    IndexOrder orderby = GetIndexOrder(order);
                    var currentCollection = GetCollection<T>();
                    return currentCollection.Find<T>(selector).Sort(orderField, orderby).Skip((pageIndex - 1) * pageSize).Limit(pageSize).Documents.ToList();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
            }
     
            /// <summary>
            /// 根据条件查询一个对象
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="selector">查询条件Lamda表达式</param>
            /// <returns>查询对象</returns>
            public static T GetOneBySearch<T>(System.Linq.Expressions.Expression<Func<T, bool>> selector) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    return currentCollection.FindOne<T>(selector);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
            }
    
            /// <summary>
            /// 根据查询条件获取总记录数
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="selector">查询条件</param>
            /// <returns>记录数</returns>
            public static long GetTotalCount<T>(System.Linq.Expressions.Expression<Func<T, bool>> selector) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    return currentCollection.Count(selector);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
            }
    
            /// <summary>
            /// 获取总记录数
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <returns>记录数</returns>
            public static long GetTotalCount<T>() where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    return currentCollection.Count();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
            }
    
            #endregion
    
            #region 数据插入
    
            /// <summary>
            /// 数据插入
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="t">要插入的数据对象</param>
            public static void Insert<T>(T t) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    currentCollection.Insert(t);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }                     
            }
    
            #endregion
    
            #region 数据更新
    
            /// <summary>
            /// 根据查询条件更新数据
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="t">待更新的对象</param>
            /// <param name="selector">更新的条件Lamda表达式</param>
            public static void Update<T>(T t, System.Linq.Expressions.Expression<Func<T, bool>> selector) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    currentCollection.Update<T>(t,selector);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
    
            }
    
            /// <summary>
            /// 更新/插入数据(id是否存在)
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="t">待更新的对象</param>
            public static void Update<T>(T t) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    //inserts of updates depends on whether id exists
                    currentCollection.Save(t);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
    
            }
    
            #endregion
    
            #region 数据删除
    
            /// <summary>
            /// 数据删除
            /// </summary>
            /// <typeparam name="T">类型参数</typeparam>
            /// <param name="selector">查询的条件Lamda表达式</param>
            public static void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> selector) where T : class
            {
                try
                {
                    var currentCollection = GetCollection<T>();
                    currentCollection.Remove<T>(selector);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    mongo.Disconnect();
                    mongo.Dispose();
                }
    
            }
            #endregion
        }
    }

    初次调用的时候,会读取在站点项目下Web.Config文件中配置的数据库服务器地址以及数据库名称。

     

    2,Flexgrid加载的数据格式。
    在官网上徘徊了很久也没有找到Flexgrid要求的数据格式说明。还好有Firebug,但遗憾的是官方示例采用的是XML格式。如下:

    <rows>
      <page>1</page>
      <total>234</total>
      <row id='AD'>
        <cell><![CDATA[AD]]></cell>
        ...
      </row>
      ...
    </rows>

    上述XML存在一个问题,就是具体的列并没有id标识。也就是说,在配置Flexgrid的时候,你必须了解服务器返回的数据字段的顺序。否则就会出现“标题列显示回复数”的情况。在数据格式为Json的时候,也会出现同样的状况。理想情况下,官方应该给出的XML数据格式如下:

    <rows>
      <page>1</page>
      <total>234</total>
      <row id='AD'>
        <cell id='name'><![CDATA[AD]]></cell>
        ...
      </row>
      ...
    </rows>

    对于本示例采用的Json,经测试,完整的数据格式如下:

    {
      "page":当前页,
      "total":总记录数,
      "rows":[
        {
          "id":当前行编号,
          "cell":{
            "username":"mcmurphy",
            "password":"mcmurphy",
            ...
          }
        }
        ...
      ]
    }

    Flexgrid官方文档的欠缺和一个无意的疏忽,相信一定误导了不少人,也导致本鸟走了不少弯路。

    对于服务器向客户端输出Json,使用了Newtonsoft.Json这个第三方组件,有兴趣的朋友可以百度一下。
    当然,在System.Web.Script.Serialization命名空间下,有一个JavaScriptSerializer类,也可以对Json进行序列化与反序列化的操作。

     

    3,LINQ的动态组合查询。

    LINQ虽然给我们提供了很多方便,但在多条件组合查询方面,显然没有传统的拼接SQL来得直观和爽快。网上流传的很多解决方案,代码一坨一坨的,看了都头痛,而且基本都是抄来抄去。后来找到杨过前辈的一篇,比较有参考价值:

    http://www.cnblogs.com/yjmyzz/archive/2008/03/25/1122135.html

    主要借助了老外写的一个扩展表达式,代码如下:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Mcmurphy.DAL
    {
        /// <summary>
        /// 老外写的,非常厉害
        /// </summary>
        public static class PredicateExtensions
        {
            public static Expression<Func<T, bool>> True<T>() { return f => true; }
    
            public static Expression<Func<T, bool>> False<T>() { return f => false; }
    
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1,
                    Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
    
                return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression),
                   expression1.Parameters);
            }
    
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,
                    Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
    
                return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body,
                  invokedExpression), expression1.Parameters);
            }
        }
    }

    上述代码主要是进行逻辑运算的四个方法,代码很短,但我们不得不佩服老外的功力。
    关于老外的这个扩展表达式,还有前辈写过一篇讲解:

    http://www.cnblogs.com/whitewolf/archive/2010/08/02/1790390.html

     

    四,最终运行

    有图有真相:

     

    本文主要是做一个梳理和记录。示例中用到的很多技术都比较简单,当然也有很多不足之处,这对一个菜鸟来说在所难免。希望路过的高手给予最严厉的批评和指正。放心,你只要不能直接干掉我,都只会让我更加坚强。 (^o^)

    下面流出源码种子(运行前请读一下:读我.txt):源码种子

  • 相关阅读:
    sql server 查询最近备份记录
    如何手动卸载 SQL Server
    Microsoft SQL Server 2012 Versions
    SQLNET and TCP Keepalive Settings
    SQLSERVER的备份信息查询
    How to get the DDL for indexes using dbms_metadata
    用于确定 SQL Server recovery何时完成的脚本
    SQLSERVER备份命令总结
    SQL Server 备份和还原的如何使网络驱动器
    这工具,这翻译,看来软件还是不够智能啊
  • 原文地址:https://www.cnblogs.com/mcmurphy/p/2694428.html
Copyright © 2020-2023  润新知