MongoDB: проблема с дочерним классом с переопределенным идентификатором и атрибутом - PullRequest
2 голосов
/ 16 апреля 2019

У меня большие проблемы при переопределении свойства Id в производном классе в моей настройке хранилища MongoDB.

Базовый класс, который наследуют все мои модели данных, выглядит следующим образом:

public abstract class DataModel
{
     [BsonId]
     [BsonRepresentation(BsonType.ObjectId)]
     public virtual string Id { get; set; }

     public DateTime Created { get; set; }

     public DateTime Modified { get; set; }

     public DateTime Deleted { get; set; }
}

Тогда есть несколько конкретных дочерних моделей данных, которые используют upserts . Это требует от меня аннотирования переопределенного свойства Id с [BsonIgnoreIfDefault] согласно этому ответу :

public class ChildDataModel : DataModel
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonIgnoreIfDefault]          //  <---- need this for Upserts to work
    public override string Id { get; set; }

    ... // child-specific properties
}

Но, к сожалению, это приводит к этой ошибке:

Свойство 'Id' типа Namespace.ChildDataModel не может используйте имя элемента _id, потому что оно уже используется свойством «Идентификатор» типа «Namespace.DataModel».

Я пытался зарегистрировать карты классов, добавить дискриминатор типов с RootClass = true в базовую модель, а также определить мои дочерние модели данных в базовом классе с помощью специального атрибута [BsonKnownTypes(typeof(ChildDataModel), ...)], но безрезультатно.

Что я здесь не так делаю?

1 Ответ

2 голосов
/ 16 апреля 2019

Драйвер MongoDB по соглашению пытается отобразить все свойства с именем Id в _id в карте классов.Поскольку у вас есть два класса, он регистрирует _id дважды.Более того, BsonIgnoreIfDefault будет работать нормально, если Id было null, но здесь это не так, поскольку драйвер автоматически сгенерирует значение при вставке нового документа.

Чтобы исправить это, вы можете использовать BsonIgnoreесли вы хотите, чтобы один _id в MongoDB

public class ChildDataModel : DataModel
{        
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonIgnore]
    public override string Id { get; set; }
}

был сохранен как:

{
    "_id" : ObjectId("5cb5fe72e2a22b3848b6a1f6"),
    "Created" : ISODate("2019-04-16T16:10:25.908Z"),
    "Modified" : ISODate("2019-04-16T16:10:25.914Z"),
    "Deleted" : ISODate("2019-04-16T16:10:25.914Z")
}

, или вы можете использовать атрибут BsonNoId, если хотите сохранить два значенияотдельно:

[BsonNoId]
public class ChildDataModel : DataModel
{        
    [BsonRepresentation(BsonType.ObjectId)]
    public override string Id { get; set; }
}

будет:

{
    "_id" : ObjectId("5cb5fecde2a22b3088ef731c"),
    "Created" : ISODate("2019-04-16T16:11:56.810Z"),
    "Modified" : ISODate("2019-04-16T16:11:56.822Z"),
    "Deleted" : ISODate("2019-04-16T16:11:56.822Z"),
    "Id" : ObjectId("5cb5fecde2a22b3088ef731c")
}

, но с точки зрения приложения оно все равно будет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...