При работе с реляционными базами данных многие уже наверняка сталкивались с понятием ORM. К счастью, организовать взаимодействие между приложением и базой данных на подобном уровне возможно и для некоторых NoSQL решений.
Безусловно, в отличие от обычных ORM технологий для NoSQL ещё нет такой степени универсальности и автоматизации разработки, но тем не менее отображение данных из NoSQL хранилища на объекты языка программирования очень существенно облегчает жизнь.
Рассмотрим как это работает в случае связки MongoDB и C#.
Создадим простой класс, который описывает сотрудника компании.
1 2 3 4 5 6 |
class Worker { public int TabNo { get; set; } public string FIO { get; set; } public string Position { get; set; } } |
Инициализируем три его экземпляра:
1 2 3 |
_worker1 = new Worker { TabNo = 1, FIO = "Иванов Иван Иванович", Position = "Директор" }; _worker2 = new Worker { TabNo = 2, FIO = "Петрова Анна Борисовна", Position = "Секретарь" }; _worker3 = new Worker { TabNo = 3, FIO = "Сидоров Пётр Петрович", Position = "Менеджер" }; |
Подключаемся к MongoDB:
1 2 3 4 5 6 |
private MongoClient _client; private IMongoDatabase _database; . . . string connectionString = "mongodb://localhost:27017"; _client = new MongoClient(connectionString); _database = _client.GetDatabase("test"); |
Далее нам необходимо получить коллекцию документов. Но, с BSON, как предлагается в документации мы работать не будем. Вместо этого мы получим коллекцию документов — объектов класса Worker.
1 2 3 |
IMongoCollection _col; . . . _col = _database.GetCollection("workers"); |
Таким образом мы формируем сопоставление (mapping) между документами в MongoDB и классом Worker.
Поочередно добавим созданные нами объекты класса Worker в коллекцию workers MongoDB:
1 2 3 |
_col.InsertOne(_worker1); _col.InsertOne(_worker2); _col.InsertOne(_worker3); |
Проверяем результат в консольном клиенте (mongo.exe).
Все наши объекты были добавлены в коллекцию.
Обратите внимание. Мы ни разу не формировали BSON, а работали только с «обычными» объектами C#.
Но, у подобного подхода есть один недостаток.
Как видно на скриншоте MongoDB при добавлении документа в коллекцию создаёт поле «_id», которое служит ключом. В классе Worker его нет.
При операции добавления это роли не играет, так как новый ключ будет сформирован только когда данные будут переданы в MongoDB. Но, в случае выборки данных, их обновления или удаления это спровоцирует фатальную ошибку.
Поэтому перед тем, как выбрать документы добавим в класс Worker соответствующее поле.
1 2 3 4 5 6 7 8 9 |
using MongoDB.Bson; . . . class Worker { public ObjectId _id { get; set; } public int TabNo { get; set; } public string FIO { get; set; } public string Position { get; set; } } |
Теперь наш класс полностью совместим с MongoDB.
Попробуем получить из базы данных записи со значениями TabNo меньше 10 в виде списка.
1 2 |
FilterDefinition filter = Builders.Filter.Lt("TabNo", 10); List workers= _col.Find(filter).ToList(); |
И здесь мы снова имеем дело только с объектами C#.
То же самое при обновлении уже существующего документа или его удалении.
1 2 3 4 5 6 7 |
// Обновление документа FilterDefinition filter = Builders.Filter.Eq("TabNo", 3); UpdateDefinition update = Builders.Update.Set("Position", "Старший менеджер"); _col.UpdateOne(filter,update); // Удаление документа FilterDefinition filter = Builders.Filter.Eq("TabNo", 2); _col.DeleteOne(filter); |
Таким образом, при работе с MongoDB мы можем почти полностью отказаться от BSON и вместо него оперировать объектами C#. Это не только удобно, но и открывает новые возможности. В частности можно использовать в сочетании с MongoDB многие паттерны, которые хорошо зарекомендовали себя , но изначально были разработаны для реляционных СУБД (например, «Репозиторий»).
Однако, не всё так гладко. К сожалению, есть и «ложка дёгтя».
Как это ни прискорбно, в MongoDB имена объектов базы данных регистрозависимые. Поэтому Id и id будут восприниматься как два разных поля.
Так как, MongoDB не накладывает никаких ограничений на документы в коллекциях, проверка на его стороне не предусмотрена. Так, что если между структурами документа и объекта C# будут обнаружены отличия, возникнет фатальная ошибка.
Все эти нюансы нужно обязательно учитывать при проектировании и реализации приложения.
Добавить комментарий