快速掌握mongoDB(四)—— C#驱动MongoDB用法演示

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: 快速掌握mongoDB(四)—— C#驱动MongoDB用法演示阅读目录0.准备测试数据1 添加(InsertOne,InsertMany)2 查询(Find,Filter,Sort,Projection)1.

快速掌握mongoDB(四)—— C#驱动MongoDB用法演示
阅读目录

0.准备测试数据

1 添加(InsertOne,InsertMany)

2 查询(Find,Filter,Sort,Projection)

1.简单查询(Find、Filter)
2.AND查询
3 OR查询
4 字段存在(Exists)
4 排序(Sort)
5 查询指定字段(Projection)
3 修改(UpdateOne,UpdateMany)

1 修改单条记录(UpdateOne)
2 修改多条记录(UpdateMany)
4 删除(DeleteOne和DeleteMany)

1 删除单条记录(DeleteOne)
2 删除多条记录(DeleteMany)
5 类型映射

1 简单栗子
2 常用属性
3 MongoDB使用Linq查询

  前边我们已经使用mongo shell进行增删查改和聚合操作,这一篇简单介绍如何使用C#驱动MongoDB。C#驱动MongoDB的本质是将C#的操作代码转换为mongo shell,驱动的API也比较简单明了,方法名和js shell的方法名基本都保持一致,熟悉mongo shell后学习MongoDB的C#驱动是十分轻松的,直接看几个栗子吧。

回到顶部
0.准备测试数据
  使用js shell添加一些测试数据,如下:

