【问题标题】:Instantiating a context in LINQ to Entities在 LINQ to Entities 中实例化上下文
【发布时间】:2009-05-01 21:52:56
【问题描述】:

我见过程序员在代码中创建实体上下文时采用的两种不同方式。

第一个是这样的,你可以在MSDN代码示例中找到它:

public void DoSomething() {
     using (TaxableEducationEntities context = new TaxableEducationEntities()) {
          // business logic and whatever else
     }
}

第二个是在封装您的业务逻辑的某个类中将上下文创建为私有属性。所以你会有类似的东西:

public class Education_LINQ {

        private TaxableEducationEntities context = new TaxableEducationEntities();

        public void DoSomething() {
            var result = from a in context.luAction
                         select a;

            // business logic and whatever else
        }
}

哪种方式更有效?

假设您有两种方法,一种称为 DoSomething1(),另一种称为 DoSomething2(),并且这两种方法都包含 using 语句来打开上下文并对其执行任何操作。如果您要一个接一个地调用一个方法,是否会产生任何多余的开销,因为本质上这两种方法都会创建上下文,然后在完成后将其清除?与在实例化类对象时仅创建一个私有属性相反,然后在对象超出范围时依次清理?

【问题讨论】:

    标签: linq entity-framework linq-to-entities entity


    【解决方案1】:

    每次创建一个新的 ObjectContext 确实涉及“一些”开销。本质上,所涉及的开销是将元数据从全局缓存复制到与特定 ObjectContext 关联的元数据中。

    这种开销相对较小,因此通常不值得担心,尤其是当您考虑到使用模式固有的额外安全性时。

    对我来说,您选择哪个选项取决于以下内容:

    1. 你的寿命有多长 包装类可能是什么?如果它活着 很长一段时间 ObjectContext 可能 成长为拥有许多实体 随着时间的推移减速。所以一个新的 ObjectContext 每次都可能是一个 好主意。
    2. 是否调用 包装类上的方法 同步?对象上下文 类本身不是线程安全的,所以如果 你使用你需要的第二种模式 确保你的包装类/ 存储库是线程安全的,如果你 期望多个线程调用它。
    3. 这些方法本质上是 无关?如果是这样,如果它们在方法之间共享一个上下文,您可能会得到意想不到的副作用。

    一般来说,我的建议是,如果方法是无状态的,即触发并忘记每个方法的新上下文可能是个好主意。

    但是,如果您有一个相对较短的有状态形式或其他东西,那么共享上下文可能是一个更好的主意。

    更新:我花时间整理了a more complete answer

    【讨论】:

    • 很好的问题,很好的答案 +1 对双方都有效
    • 缓存EntityConnection怎么样? stackoverflow.com/questions/2575485/…
    • 在服务层之上派生的层应用过滤器和排序等场景怎么样?您是否应该预先实现数据、接受打击并返回IEnumerable 而不是IQueryable?是否存在您认为应该在服务层之外返回IQueryable 的上下文?
    【解决方案2】:

    如果这就是您的意思,第二个选项实际上不会自行清理。我更喜欢每次都使用 ObjectContext 版本,因为我不必在之后处理它。不过我不确定我的问题是否正确……今天编程时间太长了。

    public class UserManagerRepository : IUserManagerRepository, IDisposable
    {
        private readonly Entities _context = new Entities();
        private bool _disposed;
    
        public User Create(User user, int countryId)
        {
            user.Country = GetCountry(countryId);
            _context.AddToUser(user);
            _context.SaveChanges();
            return user;
        }
    }
    

    然后要使用这个存储库,我会执行以下操作:

    using(var repository = new UserManagerRepository())
    {
        repository.Create(user);
    }
    

    【讨论】:

    • 好吧,我的假设不好;我应该意识到实体上下文没有得到清理,但这也许没什么大不了的。当我这样做时,我也倾向于合并 using() 语句。引发这个问题的原因是我遇到了 Scott Guthrie 所做的 MVC 教程,他将实体上下文创建为正在使用的类的私有属性。
    • 这取决于您的模型/域的复杂程度。在某些情况下,我需要发送当前对象上下文。不久前,我创建了一些非常复杂的发票或其他东西。我让工厂在构造函数中获取上下文,以便我可以重用它。不过,我确实认为您可以在大多数情况下摆脱上述情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    相关资源
    最近更新 更多