powlette
powlette

Reputation: 1800

Entity Framework 5.0 Repository with dynamic DbContext

As it says on the tin, is it possible to create an instance of a DbContext suitable for use as an Entity Framework 5.0 POCO context where the properies that are normally declared as

public DbSet<T> Entities { get; set; }

aren't set/known until runtime?

I'd like to make a repository that has methods like

public TEntity Find<TEntity>(object key) where TEntity : class
{
    return _context.Set<TEntity>().Find(key);
}

public void Update<TEntity>(TEntity entity) where TEntity : class
{
    if (_context.Entry(entity).State == EntityState.Detached) //entity is detached 
        _context.Set<TEntity>().Attach(entity);
    _context.Entry(entity).State = EntityState.Modified;
}

.... etc

And then use them like:

Widget w = repository.Find<Widget>(123);
repository.SaveChanges();

This is trivial if the repository's context is set to a class that contains a DbSet<Widget> Widgets, but can it be done such that the entity types that I plan to use won't be know until runtime OR possibly not until I actually USE them? So that if I have a new class Foo, I can immediately query my repository to .Find<Foo>(123) without having to first add a DbSet<Foo> Foos to my DbContext class?

I think this should be possible because there's nothing special about the poco classes or the DbContext instance which holds references to them.

Upvotes: 0

Views: 1050

Answers (1)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364269

You don't need DbSet<Foo> Foos property in your context. That is just one way to tell context about existence of the Foo entity. There are multiple ways how context discovers mapped entities:

  • By explicit DbSet<T> properties
  • By navigation properties in already discovered entities
  • By specifying mapping in DbModelBuilder
    • Overriding OnModelCreated in your context type
    • Creating DbModelBuilder manually, building it and compiling it into DbCompiledModel which can be passed to DbContext constructor
    • By declaring EntityTypeConfiguration<T> for each entity and adding it to DbModelBuilder (either in OnModelCreated or in manually created DbModelBuilder).

The last option can be used to discover all required entities at application startup (for example by searching assemblies for all entity configuration classes and registering them to model builder) but it is still not fully dynamic solution. Compiled model is normally constructed only once per application run when the context is used for the first time. Without replacing the compiled model you cannot add or remove mapped entity types to the context.

Upvotes: 2

Related Questions