alexandre-spieser / mongodb-generic-repository

An example of generic repository implementation using the MongoDB C# Sharp 2.0 driver (async)
MIT License
311 stars 84 forks source link

AddOneAsync always generate new _id #37

Closed mduu closed 4 years ago

mduu commented 4 years ago

I'm stuck with adding new documents to the collection. When I use AddOneAsync(myDocument) it doesn't use my Id but stores a new Guid. I really could need some help.

I use:

Here are my model and my model-base class:

    [CollectionName("Ride")]
    internal class RideModel : ModelBase
    {
        public Guid TripId { get; set; }
        public Guid? NextTripId { get; set; }
        public Guid VehicleId { get; set; }
        ...
    }

    internal abstract class ModelBase : IDocument
    {
        [BsonId]
        public Guid Id { get; set; }

        public int Version { get; set; }
    }

I made my own base repository inherited from BaseMongoRepository like this:

    internal abstract class RepositoryBase<TEntity, TModel> : BaseMongoRepository<Guid>, IRepository<TEntity>
        where TEntity: IEntity
        where TModel: ModelBase
    {
        private readonly ILogger logger;

        protected RepositoryBase(
            ILogger logger,
            IMongoDatabase mongoDatabase) : base(mongoDatabase)
        {
            this.logger = logger;
        }

        public virtual async Task SaveEntityAsync(TEntity entity)
        {
            var model = await GetByIdAsync<TModel>(entity.Id);

            var updatedModel = MapTo(entity);
            if (model != null)
            {
                await UpdateOneAsync(updatedModel);
                logger.LogInformation("{entityName} [{id}] updated.", typeof(TEntity).Name, updatedModel.Id, updatedModel);
            }
            else
            {
                await AddOneAsync(updatedModel);
                logger.LogInformation("{entityName} [{id}] added.", typeof(TEntity).Name, updatedModel.Id, updatedModel);
            }
        }

        [return: MaybeNull]
        public virtual async Task<TEntity> GetByIdAsync(Guid id)
        {
            var model = await GetByIdAsync<TModel>(id);
            return model == null ? default : MapTo(model);
        }

        public virtual async Task<IReadOnlyCollection<TEntity>> GetAllAsync()
            => (await base.GetAllAsync<TModel>(e => true))
                .Where(e => e != default)
                .Select(MapTo)
                .ToList();

        public virtual async Task<bool> UpdateAsync(TEntity entity) => 
            await base.UpdateOneAsync(MapTo(entity));

        public virtual async Task InsertAsync(TEntity entity) => 
            await base.AddOneAsync(MapTo(entity));

        public async Task DeleteAsync(TEntity entity)
            => await base.DeleteOneAsync(MapTo(entity));

        protected abstract TEntity MapTo(TModel model);

        protected abstract TModel MapTo(TEntity entity);
    }

I checked multiple times that the Id property is set to my Gui value (so MapTo() works). When I now call InsertAsync() or SaveEntityAsync() I always get a new guid in _id instead of the Guid value I set in the Id property. I guess that means MongoDb does not get that I have BsonId or unique Id and generate it own.

But why? I don't see what's wrong here. Can you please help? Cheers, Marc

mduu commented 4 years ago

Never mind. Seems that this code works as expected but looking at the data in Robo 3T shows some other value in _id. Maybe final value in MongoDb is a encoded version of the Guid value of the Id property.