0

In my project I do have many Database Contexts.

1. MyContext1 
2. MyContext2 
3. MyContext3 

I am currently using database first approach (edmx based).

As part of edmx creation all these contexts are created. I would like to disable lazy loading for all these contexts.

I thought of writing a partial class for this. So for each Context there will be a partial class and which is responsible for disabling the lazy loading.

My current approach is something like below

[DbConfigurationType(typeof(InterceptorConfiguration))]
    public partial class MyContext1 : DbContext
    {
        public static MyContext1 Create()
        {
            var applicationDbContext = new MyContext1();
            applicationDbContext.Configuration.LazyLoadingEnabled = false;
            return applicationDbContext;
        }
    }

Here i do have static method where i manually create instance of context and apply the configurations and returning it. Is there any other way to do this without creating a direct instance in the partial class?

Since there is already a default constructor in the edmx auto generated class I cannot write a constructor in the partial class which I have created.

I can disable this one in service layer, but since this one is an existing project I dont want to touch everywhere. So is there any better solution to do the same ?

Since this one is an existing application and it has many edmx files I cannot edit/change anything in the edmx including t4 template

6
  • Does this answer your question? Override or replace default constructor when using database first approach Commented Jul 24, 2020 at 12:36
  • @JohnathanBarclay sorry not exactly. This needs changing the existing edmx t4 template. And this will change most of my existing classes also(edmx related) I am not allowed to change this. Else i could have added it in the service layer itself Commented Jul 24, 2020 at 13:13
  • Use a context factory. Commented Jul 24, 2020 at 13:37
  • @GertArnold I am using Simple Injector and i do have Db context provider which is responsible for providing the instance as scoped. It act like a factory where i can get the instance based on need, But the issue is its a generic type and the simple injector GetInstance method return object , so i cannot get DbContext type there and do this operations Commented Jul 24, 2020 at 13:43
  • Then give the partial contexts constructors in which you can inject an options object that directs the lazy-loading option. Commented Jul 24, 2020 at 13:47

1 Answer 1

0

Finally got a solution.

Since I am using Simple Injector Dependency Injection package in my solution. I have created a provider for getting the instance at run time.

public sealed class DbContextProvider<T> : IDbContextProvider<T>
     where T : DbContext
{
    /// <summary>
    /// The producer
    /// </summary>
    private readonly InstanceProducer producer;

    /// <summary>
    /// Initializes a new instance of the <see cref="DbContextProvider{T}"/> class.
    /// </summary>
    /// <param name="container">The container.</param>
    /// <exception cref="InvalidOperationException">You forgot to register {typeof(T).Name}. Please call: " +
    ///                     $"container.Register<{typeof(T).Name}>(Lifestyle.Scope);</exception>
    public DbContextProvider(Container container)
    {
        this.producer = container.GetCurrentRegistrations()
            .FirstOrDefault(r => r.ServiceType == typeof(T))
            ?? throw new InvalidOperationException(
                $"You forgot to register {typeof(T).Name}. Please call: " +
                $"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
    }

    /// <summary>
    /// Gets the context.
    /// </summary>
    /// <value>
    /// The context.
    /// </value>
    public T Context
    {
        get
        {
            DbContext dbContext = (T)this.producer.GetInstance();
            //Dynamic proxies are used for change tracking and lazy loading
            //if DbContext.Configuration.ProxyCreationEnabled is set to false, DbContext will not load child objects 
            //for some parent object unless Include method is called on parent object.
            dbContext.Configuration.ProxyCreationEnabled = false;
            return (T)dbContext;
        }
    }
}

Then the interface

 public interface IDbContextProvider<out T> where T : DbContext
    {
        /// <summary>
        /// Gets the context.
        /// </summary>
        /// <value>
        /// The context.
        /// </value>
        T Context { get; }
    }

I can call this one from service layer like

private readonly IDbContextProvider<MyDbContext> _baseContextProvider;

public MyService(IDbContextProvider<MyDbContext> baseContextProvider)
        {
            this._baseContextProvider = baseContextProvider;
        }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.