你能从DbSet获取DbContext吗? [英] Can you get the DbContext from a DbSet?

查看:160
本文介绍了你能从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)

我试图对DbSet做一个名为AddRange的扩展方法,这将禁用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< TEntity> 获取 DbContext ,但解决方案是反映沉重。我已经提供了一个如何做到这一点的例子。

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 DbSet 的c $ c>实例。请注意,尽管它确实能够回答您的问题,但几乎肯定会更好地解决您的问题。

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

使用示例:

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

说明:

根据Reflector, DbSet< TEntity> 有一个私人字段 _internalSet code> InternalSet< TEntity> 。该类型是EntityFramework dll的内部。它继承自 InternalQuery< TElement> (其中 TEntity:TElement )。 InternalQuery< TElement> 也是EntityFramework dll的内部。它有一个类型为 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天全站免登陆