快速掌握mongoDB(四)—— C#驱动MongoDB用法演示
前边我们已经使用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:, name: "张三", age: ,level:, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]},
{_id:, name: "李四", age: ,level:, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]},
{_id:, name: "王五", age: ,level:, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]},
{_id:, name: "赵六", age: ,level:, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] },
{_id:, name: "田七", age: , ename: { firstname: "qi", lastname: "tian"}, address:'北京' },
{_id:, name: "周八", age: ,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", },
{ "name", "吴九" },
{ "age", },
{ "ename", new BsonDocument
{
{ "firstname", "jiu" },
{ "lastname", "wu" }
}
}
};
//InsertOne()添加单条docment
collection.InsertOne(doc);
}
}
执行完成后,查看在RoboMongo中查询,看到已经添加成功了:
我们也可以是用 collection.InsertMany(IEnumerable<BsonDocument> docs) 来批量添加docment,这里就不再演示了。
2 查询(Find,Filter,Sort,Projection)
1.简单查询(Find、Filter)
栗子:查找name=“吴九"的记录
//Fileter用于过滤,如查询name = 吴九的第一条记录
var filter = Builders<BsonDocument>.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<age<28的记录
var filter = Builders<BsonDocument>.Filter;
var docs = collection.Find(filter.Gt("age", ) & filter.Lt("age", )).ToList();
docs.ForEach(d => Console.WriteLine(d));
查询结果如下:
3 OR查询
栗子:查询年龄小于25或年龄大于28的记录
//查询age<25或age>28的记录
var filter = Builders<BsonDocument>.Filter;
var docs = collection.Find(filter.Lt("age", ) | filter.Gt("age", )).ToList();
docs.ForEach(d => Console.WriteLine(d));
查询结果如下:
4 字段存在(Exists)
栗子:查询包含address字段的所有记录
//查询存在address字段的记录
var filter = Builders<BsonDocument>.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",))//过滤
.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", ))//过滤
.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", ));
//查询张三的记录
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",), 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", ));
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岁的记录
.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岁的记录
.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<T>实例,然后就可以使用Linq对这个IMongoQueryable<T>进行查询了。
使用过EF的小伙伴应该都了解IQueryable+Linq的查询默认不是将整个结果集立即加载到内存中,而是延迟加载的,即只有使用结果时(如 在执行First,Last,Single,Count,ToList等)才会将Linq转换成Sql,在数据库中执行查询操作。类似的,在使用IMongoQueryable<T>+Linq进行查询时默认也是延迟加载的,在需要使用查询结果时,驱动会将Linq转换成聚合管道命令(aggregation pipeline),如Linq中的Where被转换成$watch,Join转换为$lookup,Skip和Take转换为$skip和$limit等等,然后在Mongodb中执行这些管道命令获取结果,看一个栗子我们就会轻松地掌握了。
首先添加一些测试数据:
//添加学生数据
db.students.insertMany([
{"no":, "stuName":"jack", "age":, "classNo":},
{"no":, "stuName":"tom", "age":, "classNo":},
{"no":, "stuName":"hanmeimei", "age":, "classNo":},
{"no":, "stuName":"lilei", "age":, "classNo":}
]) //添加班级数据
db.classxes.insertMany([
{"no" : ,"clsName" : "A班"},
{"no" : ,"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>("classxes");
//查找年龄大于22的学生
Console.WriteLine("-------------查找年龄大于22的学生列表--------------");
//1.query语法
List<Student> stuList1 = (from stu in stuCollection.AsQueryable()
where stu.age >
select stu).ToList();
//2.点语法
List<Student> stuList2 = stuCollection.AsQueryable().Where(s => s.age > ).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功能,这里就不再过多介绍了,有兴趣的小伙伴可以看看官方的文档。如果文中有错误的话,希望大家可以指出,我会及时修改,谢谢。
快速掌握mongoDB(四)—— C#驱动MongoDB用法演示的更多相关文章
- [译] MongoDB Java异步驱动快速指南
导读 mongodb-java-driver是mongodb的Java驱动项目. 本文是对MongoDB-java-driver官方文档 MongoDB Async Driver Quick Tour ...
- MongoDB快速入门学习笔记8 MongoDB的java驱动操作
import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.bson.D ...
- CRL快速开发框架系列教程十二(MongoDB支持)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Mongodb快速入门之使用Java操作Mongodb
[IT168 专稿]在上一篇文章中,我们学习了Mongodb的安装和初步使用,在本文中,将学习如何使用Java去编程实现对Mongodb的操作. HelloWorld程序 学习任何程序的第一步,都是编 ...
- MongoDB的Java驱动使用整理 (转)
MongoDB Java Driver 简单操作 一.Java驱动一致性 MongoDB的Java驱动是线程安全的,对于一般的应用,只要一个Mongo实例即可,Mongo有个内置的连接池(池大小默认为 ...
- mongodb原生node驱动
写在前面 最近读<node.js学习指南>,对于mongodb没有介绍太多的工作原理,但是对于一个前端开发者,即使你还没有用过这种数据库也可以让你很好的理解和使用 一本非常好的 ...
- 适用于app.config与web.config的ConfigUtil读写工具类 基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类) 基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD) C# 实现AOP 的几种常见方式
适用于app.config与web.config的ConfigUtil读写工具类 之前文章:<两种读写配置文件的方案(app.config与web.config通用)>,现在重新整理一 ...
- .net Core MongoDB用法演示
C#驱动MongoDB的本质是将C#的操作代码转换为mongo shell,驱动的API也比较简单明了,方法名和js shell的方法名基本都保持一致,熟悉mongo shell后学习MongoDB的 ...
- Mongodb的Samus驱动
最近开始学习Mongodb方面的东西.. 看到有很多博主都说MongoDB的第三方驱动 Samus 对Linq的支持比较好..能够降低学习的成本..所以就想从这里开始.. 但是弊端在我学习了一半的时候 ...
随机推荐
- 无法删除 NTFS 盘上的文件或文件夹(对Windows文件的各种情况有比较详细的描述)
简介 本文介绍您可能无法删除 NTFS 文件系统卷上的文件或文件夹的原因,以及如何分析造成此问题的不同原因从而解决此问题. 更多信息 注意:在内部,NTFS 将文件夹作为特殊类型的文件进行处理.因此, ...
- 零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」
原文:零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」 本系列将教大家以实做案例认识Blend 4 的布局容器,此章介绍的是Blend 4 里的 ...
- 使用SpringMVC框架解决中文乱码的问题
spring Web MVC框架提供了org.springframework.web.filter.CharacterEncodingFilter用于解决POST方式造成的中文乱码 问题. 需要在we ...
- Spring Cloud Ribbon配置详解
概述 有时候需要自定义Ribbon的配置和客户端超时配置. 自动化配置 /* 使用属性自定义功能区客户端 从版本1.2.0开始,Spring Cloud Netflix现在支持使用属性与Ribbon文 ...
- 一次项目代码重构-使用spring容器干掉条件判断
一次项目代码重构-使用spring容器干掉条件判断 这是在一次公司项目中进行重构时,一些复杂业务时想到的一个去掉一些if else的办法.能够使代码逻辑更加清晰,减少一些业务上的耦合. 业务说明 我所 ...
- docker系列(五):网络通信
1 引言 之前的几篇docker系列博客说的都是单个容器或者镜像的操作.但容器,作为一种简化的操作系统,又怎能不与机器或者容器相互协同工作呢,这就需要用到容器的网络功能.docker中提供了多种不同的 ...
- 短视频技术详解:Android端的短视频开发技术
在 <如何快速实现移动端短视频功能?>中,我们主要介绍了当前短视频的大热趋势以及开发一个短视频应用所涉及到的功能和业务.在本篇文章中,我们主要谈一谈短视频在Android端上的具体实现技术 ...
- 补习系列(21)-SpringBoot初始化之7招式
目录 背景 1. @PostConstruct 注解 2. InitializingBean 接口 3. @Bean initMethod方法 4. 构造器注入 5. ApplicationListe ...
- 动手写一个简单版的谷歌TPU-指令集
系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...
- 【设计模式】结构型05组合模式(Composite Pattern)
组合模式(Composite Pattern) 意图:将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决:它在我们 ...