I’m implementing a Domain-Driven Design (DDD) architecture in my application using MongoDB with Entity Framework Core. My goal is to maintain clear separation between the domain logic and the database infrastructure. To achieve this, I have structured my solution with separate projects for the domain and infrastructure layers.
In my domain project, I have defined a Customer
entity and a CustomerService
. The Customer entity has a string property Id:
public class Customer
{
public string Id { get; set; }
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Customer> Customers { get; set; }
}
public class CustomerService
{
private readonly MyDbContext _mydbContext;
public CustomerService(MyDbContext mydbContext)
{
_mydbContext = mydbContext
}
public Customer Get(string id)
{
return _mydbContext.Customers.Find(id);
}
public void Create(Customer customer)
{
_mydbContext.Customers.Add(customer);
_mydbContext.SaveChanges();
}
}
In the infrastructure project, I have extended the MyDbContext with MongoDbContext, using the MongoDB.EntityFrameworkCore
package:
public class MongoDbContext : MyDbContext
{
public static MongoDbContext Create(IMongoDatabase database) =>
new(new DbContextOptionsBuilder<MongoDbContext>()
.UseMongoDB(database.Client, database.DatabaseNamespace.DatabaseName)
.Options);
public MongoDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>(c =>
{
c.ToCollection("customers");
c.HasKey(c => c.Id);
c.Property(p => p.Id)
.HasConversion(id =>ObjectId.Parse(id),oid => oid.ToString());
});
}
}
It’s important to note that the Id
property in the Customer entity is currently defined as a string
. While I could redefine it as type MongoDB.Bson.ObjectId
, doing so would introduce a dependency on the MongoDB.Bson
package in the domain layer, which contradicts the abstraction I’m aiming for. The objective is to keep the domain layer unaware of the underlying database implementation.
Furthermore, note that I’m working with pre-existing MongoDB documents where the Id
field is of type ObjectId
. Otherwise, I might have opted for Guid or other primitive data types.
Fetching customers works seamlessly since the HasConversion()
method handles the conversion from ObjectId to string. However, when creating a new customer, the Id property needs to be populated during the addition of the entity to the DbContext.
My preference is, if possible, to utilize the ObjectId generated by MongoDB for this purpose, instead of creating in C# code.
How can I address this challenge while preserving the abstraction between the domain and the infrastructure layers?