繁体   English   中英

使用Entity Framework Core时应该处置DbContext吗

[英]Should I dispose DbContext when using Entity Framework Core

我在aspx文件(.NET Framework 4.6.2项目)中具有以下方法:

public static string SetAvgPeriodDays(int userId)
{
    var service = new AveragePeriodDaysService(EfHelper.GetContext());

    try
    {
        return service.SetAveragePeriodDays(userId);
    }
    catch (Exception e)
    {
        return e.Message;
    }
}

AveragePeriodDaysService类具有一个接受DbContext实例的构造函数:

public class AveragePeriodDaysService
{
    private readonly MyDbContext _ctx;

    public AveragePeriodDaysService(MyDbContext ctx)
    {
        _ctx = ctx;
    }

    public string SetAveragePeriodDays(int userId)
    {
        // main logic goes here...
    }
}

这里是EfHelper类:

public class EfHelper
{   
    public static MyDbContext GetContext()
    {
        var options = new DbContextOptionsBuilder<MyDbContext>();

        var connectionString = ...
        options.UseSqlServer(connectionString);
        options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

        return new MyDbContext(options.Options);
    }
}

题。 我应该处置MyDbContext吗? 如果是,我应该如何正确处理?

通常,您永远都不应处置从外部获得的依赖项,因为您永远不知道还有谁使用此依赖项的相同实例。 这意味着AveragePeriodDaysService无法处理MyDbContext 但是SetAvgPeriodDays确切知道谁将消费MyDbContext因为它请求创建MyDbContext ,因此它可以并且应该在使用后进行处置。 使用using关键字:

public static string SetAvgPeriodDays(int userId)
{
    using(var ctx = EfHelper.GetContext())
    {
        var service = new AveragePeriodDaysService(ctx);

        try
        {
            return service.SetAveragePeriodDays(userId);
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }
}

我实际上不太确定正确的模式是什么,但是我通常采用以下方法(类似于.NET StreamSafeHandle类所做的事情):

您的AveragePeriodDaysService实际上似乎可以控制上下文(将其存储在private readonly字段中)。 因此,实际上,此类应实现IDisposable并处理上下文本身。

另一方面,您可能想对不同的“服务”类使用单个上下文,而不必始终创建一个新的上下文。 因此,如果这些类始终放置上下文,将很烦人。

所以我的实现方式是这样的:

public class AveragePeriodDaysService : IDisposable
{
    private readonly MyDbContext _ctx;
    private readonly bool _ownContext;

    public AveragePeriodDaysService(MyDbContext ctx, bool ownContext)
    {
        _ctx = ctx;
        _ownContext = ownContext;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing) GC.SuppressFinalize(this);
        if (_ownContext) _ctx.Dispose();
    }

    public void Dispose()
    {
        Dispose(true);
    }

然后,您可以决定创建的实例是否应该负责处理上下文,或者创建者是否需要保持控制权。

当然,如果创建的实例可以控制,则需要正确处置该实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM