1

Is there any way to know if DbContext.OnConfiguring() is being called from the Package Manager?

Here's my method.

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
    if (string.IsNullOrWhiteSpace(DataPath))
        throw new InvalidOperationException("No database path is specified.");

    // Configure SQLite
    options.UseSqlite($"Data Source={DataPath}");
}

This code works fine in my WinForms application. However, when adding migrations via the Package Manager Console, DataPath will be null and an exception is thrown.

When run from Package Manager Console, it's okay if DataPath is null, as no actual database is used in that case. But I still want to throw an exception if DataPath is null while my application is running.

Is there any way to detect when this code is called from my application, and when it's called from Package Manager Console?

Note that I'm using .NET 6 and EF 6.

Note

Looking at the current entry assembly is one answer to this question. However, because that would run every time an instance of my DbContext class is created, it would not be ideal from a performance perspective. In addition, I am not sure if the name of the DLLs could change in future versions of .NET. The ideal solution would be a more direct way, either as a property of the DbContextOptionsBuilder instance that is passed to the method, or by setting my own flag by detecting difference in the way the class is instantiated.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • Does this answer your question? [How do I get the path of the assembly the code is in?](https://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in) – paulsm4 Aug 06 '22 at 22:56
  • I'm curious why you want to do this? – DavidG Aug 06 '22 at 23:59
  • @DavidG: Because when my program is running, I need to configure the connection string to reference the current database file. But when it's run from Pacakage Manager Console, there is no current database. – Jonathan Wood Aug 07 '22 at 16:21

1 Answers1

2

You could get the name of the exe that is running when OnConfiguring executes with

using System.IO;
using System.Reflection;

var exeName = Path.GetFileName(Assembly.GetEntryAssembly().Location);
Console.Log("Running with " + exeName);

Returns the assembly that is the process executable in the default application domain, or the first executable that was executed by ExecuteAssembly(String). Can return null when called from unmanaged code.

See https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.getentryassembly for more info

Edit:

You pointed out that the executable name might be a moving target. This is a valid point, but if your application name is the constant in this scenario, then you can check for "myapp.exe" as the condition.

Another alternative is to just use a temporary value for DataPath when it is null since this seems like the actual problem you are trying to solve.

if (string.IsNullOrWhiteSpace(DataPath))
   DataPath = Path.GetTempFileName();
Bron Davies
  • 5,930
  • 3
  • 30
  • 41
  • 1
    that's what I was trying to tell the OP: a) use System.Reflection to get the assembly, then b) use .Location (or equivalent) to determine the origin. I guess somebody had to spell it out. Glad you did: +1. – paulsm4 Aug 06 '22 at 20:39
  • 1
    Thanks. In fact, `DataPath` can be null and it will translate to an empty path in my connection string. For Package Manger Console, this is just fine. I ended up reworking the code so more is handled through different constructors. It's not ideal. – Jonathan Wood Aug 07 '22 at 16:31