• 第二节 为什么用MongoDB及.NET开发入门


    第二节 为什么用MongoDB及.NET开发入门

    本节问题:

    • 为什么要用MongoDB
    • MongoDB for .net驱动选择
    • MongoDB for VS插件介绍
    • Demo介绍   

     一、为什么要用MongoDB

      为什么要用MongoDB取代传统关系型数据库?其实不是取代,只是对传统数据库的文档型补充。不是所有的数据都需要二维关系及多表对应的存储和查询,比如:文件的海量存储,只需Key与Value形式的存储及查询,同时这种方式的存储及查询都是高效的,可查看GirdFS,GirdFS是MongoDB的大文件存储系统,比如图片、音频、视频;数据如果不需要实时分析统计(包含读写比高的),也可以使用KV形式存储及查询。MongoDB介于缓存与数据库之间,存取速度逊于缓存但远远高于传统数据库。数据库存储以键值形式,你可能会认为对数据关系的处理及分析挖掘不及传统数据库,理论上是如此,但是MongoDB加入了对LINQ的支持,相信可以弥补其不足之处。做项目要求稳,对于MongoDB的使用我们只是对传统数据库的一个类似二级缓存的补充,cache缓存及Memcached做为一级缓存,MongoDB做为二级缓存对海量大数据的一个缓冲查询,最终才是数据库及物理文件的存储。如果你对数据的分析挖掘统计不是实时的,也可以尝试使用MongoDB直接存取数据,数据后期处理工作可通过MongoDB同步到传统数据库。(以上纯属个人理解)

          用MongoDB做海量存储,又出现另一个问题读写频率与扩展?MongoDB可以根据应用程序的需要以两种模式来运行。第一种是“单主”(single master)模式,只有一台主服务器来处理所有的写操作。读操作能从中分离出去,通过任意数量的从服务器来进行读操作,这有利于提高读的可扩展性(使用场景:Sourceforge)。对于那些写数据量很大或写频率过高,单台主服务器无法处理的应用程序,可以使用MongoDB的自动分片模式。该模式下写操作会自动分配到任意数量的“片”中(一般是一台或一组MongoDB服务器),它们负责这部分数据集的写和读。无论使用哪种模式,MongoDB都会采取“强一致性”方法(你可以把MongoDB看成CAP理论中的C-P系统)。高可用性是通过将数据复制到多个MongoDB节点来实现的,每个节点都能及时成为一个分片的主服务器——MongoDB会自动处理故障转移。这能让你在维持相当高的写可用性的同时,拥有强一致性特性,这对一些用例来说非常重要。而MongoDB的分片支持复制和故障切换:Mongo数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。MongoDB的自动分片模块 ("mongos"). 自动分片可以用于构建一个大规模的可扩展的数据库集群,这个集群可以并入动态增加的机器。(说细可参照此官方文档

    二、MongoDB for .net驱动选择

    驱动源码地址:https://github.com/mongodb/mongo-csharp-driver/downloads(第一章提到的)

    项目应用:

    第一款:mongodb-csharp 项目地址:http://github.com/samus/mongodb-csharp  应用很广泛,更新速度也比较快,也加入了对LINQ的支持 

    第二款:simple-mongodb 项目地址:http://code.google.com/p/simple-mongodb   以JSON为核心

    第三款:NoRM 项目地址:http://github.com/atheken/NoRM  加入了对强类型的支持,是对一的补充

    其它的也有,就不介绍了,经过综合比较选择了方案一,也就是第一章介绍的。方案一应该广泛用于项目了,并且保持较快的更新速度,同时也加了LINQ的支持,对于项目求稳的朋友是最好的选择,所以我也选择了方案一samus驱动,下载的是(samus-mongodb-csharp-0.90.0.1.zip)下载选Tar.Zip包含源码。另外一个包只有DLL。后面的文章中将一直使用samus开发包。

    三、MongoDB for VS插件介绍

    插件下载地址:http://www.cnblogs.com/ILoveSilence/archive/2010/08/10/mongowidget_1.html (园子里人做的)

    插件和VS的数据源功能类似,想使用的就去看这篇博文吧。

    四、Demo介绍

    下载samus开发包后,你会发现里面已经有了samples了,那就开始我们的入门之路了

    这Demo都不写了,直接拿来分析了

    留意的朋友会发现,MongoDB的连接字符串是IP+端口,与传统的数据库引擎不同,包括数据的CURD操作都是键值方式,是不是有点像Memcached。

    View Code
    using System;
    using System.Configuration;
    using System.Linq;
    using MongoDB;
    using MongoDB.Configuration;
    using MongoDB.Linq;

    namespace Simple
    {
    /// <summary>
    /// Illustrates some simple operations on the database.
    /// Creating a database connection.
    /// Remove some documents.
    /// Insert some documents
    /// Find one document
    /// Find several documents and iterate through them.
    /// </summary>
    internal class MainClass
    {
    private IMongoCollection<Document> categories;
    private Mongo mongo;
    private IMongoDatabase simple;

    private class MyClass
    {
    public string Name { get; set; }
    public int Corners { get; set; }
    }

    private class SubClass : MyClass
    {
    public double Ratio { get; set; }
    }

    public static void Main(string[] args)
    {
    #region 以下为被屏蔽源码部分,我们先从SetUp方法开始
    //var config = new MongoConfigurationBuilder();
    //// COMMENT OUT FROM HERE
    //config.Mapping(mapping =>
    //{
    // mapping.DefaultProfile(profile =>
    // {
    // profile.SubClassesAre(t => t.IsSubclassOf(typeof(MyClass)));
    // });
    // mapping.Map<MyClass>();
    // mapping.Map<SubClass>();
    //});
    //// TO HERE

    //config.ConnectionString("Server=127.0.0.1");

    //using (Mongo mongo = new Mongo(config.BuildConfiguration()))
    //{
    // mongo.Connect();
    // try
    // {
    // var db = mongo.GetDatabase("TestDb");
    // var collection = db.GetCollection<MyClass>();

    // MyClass square = new MyClass()
    // {
    // Corners = 4,
    // Name = "Square"
    // };

    // MyClass circle = new MyClass()
    // {
    // Corners = 0,
    // Name = "Circle"
    // };

    // SubClass sub = new SubClass()
    // {
    // Name = "SubClass",
    // Corners = 6,
    // Ratio = 3.43
    // };

    // collection.Save(square);
    // collection.Save(circle);
    // collection.Save(sub);

    // var superclass = (from item in db.GetCollection<MyClass>("MyClass").Linq()
    // where item.Corners > 1
    // select item.Corners).ToList();

    // var subclass = (from item in db.GetCollection<SubClass>("MyClass").Linq()
    // where item.Ratio > 1
    // select item.Corners).ToList();

    // Console.WriteLine("Count by LINQ on typed collection: {0}", collection.Linq().Count(x => x.Corners > 1));
    // Console.WriteLine("Count by LINQ on typed collection2: {0}", db.GetCollection<SubClass>().Linq().Count(x => x.Corners > 1));
    // //Console.WriteLine("Count by LINQ on typed collection3: {0}", db.GetCollection<SubClass>().Count(new { Corners = Op.GreaterThan(1) }));
    // Console.WriteLine("Count on typed collection: {0}", collection.Count(new { Corners = Op.GreaterThan(1) }));

    // var coll = db.GetCollection("MyClass");
    // var count = coll.Count(new Document("Corners", Op.GreaterThan(1)));
    // Console.WriteLine("Count: {0}", count);
    // Console.ReadKey();
    // }
    // finally
    // {
    // mongo.Disconnect();
    // }
    //}
    #endregion

    var main
    = new MainClass();
    main.Setup();
    main.Run();

    Console.ReadLine();
    }

    /// <summary>
    /// Setup the collection and insert some data into it.
    /// </summary>
    public void Setup()
    {
    //从配置文件读取连接字符串 IP+端口
    var connstr = ConfigurationManager.AppSettings["simple"];
    if(String.IsNullOrEmpty(connstr))
    throw new ArgumentNullException("Connection string not found.");
    //创建Mongo数据服务及连接
    mongo = new Mongo(connstr);
    mongo.Connect();

    //获取数据库实例(如果该实例不存,就会自动创建simple实例)
    simple = mongo["simple"];
    //获取表名(如果该表名不存在,就会自动创建categories表名)
    categories = simple.GetCollection<Document>("categories");
    //添加记录前清除所有记录
    Clean();

    var names
    = new[] {"Bluez", "Jazz", "Classical", "Rock", "Oldies", "Heavy Metal"};
    //循环插入记录 doucment会自动生成键值_id,id的编码体现了数据的插入顺序
    foreach(var name in names)
    categories.Insert(
    new Document {{"name", name}});
    }

    public void Clean()
    {
    //删除document name 为Jazz的记录
    categories.Remove(new Document {{"name", "Jazz"}}); //remove documents with the name Jazz.
    //删除所有记录集
    categories.Remove(new Document()); //remove everything from the categories collection.
    }

    public void Run()
    {
    //查找单条记录 参数类型为Document
    var category = categories.FindOne(new Document {{"name", "Bluez"}});
    Console.WriteLine(
    "The id findOne" + category["_id"]);

    //更新1 用键值ID读取对象,并更新字段值,保存
    var selector = new Document {{"_id", category["_id"]}};
    category[
    "name"] = "Bluess";
    //The following will do the same thing.
    categories.Save(category);
    Console.WriteLine(
    "Category after one update " + categories.FindOne(selector));
    //更新2 Update参数1去更新参数2并保存
    category["name"] = "Blues";
    categories.Update(category, selector);
    Console.WriteLine(
    "Category after two updates " + categories.FindOne(selector));

    //Find it by _id that has been converted to a string now.
    var id = (category["_id"]).ToString();
    //注意: 这里id.ToString()与id.ToOid() (为什么类扩展这个方法,我也没明白,是不是id!=24 位会出现转义字符要替换掉)
    Console.WriteLine(string.Format("Found by string id[{0}] converted back to Oid[{1}]",id.ToString(),id.ToOid()));
    Console.WriteLine(categories.FindOne(
    new Document {{"_id", id.ToOid()}}));

    //Find(new Document()) is equivalent to FindAll();
    //Specifying the cursor in a using block will close it on the server if we decide not
    //to iterate through the whole thing.
    Console.WriteLine("输出所有对象.........");
    using(var all = categories.Find(new Document()))
    {
    foreach(var doc in all.Documents)
    Console.WriteLine(doc.ToString());
    }

    mongo.Disconnect();
    }
    }
    }

    //类扩展ToOid方法到string中
    public static class OidExtensions
    {
    public static Oid ToOid(this string str)
    {
    if(str.Length == 24)
    return new Oid(str);

    return new Oid(str.Replace("\"", ""));
    }
    }

    以上为MongoDB的数据库连接及CRUD操作(Document方式),我们来测试一下,数据库实例,表,记录是否创建成功了呢?

    打开上一章提到的Bin文件夹下的Mongo.exe程序 按图示输入命令查看

    入门Demo就演示到这里了,有点简单,我也在是一边学习一边分享。Demo就不提供下载了,都在samus里面,只是我这边加了注释。

    分类: MongoDB
    2
    0
    (请您对文章做出评价)
  • 相关阅读:
    RDA安装
    关闭SELinux
    Linux下开启关闭防火墙
    长事务管理
    增加复制表
    Python使用property函数定义的属性名与其他实例变量重名会怎么样?
    Python使用property函数定义属性访问方法如果不定义fget会怎么样?
    Python使用property函数和使用@property装饰器定义属性访问方法的异同点分析
    第8.18节 Python类中内置析构方法__del__
    Python中的列表解析和列表推导是一回事吗?
  • 原文地址:https://www.cnblogs.com/dajiang02/p/2079353.html
Copyright © 2020-2023  润新知