Mongo DB BSON: не удается определить информацию о сериализации для интерфейса (C #)

#c# #mongodb #bson #mongodb.driver

#c# #mongodb #bson #mongodb.driver

Вопрос:

Я новичок в mongo DB и имею объекты разных классов, которые реализуют один и тот же интерфейс. Я храню эти объекты в базе данных mongo, которая работает нормально. Проблема заключается в десериализации этих объектов.

Вот мой интерфейс и классы:

 public interface IEvent
{ ... }


[Serializable, JsonObject]
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(CloudBaseEvent))]
public class BaseEvent: IEvent
{...}

[Serializable, JsonObject]
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(CloudRenameEvent))]
public abstract class CloudBaseEvent : BaseEvent, IEvent
{

[Serializable, JsonObject]
[BsonDiscriminator(Required = true)]
public class CloudRenameEvent : CloudBaseEvent, IEvent
{ ... }

public class EventLog
{

    [BsonId]
    public string EventID { get; set; }

    [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)]
    public IEvent Event { get; set; }
  

Для фильтрации мне нужно проверить e.Event.Учетная запись. Здесь возникает ошибка

Не удалось определить информацию о сериализации для e => e.Событие.Учетная запись

Похоже, что десериализация e.Event не работает:

 internal class MyRepository
{

    private readonly IMongoDbRepository<Types.Models.EventLog> _mongoDb;

    /// <summary>
    /// Static constructor, initializes the MongoDB ClassMap.
    /// </summary>
    static MyRepository()
    {
        BsonClassMap.RegisterClassMap<Types.Models.EventLog>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
        });
        BsonClassMap.RegisterClassMap<BaseEvent>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
        });
        BsonClassMap.RegisterClassMap<CloudRenameEvent>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
        });
        MongoDefaults.GuidRepresentation = GuidRepresentation.Standard;
    }


public async Task<EventLog.Types.Models.EventLog> GetEventLogAsync(string eventId)
    {
        var collection = await _mongoDb.GetCollectionAsync();
        var filter = GetCustomerEventLogFilter(eventId);

        var res = await collection.Aggregate()
    //Here occurs the error
            .Match(filter)
            .FirstOrDefaultAsync();
        return res;
    }


private FilterDefinition<Types.Models.EventLog> GetCustomerEventLogFilter(string eventId)
    {
        var filters = new List<FilterDefinition<Types.Models.EventLog>>
        {
            Builders<Types.Models.EventLog>.Filter.Eq(e => e.Event.Account, Account),
        };           


        return Builders<Types.Models.EventLog>.Filter.And(filters);
    }
 }
  

Если я добавлю аннотацию

 [BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IEvent, BaseEvent>))]
  

выше

 public IEvent Event { get; set; }
  

сериализация работает, но я должен выбрать класс (например, BaseEvent). Это должно сработать автоматически.

Ответ №1:

Я придумал, как решить эту проблему:

По-видимому, десериализация невозможна при использовании интерфейса. По крайней мере, я не смог заставить это работать. Поэтому я изменил тип журнала событий.Событие из IEvent в BaseEvent, и теперь все работает нормально.

Подсказка: Кроме того, было важно, чтобы все свойства были доступны для чтения и записи. В дополнение к этому вы должны использовать аннотацию «BsonKnownTypes».