MongoDb.Driver IMongoDatabase.GetCollectionNamesAsync() Исключение
Я подключаюсь к MongoDB, используя C# MongoDB.Driver
библиотека. Какой-то код, который работает
MongoClient client = MongoClientBuilder.Build(
"77.199.99.90", 27016, "admin", "pwd");
IReadOnlyList<string> dbNames = this.client.GetDatabaseNamesAsync().Result;
foreach (var dbn in dbNames)
{
IMongoDatabase mongoDb = client.GetDatabase(dbn);
var cNames = mongoDb.GetCollectionNamesAsync().Result; <- THIS THROWS AggregateException.
foreach (var cn in cNames)
{
...
}
}
Таким образом, учетные данные верны, и я получаю IMongoDatabase
Это просто прекрасно, однако, когда я пытаюсь получить коллекции в базе данных, я получаю AggregateException
когда я делаю mongoDb.GetCollectionNamesAsync().Result
, детали исключения
AggregateException InnerException (count 1) MongoQueryException: флаг QueryFailure был истинным (ответ был { "$err": "не авторизован для запроса на taurusEvents.system.namespaces", "code": 13 }).
Я не уверен, что говорит мне это исключение. Аутентификация на клиенте в порядке, но я могу запросить базу данных. Что мне здесь не хватает?
Редактировать. Теперь я понимаю, что мне нужно было использовать учетные данные, чтобы сделать это, однако, делая
public static MongoClient Build(string host, int port,
string username, string password, string authDb)
{
MongoCredential cred = MongoCredential.CreateMongoCRCredential(authDb, username, password);
MongoClientSettings settings = new MongoClientSettings()
{
Credentials = new[] { cred },
Server = new MongoServerAddress(host, port)
};
return new MongoClient(settings);
}
где я сейчас предоставляю свое имя базы данных аутентификации authDb
также бросает то же самое внутреннее исключение выше.
Изменить #2. Я обнаружил, что если я сделаю
var o = database.GetCollection<BsonDocument>("events");
с явной ссылкой на имя коллекции, это работает, я получаю свою коллекцию. Но я хочу список доступных коллекций, почему GetCollectionNamesAsync()
не работает?
Edit # 3. Я создаю свои роли сервера, используя:
1. Создайте пользователя-администратора:
use admin
db.createUser({user: "admin", pwd: "*******", roles: [{role: "userAdminAnyDatabase", db: "admin"}]})
2. Создайте других пользователей, например:
use admin
db.createUser({user: "mel", pwd: "*******", roles: [{role: "readWrite", db: "taurusEvents"}, {role: "readWrite", db: "taurusOdds"}, {role: "readWrite", db: "taurusState"}]})
Спасибо за ваше время.
2 ответа
Вы получаете AggregateException из-за того, как.Result работает в.NET.
var result = task.Result; // throws an AggregateException if the task faulted
Чтобы ваш код выдал внутреннее исключение, используйте либо:
var result = task.GetAwaiter().GetResult(); // throws the inner exception if the task faulted
var result = await task; // also throws the inner exception if the task faulted
Я подозреваю, что причина того, что вы получаете это исключение, заключается в том, что, пока вы используете действительные учетные данные (если бы вы не потерпели неудачу раньше), пользователь, которого вы аутентифицируете, не имеет разрешения на чтение базы данных taurusEvents.
GetCollection и GetCollectionNamesAsync различаются.
GetCollection просто создает объект на стороне клиента, который представляет коллекцию. На самом деле он не общается с сервером (поэтому проверка подлинности никогда не будет проблемой).
GetCollectionNamesAsync обращается к серверу, чтобы получить имена всех коллекций для данной базы данных. Для этого необходимо, чтобы имя пользователя, с которым вы прошли аутентификацию, имело как минимум разрешение на чтение в этой базе данных.