Windows Form App C#调用DbContext的正确方法

时间:2019-02-22 01:32:19

标签: c# .net entity-framework

我的Windows窗体应用程序有3个相互引用的类。

每个类都有其自己的特定数据库调用。

但是,我不确定这是调用它们的正确方法,因为当我现在启动程序时遇到堆栈溢出异常

当我调试时,我意识到我在每个类上调用时,每次都会重新加载dbcontext。可以吗?

public class ProgramsData
{
    private AutoPrintDbContext dbContext = new AutoPrintDbContext();
    private FieldsData fieldsData = new FieldsData();
    private PrinterData printerData = new PrinterData();

    public ProgramsData()
    {

    }
}

public class PrinterData
{
    private AutoPrintDbContext dbContext = new AutoPrintDbContext();
    private ProgramsData programsData = new ProgramsData();
    private FieldsData fieldsData = new FieldsData();

    public PrinterData()
    {

    }
}

public class FieldsData
{
    private AutoPrintDbContext dbContext = new AutoPrintDbContext();
    PrinterData printerData = new PrinterData();

    public FieldsData()
    {

    }
}

这是我在主程序中调用类的方式:

public partial class AutoPrint : Form
{
    ProgramsData programsData = new ProgramsData();
    PrinterData printerData = new PrinterData();

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        var backgroundWorker = sender as BackgroundWorker;
        List<PrintObject> pol = new List<PrintObject>();
        pol = printerData.Load(InputDirectory.Text, programInput.Text);

    }
}

2 个答案:

答案 0 :(得分:2)

您的StackOverflowException与您的Entity Framework数据库上下文无关。这是您的课程属性。

创建PrinterData的实例时发生的第一件事是什么?它创建FieldsData的实例:

private FieldsData fieldsData = new FieldsData();

创建实例时,该实例的第一件事是什么?它创建PrinterData的实例:

PrinterData printerData = new PrinterData();

创建实例时,该实例的第一件事是什么?它创建FieldsData的实例:

private FieldsData fieldsData = new FieldsData();

创建实例时,该实例的第一件事是什么?它创建PrinterData的实例:

PrinterData printerData = new PrinterData();

...等无限期。 (您的ProgramsData也是该模式的一部分。)

不要那样做。

无论这些类是什么,无论它们在设计中做什么或代表什么,它们都不能以这种方式相互依赖。没有关于您的设计或系统需求的任何其他信息,我只能说要从类中删除这些字段,以使它们彼此之间不会无限地相互依赖。

也许在程序的顶层,您只需要每个类的一个实例。而且,如果一个类中的任何给定方法都需要另一个类的实例来执行某些操作,则可以将其传递给您拥有的实例,而无需创建新实例。

仍有可能仍然是一种更好的方法来设计您正在处理的内容,但是我仍然无法真正地谈论它。仅是导致异常的原因。

对于数据上下文,您可能也不希望在每个地方的每个类中都全局创建它。也许也只有一个顶级实例被传递给各个类。或者让原子数据库操作的各个方法在内部创建,使用和处置其数据上下文对象。因为在您的应用程序中打开了多个并发数据库上下文,可能会导致各种并发问题。

答案 1 :(得分:1)

否,这不是使用数据库上下文的正确方法。在大多数情况下,数据库上下文不应成为您的类的成员(或者您的类至少应为IDisposable),因为它的生存期应尽可能短,并应正确处理:

public class ProgramsData
{
    private FieldsData fieldsData = new FieldsData();
    private PrinterData printerData = new PrinterData();

    public ProgramsData()
    {

    }

    public void SomeMethodWhichWorksWithData()
    {
        using (AutoPrintDbContext dbContext = new AutoPrintDbContext())
        {
            // work with database context here, try to make it as short as possible
        }
    }
}

StackOverflowException与数据库上下文完全无关,因为您的类在无限循环中相互创建了新实例。

例如,ProgramsData在此行中创建PrinterData的新实例:

private PrinterData printerData = new PrinterData();

,然后PrinterData在此行中创建ProgramsData的新实例:

private ProgramsData programsData = new ProgramsData();

然后重复,直到它使程序崩溃。