Unable to determine the serialization information

2019-05-18 11:07发布

问题:

First up, I know there is already questions out there with this error message, but I haven't found any that relate to the use of using interfaces with this type of query.

I'm currently trying to update a MongoDB entity using the C# Driver 2.0. However, I'm getting an error when it's trying to build the query (I'm assuming it's the Builders<T>.Filter.Eq(i => i.Id, entity.Id) bit of code) and I'm getting the following error:

Unable to determine the serialization information for i => i.Id.

I've got the following class that I'm trying to update

public interface IEntity {
    string Id { get; set; }
}

public interface ITrack : IEntity {
    string Name { get; set; }
}

public class TrackDTO : ITrack
{

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

    public string Name { get; set; }

}

I'm then using the interface to save the object into the database using the following method in a generic DAO class to replace the entire document. Note, in the example below T is coded as ITrack (i.e. TrackDao = new Dao<ITrack>) but when the object is passed in at runtime it's a TrackDTO object (which is correct):

public async Task<T> Save(T entity)
{
    // Save the entity to the collection.
    ReplaceOneResult result = await _collection.ReplaceOneAsync(Builders<T>.Filter.Eq(i => i.Id, entity.Id), entity, new UpdateOptions() { IsUpsert = true });

    // return the saved user object.
    return entity;
}

I don't know if the Id property of my IEntity class also requires the [BsonId] attribute, but I'd like to avoid this if possible, as I want to keep my model layer (where IEntity resides) free of any database platform specific references.

I've also tried adding the following class map which has had no effect either:

BsonClassMap.RegisterClassMap<TrackDTO>(cm =>
{
    cm.AutoMap();
    cm.MapMember(c => c.Id).SetSerializer(new StringSerializer(BsonType.ObjectId));
    cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});

For the same reason as not having the [BsonId] attributes in the Model layer, I don't want to have the Model classes decorated with [BsonKnownTypes] that reference DTO objects, however I don't mind if this needs to occur as part of a class map.

回答1:

  1. For

"Unable to determine the serialization information for i => i.Id."

Try to use: nameof().

Builders<T>.Filter.Eq(nameof(IEntity.Id), entity.Id)

2.

...but I'd like to avoid this if possible, as I want to keep my model layer (where IEntity resides) free of any database platform specific references.

My solution for problem like your and similar problems:

public interface IEntity {
    [BsonId]
    string Id { get; set; }

    string IdEntity { get; set; }
}

[BsonIgnoreExtraElements(Inherited = true)]
public abstract class BaseEntity : IEntity 
{
    [BsonRepresentation(BsonType.ObjectId)]
    public virtual string Id { get; set; }

    [BsonIgnoreIfNull]
    public string IdEntity { get; set; }
}