c# - 我是否需要使用 Entity Framework 的 using 语句?

标签 c# database entity-framework asp.net-core

我可以与 Entity Framework 一起使用吗:

private MyDbContext _context;

public ControllerName(MyDbContext context)
{
    this._context = context;
}

或者我应该使用类似的东西:

public async Task<ActionResult> GetSomething() 
{
    using (var db = new MyDbContext())
    {
        //Some code
    }
}

当我有一个 using 语句时,它希望我传入 DbContext 的选项。我不太确定它希望我传递什么选项。

最佳答案

这取决于...

我应该创建自己的 DbContext 吗?

在使用DbContext时使用using语句的原因是因为你想让DbContext在短时间内保持事件状态。 DbContext 与数据库保持一个开放的连接,它会记住所获取的项目,因此您可以一项一项地更改所获取的项目的属性,而无需再次从数据库中获取数据。

这是一个强大的优化。但缺点是,如果数据库在 dbContext 仍处于事件状态时发生更改,则 dbContext 中的数据将与数据库中的实际数据不同步。

因此,明智的做法是不要让 dbContext 长时间保持事件状态。 using block 确保无论发生什么,在离开该 block 时都会调用 Dispose(),即使在发生异常之后也是如此。它类似于C++中的析构函数,一旦变量超出范围就会自动调用。

是否应该创建一个将 DbContext 作为输入的类,或者是否应该创建自己的 DbContext 取决于您的类。

你是否希望你的用户(=软件,而不是运算符(operator))决定哪个数据库应该提供你的类需要查询的数据:让你的用户提供dbContext,并让他处理它。注意:您的用户必须意识到这一点,并且不要让您的类保持较长时间(想想几秒钟)。

用户:

using (var dbContext = new MyDbContext(...))
{
    MyClass myObject = new MyClass(dbContext);

    var fetchedData = myObject.FetchData();
    ProcessFethedData(fetchedData);
}

通常您不想给用户带来负担。考虑创建一个在构造函数中使用 ... 的 Disposable 类。您可以创建 dbContext:

class MyDbContext: IDisposable
{
    private readonly MyDbContext dbContext;

    public MyClass(string nameOrConnectionString)
    {
        this.dbContext = new MyDbContext(nameOrConnectionString);
    }

    public void Dispose()
    {
        this.dbContext?.Dispose();
    }

    public Customer FetchCustomer(int customerId)
    {
        return dbContext.Customers.Find(customerId);
    }
}

用法:

using (var myDbContext = new MyDbContext(...))
{
    Customer customer1 = myDbContext.FetchCustomer(2);
    Customer customer2 = myDbContext.FetchCustomer(3);
    ...
}

优点:您的客户不必了解有关您的数据库的任何信息,以及您用于访问它的方法:它是 Entity Framework 吗?或者你使用的是普通的旧式 SQL?或者也许您根本不使用数据库,而是使用 CSV 文件!

问题是:你的用户仍然必须记住你的nameOrConnectionString,并且他必须在使用后处置你。他还必须知道不要让你长时间处于开放状态。

另一方面:在获取两个客户之间不必重新创建数据库连接可能会很方便。

最常用的第三种解决方案是创建一个类,该类将为每个方法创建和处置 dbContext。如果用户忘记处置您,那么 DbContext 将不会保持打开状态超过所需的时间。

注意:由于您隐藏了您正在使用 Entity Framework ,甚至隐藏了它是一个数据库,因此给它一个名称:我是一个可以更长时间存储数据的类:

class MyRepository
{
    private readonly string nameOrConnectionString;

    public MyClass(string nameOrConnectionString)
    {
        this.nameOrConnectionString = nameOrConnectionString);
    }

    public Customer FetchCustomer(int customerId)
    {
        using (var dbContext = new MyDbContext(this.nameOrConnectionString)
        {
            return dbContext.Customers.Find(customerId);
        }
    }
}

用法:

var repository = new MyRepository(...)
Customer customer1 = repository.FetchCustomer(2);
Customer customer2 = repository.FetchCustomer(3);

用户可以使您的存储库保持较长时间的事件状态。缺点是每次调用都会创建 DbContext。通常创建 dbContext 并不耗时,但请记住:如果您经常需要获取多个项目,请考虑创建一种方法来一次性执行此操作。但话又说回来:你不应该为你“定期”做的每件事制定方法吗?

DbContext的构造函数

DbContext 有两个构造函数。一个空的,从配置文件中获取连接字符串,或者带有连接字符串的一个。

如果应用程序中的每个人都应使用相同的数据库(因此使用相同的连接字符串),请将连接字符串放入 app.config 中。 Microsoft about connection strings in DbContext

如果有多个数据库要由同一个 DbContext 控制,您的创建者必须告诉您他们应该使用哪个连接字符串:

class MyDbContext : DbContext
{
    // Default constructor uses DbConnectionString from app.config
    public MyDbContext() : base()
    {
       ...
    }

    // only provide non-default constructor if users want to tell you which database to use
    public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
        ...
    }
    

关于c# - 我是否需要使用 Entity Framework 的 using 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62906949/

相关文章:

c# - 发布到 Azure 错误 - 错误 : '' , 十六进制值 0x0F 是无效字符。 1 号线,位置 285

C# 相当于 Delphi 的 DisableControls/EnableControls

mysql - 在 mySQL 中获取 CSV 值

entity-framework - 为什么我必须手动提供外键属性值(在这种情况下)?

c# - Team Foundation Server 2013 update 4 不构建 .net 4.6.1 应用程序

c# - 使用 Fluent API 而不是 InverseProperty 和导航属性

mysql - 从 MySql 导出到 sql 文件时如何自动转义内容中的引号?

c# - 如何从不同的输入插入

c# - 如何使用LINQ调整结果?

c# - 迁移问题 - EF 认为数据库需要更新,引用它的项目不会运行