Skip to content

Commit

Permalink
Add a static flag in EF that will be set when code is being executed …
Browse files Browse the repository at this point in the history
…for design-time discovery (#28508)
  • Loading branch information
ajcvickers committed Jul 28, 2022
1 parent 7437c0a commit 56bfe7c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/EFCore.Design/Design/DbContextActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public static DbContext CreateInstance(
{
Check.NotNull(contextType, nameof(contextType));

EF.IsDesignTime = true;

return new DbContextOperations(
new OperationReporter(reportHandler),
contextType.Assembly,
Expand Down
5 changes: 5 additions & 0 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ protected OperationBase(IOperationResultHandler resultHandler)
/// <param name="action">The action to execute.</param>
protected virtual void Execute(Action action)
{
EF.IsDesignTime = true;
try
{
action();
Expand All @@ -714,6 +715,10 @@ protected virtual void Execute(Action action)
{
_resultHandler.OnError(ex.GetType().FullName!, ex.Message, ex.ToString());
}
finally
{
EF.IsDesignTime = false;
}
}

/// <summary>
Expand Down
16 changes: 16 additions & 0 deletions src/EFCore/EF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ public static partial class EF
internal static readonly MethodInfo PropertyMethod
= typeof(EF).GetTypeInfo().GetDeclaredMethod(nameof(Property))!;

/// <summary>
/// This flag is set to <see langword="true" /> when code is being run from a design-time tool, such
/// as "dotnet ef" or one of the Package Manager Console PowerShell commands "Add-Migration", "Update-Database", etc.
/// </summary>
/// <remarks>
/// <para>
/// This flag can be inspected to change application behavior. For example, if the application is being executed by an EF
/// design-time tool, then it may choose to skip executing migrations commands as part of startup.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-commandline">EF Core command-line reference </see> for more information
/// and examples.
/// </para>
/// </remarks>
public static bool IsDesignTime { get; set; }

This comment has been minimized.

Copy link
@AraHaan

AraHaan Jul 29, 2022

Member

Nice, will it be passed onto MSBuild perhaps as well?


/// <summary>
/// References a given property or navigation on an entity instance. This is useful for shadow state properties, for
/// which no CLR property exists. Currently this method can only be used in LINQ queries and can not be used to
Expand Down
14 changes: 13 additions & 1 deletion test/EFCore.Design.Tests/Design/DbContextActivatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,40 @@ public class DbContextActivatorTest
[ConditionalFact]
public void CreateInstance_works()
{
EF.IsDesignTime = false;

var result = DbContextActivator.CreateInstance(typeof(TestContext));

Assert.IsType<TestContext>(result);

Assert.True(EF.IsDesignTime);
}

[ConditionalFact]
public void CreateInstance_with_arguments_works()
{
EF.IsDesignTime = false;

var result = DbContextActivator.CreateInstance(
typeof(TestContext),
null,
null,
new[] { "A", "B" });

Assert.IsType<TestContext>(result);

Assert.True(EF.IsDesignTime);
}

private class TestContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options
{
Assert.True(EF.IsDesignTime);

options
.EnableServiceProviderCaching(false)
.UseInMemoryDatabase(nameof(DbContextActivatorTest));
}
}
}
18 changes: 18 additions & 0 deletions test/EFCore.Design.Tests/Design/OperationExecutorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ public void Ctor_validates_arguments()

public class OperationBaseTests
{
[ConditionalFact]
public void Operations_have_design_time_flag_set()
{
EF.IsDesignTime = false;

var handler = new OperationResultHandler();
var result = "Twilight Sparkle";

new MockOperation<string>(handler, () =>
{
Assert.True(EF.IsDesignTime);
return result;
});

Assert.False(EF.IsDesignTime);
Assert.Equal(result, handler.Result);
}

[ConditionalFact]
public void Execute_catches_exceptions()
{
Expand Down

0 comments on commit 56bfe7c

Please sign in to comment.