避免在具有多个数据库上下文的 EF 中延迟加载的通用实现(使用部分 class)

Generic implementation to Avoid Lazy Loading in EF with multiple Database Context (using partial class)

在我的项目中,我确实有很多数据库上下文。

1. MyContext1 
2. MyContext2 
3. MyContext3 

我目前正在使用数据库优先方法(基于 edmx)。

作为 edmx 创建的一部分,所有这些上下文都已创建。我想为所有这些上下文禁用延迟加载。

我想为此写一个部分class。因此对于每个 Context 都会有一个部分 class 并负责禁用延迟加载。

我目前的做法如下

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

这里我有静态方法,我手动创建上下文实例并应用配置并返回它。有没有其他方法可以在不在部分 class?

中创建直接实例的情况下执行此操作

由于自动生成的 edmx 中已经有一个默认构造函数 class 我无法在我创建的部分 class 中编写构造函数。

我可以在服务层中禁用这个,但由于这是一个现有项目,我不想触及任何地方。那么有没有更好的解决方案呢?

因为这是一个现有的应用程序并且它有很多 edmx 文件我不能 edit/change edmx 中的任何东西包括 t4 模板

终于找到解决办法了

因为我在我的解决方案中使用了 Simple Injector Dependency Injection 包。 我创建了一个供应商,用于在 运行 时间获取实例。

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;
        }
    }
}

然后是界面

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

我可以像这样从服务层调用这个

private readonly IDbContextProvider<MyDbContext> _baseContextProvider;

public MyService(IDbContextProvider<MyDbContext> baseContextProvider)
        {
            this._baseContextProvider = baseContextProvider;
        }