检测是否将创建/创建MongoDb数据库

时间:2018-12-06 17:08:37

标签: 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事件。
  • 在插入/更新之前手动检查。这将需要对数据库的附加请求。好主意...
  • ???

创建数据库或集合时,是否有任何方法来获取触发器?

1 个答案:

答案 0 :(得分:1)

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
}

因此,您可以在C#中创建扩展方法,如果没有集合和索引,该方法将返回null

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