用WPF+MongoDB开发房产信息收集器(3)——MongoDB入门

距离上一篇文字过去已经很久了。一方面是工作有点忙,另外也是遇到点问题,到现在也没有解决。这个问题我会在文章的结尾在提出来,现在先进入这篇文章的主题吧——MongoDB入门。

由于我完全是一个彻彻底底的初学者,所以写的都只是非常非常粗浅的入门内容,各位看官不要鄙视~~~~

  • 数据库安装
    数据库的安装,网上到处都是,我也是Google的,就不哆嗦,这里上个链接吧。MongoDB 安装与启动
    另外,对于初学者来说,我觉得直接用命令行是最好的学习数据库命令的途径。但毕竟比较累。这里也推荐两个GUI的MongoDB数据库管理工具。
    1. MongoVUE 这是老外开发的一个工具。
    2. MagicMongoDBTool 这是原子里的magicDict开发的。各位可以去膜拜下~哈哈。作者已经开源了项目,有兴趣的朋友可以下载源代码自己瞅瞅。

  • 数据库连接
    在连接数据库之前,我们首先需要确定我们要用的MongoDB Driver,Driver其实有很多,但我都没有接触过,也是初学,就从官方的Driver开始吧。下载编译之后应该有两个dll文件,分别是MongoDB.Bson.dll和MongoDB.Driver.dll。
    下面是我数据库连接的代码:
    ///<summary>
    /// 连接数据库
    ///</summary>
    ///<param name="info"></param>
    public static void Connect(DbInfo info)
    {
    DbHelper.info = info;
    if (info.DbType == DbType.MongoDB)
    {
    MongoServerSettings mss = new MongoServerSettings();
    mss.ConnectionMode = ConnectionMode.Direct; // 数据库连接模式
    //mss.ConnectionMode = ConnectionMode.ReplicaSet; // 这个是针对数据库集的(多个数据库地址)
    mss.ConnectTimeout = new TimeSpan(0, 0, 20); // 超时时间 20s
    mss.Server = new MongoServerAddress(info.Source, info.Port); // 数据库
    // mss.Servers是针对数据库集的

    //mss.DefaultCredentials = new MongoCredentials(info.Uid, info.Pwd, true);
    MongoServer ms = new MongoServer(mss);
    MongoDatabaseSettings mds = new MongoDatabaseSettings(ms, info.DbName);

    ms.Connect();
    db = new MongoDatabase(ms, mds); // 保存MongoDatabase信息,以便后续调用
    }
    }
    这样连接数据库就OK了。

  • Mapping
    连接好了数据库,就需要将自己定义的类和数据进行映射了。Driver里面(MongoDB.Bson.dll)已经提供了相应的映射方法:
    BsonClassMap.RegisterClassMap<T>(cm =>
    {
    cm.AutoMap();
    });
    另外在Mapping的时候也可以直接设置id以及id生成的方法:
    BsonClassMap.RegisterClassMap<T>(cm =>
    {
    cm.AutoMap();
    cm.SetIdMember(cm.GetMemberMap(c => c.ID));
    cm.IdMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance);
    });
    如果不在映射的时候设置,也可以在定义类时为相应的ID字段添加BsonId的属性:
    [BsonId(IdGenerator = typeof(StringObjectIdGenerator))]
    public virtual string ID { get; set; }
    通过属性,也可以设置属性不映射到数据库,那样在读写数据库的时候,该属性就会被忽略掉:
    [BsonIgnore]
    public string FavImage {get; set;}
  • 增删改查数据库
    接下去我们就可以通过Driver读写数据库了。
    在获取数据之前,我们需要获取对应类映射的Collection:
    DbHelper.db.GetCollection<T>(name);   // name表示T映射的Collection名称
    GetCollection这个方法必须指定name参数。其实这里我觉得之前在映射的时候应该已经确定了T对应的Collection的名称,为什么这里的name必须要指定呢?还是说有其他方法我不知道的?
    MongoDB的读数据是Find命令。在Driver中也都是Find/FindAll方法。
    GetCollection<T>().FindAll();
    在实际应用在,我们一般都是会有查询条件,以及排序条件的。
    MongoDB的查询条件是IMongoQuery,排序条件是IMongoSortBy。
    GetCollection<T>().Find(query).SetSortOrder(sortBy);
    同时你也可以利用SetSkip和SetLimit来进行分页:
    GetCollection<T>().Find(query).SetSortOrder(sortBy).SetSkip(skip).SetLimit(limit);
    下面的是我根据标签获取对应数据的方法,根据更新时间排序,还没有处理分页的功能:
    ///<summary>
    /// 获取标签对应的数据
    ///</summary>
    ///<param name="ht"></param>
    ///<returns></returns>
    public static List<HouseInfo> Find(HouseTag ht)
    {
    QueryComplete query = null;
    if (ht != null)
    {
    query = Query.And(
    Query.GTE(HouseTag.PNameArea, ht.AreaMin),
    Query.LTE(HouseTag.PNameArea, ht.AreaMax),
    Query.GTE(HouseTag.PNamePrice, ht.PriceMin),
    Query.LTE(HouseTag.PNamePrice, ht.PriceMax),
    Query.GTE(HouseTag.PNamePriceTotal, ht.PriceTotalMin),
    Query.LTE(HouseTag.PNamePriceTotal, ht.PriceTotalMax),
    Query.GTE(HouseTag.PNameYear, ht.YearMin),
    Query.LTE(HouseTag.PNameYear, ht.YearMax)
    );
    if (!string.IsNullOrEmpty(ht.Zone))
    {
    MongoDB.Bson.BsonRegularExpression reg = new MongoDB.Bson.BsonRegularExpression(string.Format("*{0}*", ht.Zone));
    query = Query.And(query, Query.Matches(HouseTag.PNameZone, reg));
    }
    }
    return MongoHelper.FindAll<HouseInfo>(query, SortBy.Descending("UpdateTime")).ToList();
    }
    获取了数据之后,接下去就是保存数据了,保存(新增和修改)数据相对简单一点,直接用Save就好了,而且,我这里也没有处理变化的数据,每次保存都是整个对象进行了更新(就效率而言,肯定不合适,但就编程而言,那是方便不只一点点啊):
    ///<summary>
    /// 更新数据集合
    ///</summary>
    ///<typeparam name="T"></typeparam>
    ///<param name="listEntity"></param>
    public static void Save<T>(IEnumerable<IMongoEntity> listEntity)
    where T : class, IMongoEntity
    {
    if (listEntity != null)
    {
    MongoCollection<T> col = GetCollection<T>();
    foreach (IMongoEntity entity in listEntity)
    {
    col.Save(entity);
    }
    }
    }
    删除数据相对更新有个差别是需要根据对应获取条件(IMongoQuery):
    ///<summary>
    // 删除数据集合
    ///</summary>
    ///<typeparam name="T"></typeparam>
    ///<param name="listEntity"></param>
    public static void Remove<T>(IEnumerable<IMongoEntity> listEntity)
    where T : class, IMongoEntity
    {
    if (listEntity != null)
    {
    MongoCollection<T> col = GetCollection<T>();
    foreach (IMongoEntity entity in listEntity)
    {
    col.Remove(Query.EQ("ID", entity.ID));
    }
    }
    }

