Апсертирование в БД Монго и проблема Id - PullRequest
16 голосов
/ 02 сентября 2011

У меня проблема при переходе на dong монго с использованием официального драйвера C #.

public abstract class AggregateRoot
{
    /// <summary>
    /// All mongoDb documents must have an id, we specify it here
    /// </summary>
    protected AggregateRoot()
    {
        Id = ObjectId.GenerateNewId();
    }

    [BsonId]
    public ObjectId Id { get; set; }
}

У моих сущностей уже есть идентификаторы, но я должен был создать специальный идентификатор монго, чтобы он работал, поскольку у всех документов в коллекции должен быть один. Теперь, когда я получаю новую сущность в моей системе, генерируется новый Mongo Id, и я получаю Монго не может изменить _id документа старого исключения . Есть ли обходной путь?

Позвольте мне немного описать дизайн. Все объекты, которые будут хранятся как документы, наследуемые от AggregateRoot, который имел генерация id в нем. Каждый поддокумент имеет свой идентификатор автоматически и у меня не было проблем с этим. Идентификатор в AggregateRoot была введена для устранения проблемы при получении данных из MongoCollection в список и поколение было введено, так что id-ы разные. Теперь мы можем переместить это поколение идентификаторов, чтобы сохранить методы потому что новая сущность для обновления имела новое поколение идентификаторов. Но это будет означать, что каждый разработчик в команде не должен забывать генерации идентификаторов в хранилище, которое рискованно. Было бы лучше просто игнорировать идентификатор чем отображение из монго, если это возможно и не иметь Класс AggregateRoot вообще

Ответы [ 2 ]

62 голосов
/ 29 ноября 2012

Я столкнулся с подобной проблемой.Я хотел сохранить документы, используя официальный драйвер C #.У меня был такой класс:

public class MyClass
{
    public ObjectId Id { get; set; }
    public int Field1 { get; set; }
    public string Field2 { get; set; }
}

В консоли я бы написал: db.collection.update({Field1: 3},{Field1: 3, Field2: "value"}), и это сработало бы.В C # я написал:

collection.Update(Query.EQ("Field1", 3),
                Update.Replace(new MyClass { Field1 = 3, Field2 = "value" }),
                UpdateFlags.Upsert);

, и это не сработало!Поскольку драйвер включает пустой идентификатор в операторе обновления, и когда я вставляю второй документ с другим значением поля1, возникает исключение E11000 duplicate key error index (в этом случае Mongo пытается вставить документ с _id, который уже существует в БД).

Когда я сам сгенерировал _id (например, начало темы), я столкнулся с тем же исключением (mongo cannot change _id of a document) при добавлении объектов с существующим значением Field1.

Решение состоит в том, чтобы пометить свойство Idпо атрибуту [BsonIgnoreIfDefault] (и не инициализировать его).В этом случае драйвер пропускает поле _id в операторе обновления, а MongoDb генерирует Id, если это необходимо.

8 голосов
/ 02 сентября 2011

Похоже, вы явно устанавливали значение Id для вставок и обновлений.Это хорошо для вставок, все новые объекты нуждаются в значении _id, однако для обновлений вам не разрешено изменять значение _id в существующем документе после его создания.

Попробуйте не устанавливать *Значение 1006 * на всех.Если вы не укажете значение перед вставкой, драйвер использует встроенные классы IdGenerator для генерации нового значения _id, поэтому, если это тип ObjectId, он будет использовать ObjectIdGenerator.Тогда и ваши вставки и обновления работают нормально.

...