复制代码
use myDb
db.userinfos.insertMany([
{_id:1, name: "张三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]},
{_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]},
{_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]},
{_id:4, name: "赵六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] },
{_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京' },
{_id:6, name: "周八", age: 28,roles:["gen"], address:'上海' }
])
复制代码
回到顶部
1 添加(InsertOne,InsertMany)
  首先创建一个Console应用程序,使用命令 Install-Package MongoDB.Driver 添加C#的驱动包,然后就可以使用C#操作MongoDB数据库了,看一个添加的栗子:

复制代码
class Program

{
    static void Main(string[] args)
    {
        //连接数据库
        var client = new MongoClient("mongodb://192.168.70.131:27017");
        //获取database
        var mydb = client.GetDatabase("myDb");
        //获取collection
        var collection = mydb.GetCollection<BsonDocument>("userinfos");
        //待添加的document
        var doc = new BsonDocument{
            { "_id",7 },
            { "name", "吴九" },
            { "age", 29 },
            { "ename", new BsonDocument
                {
                    { "firstname", "jiu" },
                    { "lastname", "wu" }
                }
            }
        };
        //InsertOne()添加单条docment
        collection.InsertOne(doc);
    }
}

复制代码
  执行完成后,查看在RoboMongo中查询,看到已经添加成功了:

  

我们也可以是用 collection.InsertMany(IEnumerable docs) 来批量添加docment,这里就不再演示了。

回到顶部
2 查询(Find,Filter,Sort,Projection)
1.简单查询(Find、Filter)
  栗子:查找name=“吴九"的记录

//Fileter用于过滤,如查询name = 吴九的第一条记录
var filter = Builders.Filter;
//Find(filter)进行查询
var doc = collection.Find(filter.Eq("name","吴九")).FirstOrDefault();
Console.WriteLine(doc);
  查询结果如下:

  如果我们想查询所有的记录,可以设置过滤器为空,代码为: var docs = collection.Find(filter.Empty).ToList();

2.AND查询
 栗子:查询年龄大于25且小于28的记录

//查询25  var filter = Builders.Filter;
  var docs = collection.Find(filter.Gt("age", 25) & filter.Lt("age", 28)).ToList();
  docs.ForEach(d => Console.WriteLine(d));
   查询结果如下:

3 OR查询
  栗子:查询年龄小于25或年龄大于28的记录

//查询age<25或age>28的记录
  var filter = Builders.Filter;
  var docs = collection.Find(filter.Lt("age", 25) | filter.Gt("age", 28)).ToList();
  docs.ForEach(d => Console.WriteLine(d));
  查询结果如下:

4 字段存在(Exists)
  栗子:查询包含address字段的所有记录

//查询存在address字段的记录
  var filter = Builders.Filter;
  var docs = collection.Find(filter.Exists("address")).ToList();
  docs.ForEach(d => Console.WriteLine(d));
  查询结果如下:

4 排序(Sort)
  栗子:查询年龄小于26岁的记录,并按年龄倒序排列

//查询age<26的记录,按年龄倒序排列

var filter = Builders<BsonDocument>.Filter;
var sort = Builders<BsonDocument>.Sort;
var docs = collection.Find(filter.Lt("age",26))//过滤
                     .Sort(sort.Descending("age")).ToList();//按age倒序
docs.ForEach(d => Console.WriteLine(d));

  查询结果如下:

5 查询指定字段(Projection)
  MongoDB查询会默认返回_id字段,如果要不返回_id字段可以使用Exclude("_id")将其排除。栗子:查询年龄小于26岁记录的name和age

复制代码
//查询age<26的记录

var project = Builders<BsonDocument>.Projection;
var filter = Builders<BsonDocument>.Filter;
var docs = collection.Find(filter.Lt("age", 26))//过滤
                     .Project(project.Include("name")//包含name
                                     .Include("age")//包含age
                                     .Exclude("_id")//不包含_id
                           ).ToList();

docs.ForEach(d => Console.WriteLine(d))
复制代码
  查询结果:

回到顶部
3 修改(UpdateOne,UpdateMany)
1 修改单条记录(UpdateOne)
  修改符合过滤条件的第一条记录,栗子:将张三的年龄改成18岁

复制代码

        var filter = Builders<BsonDocument>.Filter;
        var update = Builders<BsonDocument>.Update;
        var project = Builders<BsonDocument>.Projection;
        //将张三的年龄改成18
        collection.UpdateOne(filter.Eq("name", "张三"), update.Set("age", 18));
        //查询张三的记录
        var doc = collection.Find(filter.Eq("name", "张三"))
                            .Project(project.Include("age").Include("name"))
                            .FirstOrDefault();
        Console.WriteLine(doc);

复制代码
  执行结果:

2 修改多条记录(UpdateMany)
  UpdateMany会修改所有符合过滤条件的记录,栗子:将所有年龄小于25的记录标记为young(如果没有mark字段会自动添加)

复制代码

        var filter = Builders<BsonDocument>.Filter;
        var update = Builders<BsonDocument>.Update;
        var project = Builders<BsonDocument>.Projection;
        //将所有年龄小于25的记录标记为young(如果没有mark字段会自动添加)
        UpdateResult reulst=collection.UpdateMany(filter.Lt("age",25), update.Set("mark", "young"));
        if (reulst.IsModifiedCountAvailable)
        {
            Console.WriteLine($"符合条件的有{reulst.MatchedCount}条记录");
            Console.WriteLine($"一共修改了{reulst.ModifiedCount}条记录");
           //查询修改后的记录
            var docs = collection.Find(filter.Empty)
                            .Project(project.Include("age").Include("name").Include("mark"))
                            .ToList();
            docs.ForEach(d => Console.WriteLine(d));
        }
        else
        {
            Console.WriteLine("无修改操作!");
        }

复制代码
  查询结果如下,可以看到age<25的记录的mark字段值为young:

回到顶部
4 删除(DeleteOne和DeleteMany)
  删除操作比较简单,DeleteOne用于删除符合过滤条件的第一条记录,DeleteMany用于删除所有符合过滤条件的记录。

1 删除单条记录(DeleteOne)
  栗子:删除名字为张三的记录

复制代码

        var filter = Builders<BsonDocument>.Filter;
        var project = Builders<BsonDocument>.Projection;
        //删除名字为张三的记录
        collection.DeleteOne(filter.Eq("name", "张三"));
        var docs = collection.Find(filter.Empty)
                        .Project(project.Include("age").Include("name").Include("mark"))
                        .ToList();
        docs.ForEach(d => Console.WriteLine(d));

复制代码
  执行结果如下,我们看到张三的记录已经被删除了:

2 删除多条记录(DeleteMany)
  栗子:删除所有年龄大于25岁的记录

复制代码

        var filter = Builders<BsonDocument>.Filter;
        var project = Builders<BsonDocument>.Projection;
        //删除age>25的记录
        DeleteResult result= collection.DeleteMany(filter.Gt("age", 25));
        Console.WriteLine($"一共删除了{result.DeletedCount}条记录");
        var docs = collection.Find(filter.Empty)
                        .Project(project.Include("age").Include("name").Include("mark"))
                        .ToList();
        docs.ForEach(d => Console.WriteLine(d));

复制代码
  执行结果如下,所有年龄大于25岁的记录都被删除了:

回到顶部
5 类型映射
1 简单栗子
 有时候我们要让查询的结果映射到我们的实体类中去,实现这个需求也十分简单,mongoDB支持自动映射,直接使用泛型即可,看一个栗子:

复制代码

class Program
{
    static void Main(string[] args)
    {
        //连接数据库
        var client = new MongoClient("mongodb://192.168.70.133:27017");
        //获取database
        var mydb = client.GetDatabase("myDb");
        //获取collection
        var collection = mydb.GetCollection<Userinfo>("userinfos");
        var filter = Builders<Userinfo>.Filter;
        var sort = Builders<Userinfo>.Sort;
        List<Userinfo> userinfos = collection.Find(filter.Lt("age", 25))    //查询年龄小于25岁的记录
                                             .Sort(sort.Descending("age"))  //按年龄进行倒序
                                     .ToList();
        //遍历结果
        userinfos.ForEach(u => Console.WriteLine($"姓名:{u.name},年龄:{u.age},英文名:{u.ename.firstname} {u.ename.lastname}"));
        Console.ReadKey();
    }
}
/// <summary>
/// 用户类
/// </summary>
public class Userinfo
{
    public int _id { get; set; }//id
    public string name { get; set; }//姓名
    public int age { get; set; }//年龄
    public int level { get; set; }//等级
    public Ename ename { get; set; }//英文名
    public string[] roles { get; set; }//角色
    public string address { get; set; }//地址
}
/// <summary>
/// 英文名
/// </summary>
public class Ename
{
    public string firstname { get; set; }
    public string lastname { get; set; }
}

复制代码
执行结果如下:

2 常用属性
  上边的栗子仅仅用了基本的自动化映射,使用基本的自动化映射时:类和Bson中的字段必须严格一致(_id除外,可以自动映射到_id/id/Id),且Bson中的每一个字段在实体类中都必须有一个对应的字段,不然就会抛出异常,这就造成我们可能要写一个非常庞大的实体类,而且类中的字段命名也要严格和Bson中的字段一致。这些限制对我们开发来说是不能接受的,这里我们采用mongoDriver中的一些属性改进一下上边的代码,如下:

复制代码

class Program
{
    static void Main(string[] args)
    {//连接数据库
        var client = new MongoClient("mongodb://192.168.70.133:27017");
        //获取database
        var mydb = client.GetDatabase("myDb");
        //获取collection
        var collection = mydb.GetCollection<Userinfo>("userinfos");

        var filter = Builders<Userinfo>.Filter;
        var sort = Builders<Userinfo>.Sort;
        List<Userinfo> userinfos = collection.Find(filter.Lt("age", 25))    //查询年龄小于25岁的记录
                                             .Sort(sort.Descending("age"))  //按年龄进行倒序
                                     .ToList();
        //遍历结果
        userinfos.ForEach(u =>
        {   
            Console.WriteLine($"编号:{u.userId},姓名:{u.name},年龄:{u.age},英文名:{u.ename?.ming} {u.ename?.xing},性别:{u.gender}");
            Console.WriteLine($"其他属性:{u.otherprops}");
            Console.WriteLine();
        });
        
        Console.ReadKey();
    }
}
/// <summary>
/// 用户类
/// </summary
//[BsonIgnoreExtraElements]
public class Userinfo
{
    [BsonId]
    public int userId { get; set; }//id
    public string name { get; set; }//姓名
    public int age { get; set; }//年龄
    public Ename ename { get; set; }//英文名
    [BsonDefaultValue('男')]
    public char gender { get; set; }
    [BsonIgnore]
    public string nickname { get; set; }//昵称
    [BsonExtraElements]
    public BsonDocument otherprops { get; set; }//其他属性
}
/// <summary>
/// 英文名
/// </summary>
public class Ename
{
    [BsonElement("firstname")]
    public string ming { get; set; }
    [BsonElement("lastname")]
    public string xing { get; set; }
}

复制代码
  执行结果如下:

这里用到了几个常用的属性,作用如下:

  BsonId修饰的字段对应BsonDocument中的_id;

  BsonDefaultValue(value)用于指定默认值;

  BsonIgnore表示不映射,即使BsonDocument中包含该字段也不会赋值给属性;

  BsonExtraElements修饰的字段用于存储没有映射到类中的其他属性;

  BsonElement可以指定修饰的属性映射到BsonDocument中的哪个字段,

还有一些其他的属性,具体可以参考官方文档。

3 MongoDB使用Linq查询
  MongoDB的驱动支持Linq查询,用法十分简单,引用 usingMongoDB.Driver.Linq; 后,使用 collection.AsQueryable() 获取IMongoQueryable实例,然后就可以使用Linq对这个IMongoQueryable进行查询了。

  使用过EF的小伙伴应该都了解IQueryable+Linq的查询默认不是将整个结果集立即加载到内存中,而是延迟加载的,即只有使用结果时(如 在执行First,Last,Single,Count,ToList等)才会将Linq转换成Sql,在数据库中执行查询操作。类似的,在使用IMongoQueryable+Linq进行查询时默认也是延迟加载的,在需要使用查询结果时,驱动会将Linq转换成聚合管道命令(aggregation pipeline),如Linq中的Where被转换成$watch,Join转换为$lookup,Skip和Take转换为$skip和$limit等等,然后在Mongodb中执行这些管道命令获取结果,看一个栗子我们就会轻松地掌握了。

  首先添加一些测试数据:

复制代码
//添加学生数据
db.students.insertMany([

{"no":1, "stuName":"jack", "age":23, "classNo":1},
{"no":2, "stuName":"tom", "age":20, "classNo":2},
{"no":3, "stuName":"hanmeimei", "age":22, "classNo":1},
{"no":4, "stuName":"lilei", "age":24, "classNo":2}
])
    

//添加班级数据
db.classxes.insertMany([

{"no" : 1,"clsName" : "A班"},
{"no" : 2,"clsName" : "B班"}
])

复制代码
  这里查找了两组数据:①基本查询:查找年龄大于22岁的学生;②连接查询:查询各个学生的学号、姓名、班级名。栗子比较简单,直接看代码吧

复制代码

    static void Main(string[] args)
    {
        //连接数据库
        var client = new MongoClient("mongodb://192.168.70.133:27017");
        //获取database
        var mydb = client.GetDatabase("myDb");
        //获取collection
        var stuCollection = mydb.GetCollection<Student>("students");
        var clsCollection = mydb.GetCollection<Classx>("classes");
        //查找年龄大于22的学生
        Console.WriteLine("-------------查找年龄大于22的学生列表--------------");
        //1.query语法
        List<Student> stuList1 = (from stu in stuCollection.AsQueryable()
                    where stu.age > 22
                    select stu).ToList();
        //2.点语法
        List<Student> stuList2 = stuCollection.AsQueryable().Where(s => s.age > 22).ToList();
        stuList1.ForEach(stu => Console.WriteLine($"姓名:{stu?.stuName},  年龄:{stu?.age}"));
        Console.WriteLine();
        //表连接查询,查询各个学生的班级名
        Console.WriteLine("-------------表连接,查询学生的班级名----------------");
        //1.query语法
        var result1 = from stu in stuCollection.AsQueryable()
                      join cls in clsCollection.AsQueryable()
                        on stu.classNo equals cls.no
                      select new { stuno = stu.no, stu.stuName, cls.clsName };
        //2.点语法
        var result2 = stuCollection.AsQueryable().Join(
                        clsCollection.AsQueryable(),
                        stu => stu.classNo,
                        cls => cls.no,
                        (stu, cls) => new { stuno=stu.no, stu.stuName, cls.clsName }
                     );
        //遍历结果
        foreach (var item in result1)
        {
            Console.WriteLine($"学号:{item.stuno}, 姓名:{item.stuName}, 班级:{item.clsName}");
        }

        Console.ReadKey();
    }
}
/// <summary>
/// 学生类
/// </summary
public class Student
{
    public int no { get; set; }//学号
    public string stuName { get; set; }//姓名
    public int age { get; set; }//年龄
    public int classNo { get; set; }//班级编号
    [BsonExtraElements]
    public BsonDocument others { get; set; }
}
/// <summary>
/// 班级类
/// </summary>
public class Classx
{
    public int no { get; set; }//班级编号
    public string clsName { get; set; }//班级名
    [BsonExtraElements]
    public BsonDocument others { get; set; }
}