在最后说明下我在文章开头的时候提到的之前遇到的问题。

是这样的,我觉得这个房产信息采集器的目标用户主要是些关注房产交易信息的朋友,而这些人总不能都指望他们是IT出身,或者希望他们可以非常顺利的自己安装部署MongoDB吧。所以我就想是否可以在程序运行的时候自己去判断是否有MongoDB的服务,是否已经启动了MongoDB数据库。如果没有服务的话,创建一个服务;如果没有启动的话,就启动相应的服务。总之只要打开房产信息采集器,不需要再做其他的就直接可以用了。可是笔者尝试了n久,没能实现创建MongoDB服务的功能。

我的想法是在发布的时候将MongoDB的相应目录也一起放在程序的根目录。然后在没有相应服务的时候,启动相应的命令行自动创建MongoDB的服务,并启动。

所以这里有两个问题:

  1. 自动创建MongoDB的服务。
  2. 自动运行MongoDB的服务。

这两个问题,当然也可以引申为创建并启动服务(包括其他任何服务)。

不知道各位有没有什么建议或已经实现的方法?如果有的话,评论、私信都欢迎啊。最好能有现成的代码。哈哈。

posted @ 2011-11-13 12:25  随风逝去(叶进)  阅读(4627)  评论(0编辑  收藏  举报
Free Web Counter
Free Web Counter