c# - 检测是否将创建/已创建 MongoDb 数据库
问题描述
我们为每个租户使用一个数据库。所以我们的代码如下所示:
var collection = MongoClient.GetDatabase(accountId).GetCollection("mycol");
在这个地方,我们不知道数据库是否已经存在。收藏也一样。
问题:我想创建一个索引。为了能够做到这一点,我需要在创建新数据库或集合时有一些“事件”,所以我知道我必须为它创建索引。
选项:
- 如果有机会获得 GetDatabase() 或 GetCollection() 调用的错误/异常/空值,我可以处理此问题并“准备”数据库/集合。问题:没有错误或任何可以让我检查它是否是新的/不存在的?
- 驱动程序事件:我看到驱动程序中有事件(http://mongodb.github.io/mongo-csharp-driver/2.6/reference/driver_core/events/),但这似乎是错误的地方?
- 更改事件:https : //docs.mongodb.com/manual/changeStreams/ 看起来还不错,有一个 dropDatabase 事件 - 但没有 createDatabase 事件。
- 在插入/更新之前手动检查。这将需要对数据库的额外请求。坏主意……</li>
- ???
有没有办法在创建数据库或集合时获得触发器?
解决方案
MongoDB 与其他类似 RDBMS 的数据库之间的主要区别在于,在 MongoDB 中,数据库和集合是自动创建的。文档说:
如果数据库不存在,MongoDB 会在您首次存储该数据库的数据时创建该数据库
因此,当您尝试访问不存在的数据库时,您不会收到任何错误。此外,C# 驱动程序中没有“DatabaseExists”方法,但您可以创建自己的方法。要检查数据库是否存在,您可以使用db.stats admin 命令返回有关特定数据库的一些重要统计信息。
的示例结果db.stats
可能如下所示:
{
"db" : "databasene2",
"collections" : 0,
"views" : 0,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 0,
"numExtents" : 0,
"indexes" : 0,
"indexSize" : 0,
"fileSize" : 0,
"fsUsedSize" : 0,
"fsTotalSize" : 0,
"ok" : 1
}
null
因此,您可以在 C# 中创建一个扩展方法,如果没有集合和索引,它将返回:
public static IMongoDatabase GetDatabaseIfExists(this IMongoClient client, string databaseName)
{
var database = client.GetDatabase(databaseName);
var command = "{ dbStats: 1, scale: 1 }";
var dbStats = database.RunCommand<BsonDocument>(command);
var databaseExists = dbStats["collections"].AsInt32 > 0 || dbStats["indexes"].AsInt32 > 0;
return databaseExists ? database : null;
}
用法:
var mongoClient = new MongoClient(settings);
var db = mongoClient.GetDatabaseIfExists("dbThatNotExists"); //returns null
同样,您可以利用collStats命令创建另一个方法,在这种情况下,MongoDB C# 驱动程序会抛出MongoCommandException
,尝试:
public static IMongoCollection<T> GetCollectionIfExists<T>(this IMongoDatabase database, string collectionName)
{
var command = $"{{ collStats: \"{collectionName}\", scale: 1 }}";
try
{
database.RunCommand<BsonDocument>(command);
return database.GetCollection<T>(collectionName);
}
catch(MongoCommandException e) when (e.ErrorMessage.EndsWith("not found."))
{
return null;
}
}
显然,您不必每次需要访问数据库时都运行这些方法。您可以运行它们一次,然后将现有数据库名称缓存在内存中并GetDatabase
直接使用。
推荐阅读
- r - 更正代码中创建的函数中参数的意外未替换
- html - 快速提问。JavaScript。我添加了一个带有 createElement 的链接,但它是不可见的
- javascript - Dropzone.js全屏dropzone不工作
- java - 显示下一个对象 OnClickListener Android Studios
- javascript - 关于带小数的数字的奇怪字符串行为
- vb.net - 从本地目录下载文件?
- javascript - 正则表达式删除除@之外的所有非字母数字
- python - 如何在snakemake中处理可变数量的复制
- amazon-web-services - AppConfig 可以用于跨账户部署吗?
- swift - TabBarController:总是跳转到根 NavigationController