复制代码
 执行结果如下:

 

小结

  本篇简单介绍了C#驱动mongoDB进行CRUD操作,C#驱动功能十分丰富,几乎实现了所有的Mongo shell功能,这里就不再过多介绍了,有兴趣的小伙伴可以看看官方的文档。如果文中有错误的话,希望大家可以指出,我会及时修改,谢谢。

作者:捞月亮的猴子
    
出处:https://www.cnblogs.com/wyy1234/

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
11天前
|
安全 C#
C# List基本用法
C# List基本用法
|
1月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法
|
1月前
|
C#
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
|
1月前
|
C#
C#学习相关系列之多线程---TaskCompletionSource用法(八)
C#学习相关系列之多线程---TaskCompletionSource用法(八)
|
1月前
|
Java C#
C#学习系列相关之多线程(五)----线程池ThreadPool用法
C#学习系列相关之多线程(五)----线程池ThreadPool用法
|
3月前
|
开发框架 .NET 编译器
C# 9.0中的静态匿名函数:引入static关键字的新用法
【1月更文挑战第15天】C# 9.0为匿名函数带来了一个新的修饰符static,允许开发者明确指定匿名函数不会捕获其包含作用域中的任何变量。这一特性增强了代码的性能和可读性,同时减少了因不小心捕获变量而导致的潜在错误。本文将详细探讨C# 9.0中静态匿名函数的语法、使用场景以及它们如何影响代码的性能和安全性。
|
9月前
|
C# 数据库
C# DataGridView用法(—)代码绑定数据源
C# DataGridView用法(—)代码绑定数据源
385 1
|
1月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---where和select用法(二)
C#学习相关系列之Linq用法---where和select用法(二)
|
1月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---group和join相关用法(三)
C#学习相关系列之Linq用法---group和join相关用法(三)
|
1月前
|
存储 开发框架 .NET
C#学习相关系列之数据类型---Diactionary字典的用法
C#学习相关系列之数据类型---Diactionary字典的用法