0

Environment: I have a Visual Studio 2017 solution with a Model project containing Entity Framework (EF6) DbContext and POCOs, a data access layer project implementing the Repository and Unit Of Work patterns, and a WinForms UI project. In the UI main form there is a tab control and on one of the tab-pages there is a UserControl. On the UserControl there is DataGridView. In the UserControl's Load method, I get some data from the database via the UnitofWork (which gets data from EF) and use that data to populate the DataGridView (not using Data Binding).

Problem: At design-time, when I open the main form designer, I get a SQL Server connection Exception "A network-related or instance specific error occurred while establishing a connection to SQL Server. The server was not found or is not accessible....". The stack trace shows that it is running the code that populates the DataGridView, but cannot connect to the database at design-time. Everything works fine when I build and run the application.

Already researched/found: This SO answer shows that I can use if (!DesignMode) {...} to wrap around code that I don't want to run at design time. That's okay but I'm going to be adding many more of these UserControls and I'm looking for a cleaner solution. Is there a simple (as in a few lines of code) way to...

  1. Tell EF to return empty lists of objects at design time?

or

  1. Give EF a connection sting to use at design-time so it can successfully hit the database?

I have not added any connection string to App.config. I'm simply working with Entity Framework's default connection to localDb.

  • Are you able to connect to the local db by visual studio? – Chetan Jun 11 '17 at 10:05
  • @ChetanRanpariya no I can't. Interesting. That must be the problem. I have SQL Sever Express installed. in MSSMS I can connect to both SQL Server Express (machine name) and "(localDb)\MSSQLLocalDB", but in Visual Studio I can only see the SQL Express. If I manually type in "(localDb)\MSSQLLocalDB" it makes a new connection but I can't see any of my development databases. So I must need to fix/reinstall localDb or start using SQL Server Express for development. – Matthew Bishop Jun 11 '17 at 10:20
  • Update to the above. I CAN connect to the database in VS2017 Server Explorer, I just had to wait for it to populate the list of available databases in the localDb instance. The Server Explorer calls it \localdb#.. Is that hex number a key that should be in a config file in my project? – Matthew Bishop Jun 11 '17 at 10:47
  • You can try that. It should work. – Chetan Jun 11 '17 at 11:02
  • *I'm looking for a cleaner solution* Making sure your connection works at design time is certainly *not* cleaner. You should be able to design the UI completely independent of some database running somewhere. – Gert Arnold Jun 11 '17 at 20:45
  • Thanks @GertArnold, good point. Any suggestions on how to achieve that? – Matthew Bishop Jun 11 '17 at 23:05
  • Update: I added a connection string to the app.config for the executable project. Upon compiling and running, EF created a database in SQLServer Express but did not ad the data specified in the Seed method. Now when I open the main form designer I get an exception "No connection string named '' could be found in the application config file". I added the same connection string to all three projects but didn't fix. Now I'm thinking about completely uninstalling VS2015 and VS2017 and installing VS2017 fresh again. – Matthew Bishop Jun 11 '17 at 23:44

2 Answers2

2

After re-installing Windows, SQL Server and Visual Studio, I got the same behaviour. After more searching it has become obvious that Visual Studio will always run a UserControl's Load method at design-time when you add the UserControl to a form or open the designer of a form that contains the UserControl. The solution is to test the value of the DesignMode property in the Load method.

private void MyUserControl_Load(object sender, EventArgs e)
{
    if (!this.DesignMode)
    {
        // do stuff here, if it involves connecting to the database
    }
}
1

Matthew's answer is correct in the sense that you need to check it you are currently in design mode. However this.DesignMode may not be the best way to check this because it is not totally reliable. For instance, if the control is part of another control, this.DesignMode will return false even if it is true for the parent. This question looks at alternative ways to test if you are in design mode.

The method that worked for me was from this answer.

public bool isInDesignMode()
{
    System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
    bool res = process.ProcessName == "devenv";
    process.Dispose();
    return res;
}

Credit to GWLlosa for this code.

shadowsora
  • 663
  • 7
  • 15