常见问题解答
本页内容
本页包含常见问题及其答案。
提示
如果您在本页找不到解决问题的答案,请参阅问题与帮助页面以获取下一步操作和更多资源。
为什么我在连接到MongoDB时出现错误?
如果您在连接到MongoDB部署时遇到麻烦,请参阅连接故障排除指南以获取可能的解决方案。
.NET/C# 驱动器中的连接池是如何工作的?
每个MongoClient
实例为其MongoDB拓扑中的每个服务器都有一个内置的连接池。连接池根据需要打开套接字以支持多线程应用程序中的并发MongoDB操作。
每个连接池的最大大小由MaxConnectionPoolSize
选项设置,默认为100
。如果连接到服务器的使用中连接数达到MaxConnectionPoolSize
的值,则对该服务器的下一个请求将等待,直到有连接可用。以下图展示了MongoClient
如何管理连接池的高级视图
除了支持应用程序线程所需的套接字之外,每个MongoClient
实例还会在每个MongoDB拓扑中的服务器上打开两个额外的套接字以监控服务器状态。例如,连接到三个节点副本集的客户端会打开六个监控套接字。如果应用程序使用MaxConnectionPoolSize
的默认设置并且仅查询主节点(默认),则最多可以有106
个总连接在使用中。如果应用程序使用读取偏好来查询辅助节点,则这些连接池会增长,并且可以有306
个总连接。
为了在一个进程内支持大量并发的MongoDB线程,您可以增加MaxConnectionPoolSize
。
驱动器有一个等待队列,限制了等待连接的线程数量。等待队列的大小由WaitQueueMultiple
选项决定,默认值为5
。为了计算最大的等待队列大小,驱动器将WaitQueueMultiple
乘以MaxConnectionPoolSize
。如果您使用每个选项的默认值,等待队列的大小将为500
。您也可以通过指定WaitQueueSize
选项来设置等待队列的大小,该选项将覆盖其他设置。但是,我们不建议更改等待队列的大小。
连接池是限流的。由MaxConnecting
设置确定池在任何时候可以并行创建的连接数量。例如,如果MaxConnecting
的值为2
,则第三个尝试并发获取连接的线程只有在以下情况下才能成功
前两个线程中的任何一个完成了连接的创建。
一个现有的连接被检查回池中。
由于连接创建的限流,驱动器重用现有连接的能力得到提高。
您可以使用MinConnectionPoolSize
选项设置每个服务器的最小并发连接数,该选项默认值为0
。连接池将使用此数量的套接字初始化。如果错误导致任何套接字关闭,并且套接字的总数(包括正在使用的和空闲的)低于最小值,则驱动器会打开更多套接字,直到数量达到最小。
您可以使用MaxConnectionIdleTime
选项设置连接在池中保持空闲的最大毫秒数。一旦连接空闲了MaxConnectionIdleTime
,驱动器就会将其删除。此选项默认为10分钟。如果池的大小低于MinConnectionPoolSize
,驱动器将删除并替换空闲连接。
MongoClient
还具有MaxConnectionLifeTime
选项,该选项指定连接在过期之前可以保留在池中的时间长度,默认为30分钟。
以下针对MongoClient
的默认配置适用于大多数应用程序
var client = new MongoClient("<connection string>");
为每个进程创建一个客户端,并重用它进行所有操作。为每个请求创建一个新客户端是常见的错误,这非常低效。
在驱动器中不支持终止MongoClient
。
为什么驱动在服务器选择时抛出超时错误?
每次驱动操作都需要您选择一个满足服务器选择标准的健康服务器。服务器选择标准。如果在服务器选择超时内未选择合适的服务器,则驱动会抛出服务器选择超时异常。异常看起来类似于以下内容
A timeout occurred after 30000ms selecting a server using CompositeServerSelector{ Selectors = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 }, OperationsCountServerSelector }. Client view of cluster state is { ClusterId : "1", Type : "Unknown", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/localhost:27017" }", EndPoint: "Unspecified/localhost:27017", ReasonChanged: "Heartbeat", State: "Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown", HeartbeatException: "<exception details>" }] }.
错误消息由多个部分组成
服务器选择超时(30000 毫秒)。
考虑的服务器选择器(包含
CompositeServerSelector
,其中包含AreSessionsSupportedServerSelector
,LatencyLimitingServerSelector
和OperationsCountServerSelector
)。驱动当前对集群拓扑的视图。驱动已知的服务器列表是此视图的关键部分。每个服务器描述都包含对其当前状态的详尽描述,包括有关端点、服务器版本、服务器类型和其当前健康状态的信息。如果服务器在报告其健康状态时遇到问题,
HeartbeatException
将包含最后一次失败的 heartbeat 异常。分析每个集群节点的HeartbeatException
可以帮助诊断大多数服务器选择问题。以下 heartbeat 异常是常见的无法建立连接,因为目标机器主动拒绝
:驱动程序看不到此集群节点。这可能是由于集群节点已崩溃,防火墙阻止网络流量到达集群节点或端口,或某些其他网络错误阻止流量成功路由到集群节点。尝试读取流末尾之后的内容
:此错误发生在由于网络错误、配置不当的防火墙或其他网络问题导致驱动程序无法连接到集群节点时。要解决此异常,请确保所有集群节点可访问。此错误通常发生在客户端机器的IP地址未配置在Atlas IP访问列表中,该列表位于网络访问选项卡下,用于您的Atlas项目。远程证书根据验证程序无效
:此错误通常指示与TLS/SSL相关的问题,例如过期的/无效的证书或不受信任的根CA。您可以使用类似openssl s_client
的工具来调试TLS/SSL相关的证书问题。
在查询文档时应使用LINQ还是Builder类?
如果您习惯于使用C#编程,请考虑使用LINQ,因为它与原生C#编程的感觉相似。如果您有其他MongoDB驱动程序的使用经验,请考虑使用Builder类,因为它们与其他驱动程序的一致性更高。
我们鼓励您尝试这两种方法,以确定最适合您需求的方法。
为什么某些LINQ或Builder表达式不受支持?
每个LINQ或Builder表达式都必须在查询API中可用。以下原因可能导致此情况
您正在尝试使用.NET/C#功能,但没有等效的MongoDB表示。例如,.NET/C#和MongoDB在排序规则方面具有不同的语义。
该驱动程序不支持将LINQ或Builder表达式转换为MQL(MongoDB查询语言)的特定转换。这种情况可能是因为提供的查询没有MQL转换,或者是因为该功能尚未在驱动程序中实现。
如果您收到“不支持的过滤器 ...
”或“表达式不受支持 ...
”异常消息,请尝试以下步骤
使用MongoDB C# Analyzer分析您的表达式。
尽可能简化您的查询。
将查询作为
BsonDocument
或JSON字符串提供。所有驱动定义类,如FilterDefinition
、ProjectionDefinition
和PipelineDefinition
,都支持从BsonDocument
或JSON字符串进行隐式转换。例如,以下过滤器在查询或聚合中使用时是等价的
FilterDefinition<Entity> typedFilter = Builders<Entity>.Filter.Eq(e => e.A, 1); FilterDefinition<Entity> bsonFilter = new BsonDocument {{ "a", 1 }}; FilterDefinition<Entity> jsonFilter = "{ a : 1 }";
注意
如果您使用BsonDocument
或JSON字符串,则在查询API中不考虑BsonClassMap、BSON序列化属性和序列化约定。字段名必须与服务器存储的名称和大小写匹配。例如,当引用_id
字段时,您必须在BsonDocument
或JSON字符串定义中使用_id
。同样,如果一个文档有一个字段FirstName
被注释为[BsonElement("first_name")]
,您必须在BsonDocument
或JSON字符串定义中将其称为first_name
。
您可以在同一个查询中组合原始和类型化的形式,如下面的代码所示
FilterDefinition<Entity> filter = Builders<Entity>.Filter .And(Builders<Entity>.Filter .Eq(e => e.A, 1), BsonDocument .Parse("{ b : 2 }"));
哪些对象类型可以序列化?
ObjectSerializer
只允许序列化和反序列化被认为是安全的类型。当您构造一个ObjectSerializer
时,您可以传递一个类型为Func<Type, bool>
的委托。此委托接受一个对象类型,并返回一个布尔值,指示该类型是否适合序列化。
在大多数情况下,您应该传入 ObjectSerializer.DefaultAllowedTypes()
代表。此方法返回对许多我们认为安全的一知名框架类型的 true 值。要序列化自定义类型,创建一个布尔表达式,对于您想包含的类型,该表达式计算为 true
。然后,将此表达式添加到您传递给 ObjectSerializer
构造函数的代表的末尾。
在以下示例中,ObjectSerializer
将序列化和反序列化任何由 ObjectSerializer.DefaultAllowedTypes()
允许的类型,或全名以 "MyNamespace"
开头的类型。
var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type) || type.FullName.StartsWith("MyNamespace")); BsonSerializer.RegisterSerializer(objectSerializer);
要允许序列化匿名类型,将布尔表达式 type.FullName.StartsWith("<>f__AnonymousType"))
添加到您的代表中,如下例所示。
var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type) || type.FullName.StartsWith("<>f__AnonymousType")); BsonSerializer.RegisterSerializer(objectSerializer);
您应该在程序开始时创建并注册您的 ObjectSerializer
,在执行任何其他操作之前。
.NET/C# 驱动程序与 MongoDB Entity Framework Core 提供程序之间的区别是什么?
.NET/C# 驱动程序是一个库,它直接公开 MongoDB 功能,并包括具有投影、分组操作和灵活映射的 LINQ 提供程序。该驱动程序包括以下功能:
事务
批量操作
LINQ 查询
直接修改数据库的操作
聚合操作
自定义映射
Entity Framework Core 提供程序 允许您在 .NET/C# 应用程序中使用 Microsoft 的 Entity Framework Core 与 MongoDB。Entity Framework Core 提供程序支持智能对象跟踪、基于实体的 LINQ 操作以及 Entity Framework Core 用户熟悉的建模。该提供程序包括以下功能:
智能对象跟踪
基于实体的 LINQ 操作
使用流畅 API 进行 Entity Framework 建模和映射
通过更改跟踪自动更新数据库