#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».