skip to Main Content

I’m setuping a C# Asp.Net Core Api that will grow quite a bit in the future. So I’m trying to respect the Clean Code architecture, with my domain in the center without any dependences and everything around:

public abstract class Entity
{
    public Guid Id { get; set; }
}

I’m currently implementing the repositories. My issue is that for mongoDb, it seems mandatory to either provide the [BsonId] attribute, either use the BsonId in my entities. But that implies adding a mongoDb reference in my entity project, which I’m not a big fan.

public interface IRepository<TDocument> where TDocument : Entity
{
    IQueryable<TDocument> AsQueryable();
    IEnumerable<TDocument> FilterBy(
        Expression<Func<TDocument, bool>> filterExpression);
    IEnumerable<TProjected> FilterBy<TProjected>(
        Expression<Func<TDocument, bool>> filterExpression,
        Expression<Func<TDocument, TProjected>> projectionExpression);
    Task<TDocument> FindOne(Expression<Func<TDocument, bool>> filterExpression);

    Task<TDocument> FindById(Guid id);
    Task InsertOne(TDocument document);
    Task InsertMany(ICollection<TDocument> documents);
    Task ReplaceOne(TDocument document);
    Task DeleteOne(Expression<Func<TDocument, bool>> filterExpression);
    Task DeleteById(Guid id);
    Task DeleteMany(Expression<Func<TDocument, bool>> filterExpression);
}

In the example I found on Clean Architecture, they are mostly using entity framework, which doesn’t require absolutely attributes to work.

I could imagine doing another class and using AutoMapper to map between each other, but that seems cumbersome, since I always want to persist everything that are in my business object, and that could lead to some errors.

Isn’t there a way to indicate per collection(or even globally) what is the Id in the repository or when saving ?

2

Answers


  1. You could use the "BsonClassMap":

    BsonClassMap.RegisterClassMap<SomeEntity>(cm =>
            {
                cm.AutoMap();
                cm.SetIgnoreExtraElements(true);
                cm.MapIdMember(c => c.Id);
            });
    

    Reference: https://mongodb.github.io/mongo-csharp-driver/2.14/reference/bson/mapping/

    Login or Signup to reply.
  2. The above solution using static BsonClassMap should allow you to identify your Id member without "polluting" your domain.

    BsonClassMap.RegisterClassMap<SomeEntity>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
            cm.MapIdMember(c => c.Id);
        });
    

    One word of advice, for your own sanity: as an architect, you’ll need to pick and choose which rules you follow religiously, and where it makes sense to make exceptions.

    You may find on occasion that a low-risk package reference will make your life considerably easier, whether it be something for data annotations, or a package that gives you Guard clauses or the Specification pattern, etc… I wouldn’t be afraid to break the rule or to embrace some anti-patterns when carefully and thoughtfully considered, and you know the reason WHY it is an anti-pattern.

    If you were suggesting adding a dependency to something that was not lightweight, I might suggest you never do it. However, there are certain packages that are intentionally compact, and adding them to your Core/Domain project shouldn’t bring shame to your family name. 🙂

    Happy coding!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search