Я разрабатываю систему управления запасами с MongoDB.У меня есть следующая структура базы данных:
inventory
└─storage_slots
└─storage_locations
...etc...
Каждый раз, когда добавляется новый Slot
, дерево, представляющее местоположение слота в иерархии, добавляется в коллекцию storage_locations
для представления его местоположения (согласнорасположение, комната, раздел, полка).До сих пор мне удалось успешно добавить новый элемент, где ни одно из полей местоположения уже не используется: (слот также добавлен в коллекцию storage_slots
)
{
"_id" : ObjectId("5c57169f0863d665c7f13d27"),
"CreatedUtc" : {
"$date" : 1549211298017
},
"UpdatedUtc" : {
"$date" : 1549211298017
},
"Description" : null,
"Address" : null,
"StorageRooms" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d28"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageSections" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d29"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageShelves" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d2a"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageSlotIds" : [
ObjectId("5c57169f0863d665c7f13d26")
]
}
]
}
]
}
]
}
Для ясности, storage_locations
вышеупомянутая иерархия, в то время как storage_slots
является просто набором слотов.
Однако, если поля уже присутствуют в иерархии, запускается следующий код: (Я взял вдохновение из this post)
var filter = Builders<StorageLocation>.Filter.And(
Builders<StorageLocation>.Filter.Where(location => location.Id == id),
Builders<StorageLocation>.Filter.Eq("StorageRooms.Id", roomId),
Builders<StorageLocation>.Filter.Eq("StorageRooms.$.StorageSections.Id", sectionId),
Builders<StorageLocation>.Filter.Eq("StorageRooms.$.StorageSections.$.StorageShelves.Id", shelfId));
var update =
Builders<StorageLocation>.Update.Push("StorageRooms.$.StorageSections.$.StorageShelves.$.StorageSlotIds",
storageSlotIds);
return await UpdateAsync(filter, update, cancellationToken);
Кроме того, если определены только некоторые из них, я сделаю смесь из обоих, которые я решил не показывать здесь, поскольку они основаны на одних и тех же принципах и не будут отвечать на вопрос.
Проблема
Всякий раз, когда запускается приведенный выше код.Я получаю следующую ошибку:
InvalidCastException: Unable to cast object of type 'MongoDB.Bson.ObjectId[]' to type 'MongoDB.Bson.ObjectId'.
MongoDB.Bson.Serialization.Serializers.SerializerBase<TValue>.MongoDB.Bson.Serialization.IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
//annoying scrollbar
Ошибка в этой строке:
return await UpdateAsync(filter, update, cancellationToken);
Метод:
public Task<UpdateResult> UpdateAsync(FilterDefinition<T> filter, UpdateDefinition<T> updateDefinition,
string database, string collection, CancellationToken cancellationToken)
{
return _mongoContext.MongoClient.GetDatabase(database).GetCollection<T>(collection)
.UpdateOneAsync(filter, updateDefinition.Set(o => o.UpdatedUtc, DateTime.UtcNow),
cancellationToken: cancellationToken);
}
Дополнительная информация
Вот еще несколько подходящих классов для вопроса:
public class StorageLocation : Dbo
{
public string Description { get; set; }
public Address Address { get; set; }
public IEnumerable<StorageRoom> StorageRooms { get; set; }
}
public class StorageRoom : Dbo
{
public string Description { get; set; }
public IEnumerable<StorageSection> StorageSections { get; set; }
}
public class StorageSection : Dbo
{
public string Description { get; set; }
public IEnumerable<StorageShelf> StorageShelves { get; set; }
}
public class StorageShelf : Dbo
{
public string Description { get; set; }
public IEnumerable<ObjectId> StorageSlotIds { get; set; }
}
public class StorageSlot : Dbo
{
public string Description { get; set; }
public ObjectId LocationId { get; set; }
public ObjectId RoomId { get; set; }
public ObjectId SectionId { get; set; }
public ObjectId ShelfId { get; set; }
...etc...
}