MongoFramework icon indicating copy to clipboard operation
MongoFramework copied to clipboard

Better options/configuration/control of a Context

Open Turnerj opened this issue 4 years ago • 3 comments

Currently with a context (due to the heavy-ness of MongoDbSet), there is no way to configure things like disable tracking on an entity collection. Even looking at this from the point of view of a MongoDbSet, there is no easy way to achieve this - things are too intertwined.

Take this for example: https://github.com/dansward/DataProtection/blob/c9b4ead5f560fd4ebc1cc27ae6b37e3dbf4f8b0a/samples/EntityFrameworkCore/DataProtectionKeyContext.cs

class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext
{
    public DataProtectionKeyContext(DbContextOptions<DataProtectionKeyContext> options) : base(options) { }
    public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseInMemoryDatabase("DataProtection_EntityFrameworkCore");
        optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        optionsBuilder.EnableSensitiveDataLogging();
    }
}

While MongoFramework doesn't have that many things to configure, it provides a nice interface from the point-of-view of a context. There is a way to configure things on a MongoDbSet-level if you override OnDbSetCreation on the context but that isn't particularly nice.

So what do we do? Go the Entity Framework way (which requires refactoring a large portion of our MongoDbSet logic out to the controller and other classes) or try something different?

One thought might be to have something as simple as an OnConfiguring method like EF but instead of moving more stuff to the context, we keep it inside the DbSet.

Alternatively, we could have different types of DbSet's for different things? Some with tracking logic, some without? I mean, we already do this for buckets...

Turnerj avatar Mar 26 '20 12:03 Turnerj

With #156 landing, the MongoDbContext now does the heavy lifting, making this more plausible.

Still not many options to configure by an OnConfiguring virtual method seems like a good approach in the not-too-distant future.

Turnerj avatar Aug 17 '20 07:08 Turnerj

Would this also be needed to add indexing options without the use of attributes? I've hit a case where it would be very helpful to configure an entity without using attributes (ie the entity is in another assembly and cannot be modified, but needs indexing on particular properties).

JohnCampionJr avatar Sep 19 '20 19:09 JohnCampionJr

Nah, the mapping of entities (including indexing) is done through the entity mapping system. Because of limitations in the MongoDB driver (freezing of class maps & not allowing class maps to be replaced), it is a little messy.

At the beginning of your application (eg. Startup.cs), you could call EntityMapping.GetOrCreateEntityDefinition(typeof(MyEntity)) which would return your the entity definition as understood by MongoFramework. You can't edit it (it returns an interface with all properties as get-only) but you could cast to EntityDefinition which allows the properties to be set. From here, set an enumerable of IEntityIndex from EntityIndex.

Once this is done, the next save of an entity with that type will have the indexes updated.

If you need full control of entity mapping, you can call EntityMapping.SetDefinition(typeof(MyEntity), myEntityDefinition) and manually set the BsonClassMap.RegisterClassMap(myClassMap) instead.

The other alternative is just skip setting the indexes via MongoFramework and do it either directly in the driver (probably at application startup) OR directly to the database (via MongoDB Compass or another tool).

Ideally though, the data model would be editable directly and you can just put the index attributes on it.

In a longer-term future, I'd probably build a fluent entity definition creator so configuration is a lot easier if you didn't want to use attributes but that said, my goal for MongoFramework was to give me what I liked from Entity Framework (code-first with controls via attributes).

Turnerj avatar Sep 20 '20 02:09 Turnerj