你可以从一个DbSet中的DbContext? [英] Can you get the DbContext from a DbSet?

查看:113
本文介绍了你可以从一个DbSet中的DbContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的申请,有时必须至10,000或更多的行保存到数据库中在一个操作中。我发现,简单地迭代,并在同一时间将每个项目可以采取半小时以上。

In my application it is sometimes necessary to save 10,000 or more rows to the database in one operation. I've found that simply iterating and adding each item one at a time can take upwards of half an hour.

不过,如果我禁用AutoDetectChangesEnabled需要约5秒(这正是我想要的)

However, if I disable AutoDetectChangesEnabled it takes ~ 5 seconds (which is exactly what I want)

我试图使被称为的AddRange来DbSet扩展方法,这将禁用AutoDetectChangesEnabled,然后重新启用它完成时。

I'm trying to make an extension method called "AddRange" to DbSet which will disable AutoDetectChangesEnabled and then re-enable it upon completion.

public static void AddRange<TEntity>(this DbSet<TEntity> set, DbContext con, IEnumerable<TEntity> items) where TEntity : class
    {
        // Disable auto detect changes for speed
        var detectChanges = con.Configuration.AutoDetectChangesEnabled;
        try
        {
            con.Configuration.AutoDetectChangesEnabled = false;

            foreach (var item in items)
            {
                set.Add(item);
            }
        }
        finally
        {
            con.Configuration.AutoDetectChangesEnabled = detectChanges;
        }
    }



所以,我的问题是:有没有办法从一个DbSet中的DbContext?我不喜欢使其成为一个参数 - 这感觉就像它应该是不必要的。

So, my question is: Is there a way to get the DbContext from a DbSet? I don't like making it a parameter - It feels like it should be unnecessary.

推荐答案

是,您可以从 DbSet<获得的DbContext ; TEntity> ,但解决的办法是反射沉重。我已经提供了如何做到这一点下面的例子。

Yes, you can get the DbContext from a DbSet<TEntity>, but the solution is reflection heavy. I have provided an example of how to do this below.

我测试下面的代码,它能够成功地检索的DbContext 实例,从中<生成code> DbSet 。请注意,虽然它不回答你的问题,有几乎可以肯定是一个更好的解决您的问题

I tested the following code and it was able to successfully retrieve the DbContext instance from which the DbSet was generated. Please note that, although it does answer your question, there is almost certainly a better solution to your problem.

public static class HackyDbSetGetContextTrick
{ 
    public static DbContext GetContext<TEntity>(this DbSet<TEntity> dbSet)
        where TEntity: class
    { 
        object internalSet = dbSet
            .GetType()
            .GetField("_internalSet",BindingFlags.NonPublic|BindingFlags.Instance)
            .GetValue(dbSet);
        object internalContext = internalSet
            .GetType()
            .BaseType
            .GetField("_internalContext",BindingFlags.NonPublic|BindingFlags.Instance)
            .GetValue(internalSet); 
        return (DbContext)internalContext
            .GetType()
            .GetProperty("Owner",BindingFlags.Instance|BindingFlags.Public)
            .GetValue(internalContext,null); 
    } 
}



实例:

Example usage:

using(var originalContextReference = new MyContext())
{
   DbSet<MyObject> set = originalContextReference.Set<MyObject>();
   DbContext retrievedContextReference = set.GetContext();
   Debug.Assert(ReferenceEquals(retrievedContextReference,originalContextReference));
}



说明:

据反射, DbSet< TEntity> 有一个私有字段 _internalSet 类型 InternalSet< TEntity> 。类型是内部的的EntityFramework DLL。从 InternalQuery<继承; TElement> (其中 TEntity:TElement )。 InternalQuery< TElement> 也是内部的DLL的EntityFramework。它有一个私有字段 _internalContext 键入 InternalContext 的。 InternalContext 也是内部的EntityFramework。然而, InternalContext 公开叫所有者公共的DbContext 属性。所以,如果你有一个 DbSet< TEntity> ,你可以在的DbContext 业主参考,通过访问各这些特性沉思和铸造的最终结果为的DbContext

According to Reflector, DbSet<TEntity> has a private field _internalSet of type InternalSet<TEntity>. The type is internal to the EntityFramework dll. It inherits from InternalQuery<TElement> (where TEntity : TElement). InternalQuery<TElement> is also internal to the EntityFramework dll. It has a private field _internalContext of type InternalContext. InternalContext is also internal to EntityFramework. However, InternalContext exposes a public DbContext property called Owner. So, if you have a DbSet<TEntity>, you can get a reference to the DbContext owner, by accessing each of those properties reflectively and casting the final result to DbContext.

在EF7有一个私有字段_context直接在类的工具DbSet。不难公开揭露这一领域

In EF7 there is a private field _context directly in the class the implements DbSet. It's not hard to expose this field publicly

这篇关于你可以从一个DbSet中的DbContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