Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF 3.1 Add-Migration failing to create new migration with -StartupProject, but EF 2.2 works #19760

Closed
BobbyCannon opened this issue Jan 31, 2020 · 18 comments
Assignees
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@BobbyCannon
Copy link

BobbyCannon commented Jan 31, 2020

I'm currently upgrading my project Speedy from EF core 2.2 to 3.1. The command below works fine on 2.2 but fails on 3.1.

Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose

In the Speedy repository https://github.com/BobbyCannon/Speedy there are two master branches.

  • master == EF Core 3.1
  • master-core-2 == EF Core 2.2

Steps to reproduce

The code below returns null when using EF Core 3.1 but returns the connection string in the web.config of Speedy.Website.

Both projects reference System.Configuration.ConfigurationManager 4.7.0 nuget package to access the connection string in the web.config.

var connection = ConfigurationManager.ConnectionStrings["DefaultConnection"];
if (connection != null && !string.IsNullOrWhiteSpace(connection.ConnectionString))
{
	return connection.ConnectionString;
}

Further technical details

EF Core version: 2.2, 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET FX 4.7.2
Operating system: Windows 10
IDE: Visual Studio 2019 16.4

Output for EF Core 2.2

PM> Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose
Using project 'Speedy.Website.Data.Sql'.
Using startup project 'Speedy.Website'.
Build started...
Build succeeded.
C:\Workspaces\GitHub\Speedy - Core 2.2\packages\Microsoft.EntityFrameworkCore.Tools.2.2.6\tools\net461\any\ef.exe migrations add Initial --json --verbose --no-color --prefix-output --assembly "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.Data.Sql.dll" --startup-assembly "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.dll" --project-dir "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\" --language C# --working-dir "C:\Workspaces\GitHub\Speedy - Core 2.2" --data-dir "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\App_Data" --root-namespace Speedy.Website.Data.Sql
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql'.
Using configuration file 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.dll.config'.
Using data directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\App_Data'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding IWebHost accessor...
No entry point was found for assembly 'Speedy.Website'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ContosoSqlDatabase'.
Using context 'ContosoSqlDatabase'.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding design-time services referenced by assembly 'Speedy.Website'.
No referenced design-time services were found.
Finding IDesignTimeServices implementations in assembly 'Speedy.Website'...
No design-time services were found.
DetectChanges starting for 'ContosoSqlDatabase'.
DetectChanges completed for 'ContosoSqlDatabase'.
Writing migration to 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\Migrations\20200131123936_Initial.cs'.
Writing model snapshot to 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\Migrations\ContosoSqlDatabaseModelSnapshot.cs'.
'ContosoSqlDatabase' disposed.
To undo this action, use Remove-Migration.
PM>

Output for EF Core 3.1

PM> Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose
Using project 'Speedy.Website.Data.Sql'.
Using startup project 'Speedy.Website'.
Build started...
Build succeeded.
C:\Workspaces\GitHub\Speedy\packages\Microsoft.EntityFrameworkCore.Tools.3.1.1\tools\net461\any\ef.exe migrations add Initial --json --verbose --no-color --prefix-output --assembly C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.Data.Sql.dll --startup-assembly C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.dll --project-dir C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql\ --language C# --working-dir C:\Workspaces\GitHub\Speedy --data-dir C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data --root-namespace Speedy.Website.Data.Sql
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql'.
Using configuration file 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.dll.config'.
Using data directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data'.
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql'.
Using data directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ContosoSqlDatabase'.

**** Connection String:

@BobbyCannon BobbyCannon changed the title Add-Migration failing to create new migratin with -StartupProject EF 3.1 Add-Migration failing to create new migratin with -StartupProject, but EF 2.2 works Jan 31, 2020
@bricelam
Copy link
Contributor

Are you using .NET Framework on 2.2 and .NET Core on 3.1? We need a hook (issue dotnet/runtime#931) to make App.config work on .NET Core. Consider using Microsoft.Extensions.Configuration instead.

@BobbyCannon
Copy link
Author

BobbyCannon commented Feb 1, 2020

I'm just trying to understand why does EF 2.2 work fine but EF 3.1 doesn't. What changed? Only the EF version changed so no reason it should change unless something about the EF tools changed that no longer works with ConfigurationManager.

This is how I currently read the connection string.

public static string GetConnectionString()
{
	var connection = ConfigurationManager.ConnectionStrings["DefaultConnection"];
	if (connection != null && !string.IsNullOrWhiteSpace(connection.ConnectionString))
	{
		return connection.ConnectionString;
	}

	var configuration = new ConfigurationBuilder()
		.SetBasePath(Directory.GetCurrentDirectory())
		.AddJsonFile("AppSettings.json", true)
		.Build();

	return configuration.GetConnectionString("DefaultConnection");
}

I tried to change it to

var configuration = new ConfigurationBuilder()
	.SetBasePath(Directory.GetCurrentDirectory())
	.AddJsonFile("AppSettings.json", true)
	.AddXmlFile("web.config", true)
	.Build();

var connectionString = configuration.GetSection("ConnectionStrings")?.GetConnectionString("DefaultConnection");
return connectionString ?? configuration.GetConnectionString("DefaultConnection");

Getting a different error now....

System.FormatException: A duplicate key 'appSettings:add:key' was found.

@BobbyCannon
Copy link
Author

@bricelam I appreciate your suggestion but it has it's own issues. I would like to know why Add-Migration is different, meaning that ConfigurationManager is not initialized?, in EF Core 3.1 vs EF Core 2.2.

Here is my solution.

public static string GetConnectionString()
{
	var connection = ConfigurationManager.ConnectionStrings["DefaultConnection"];
	if (connection != null && !string.IsNullOrWhiteSpace(connection.ConnectionString))
	{
		return connection.ConnectionString;
	}

	if (connection == null)
	{
		// NOTE: EF 3.1 design tools no longer initializes ConfigurationManager  
		// so we have to load it manually for Add-Migration, grrrr
		// https://github.com/dotnet/efcore/issues/19760
		connection = GetFromAppConfig();

		if (connection != null)
		{
			return connection.ConnectionString;
		}
	}

	var configuration = new ConfigurationBuilder()
		.SetBasePath(Directory.GetCurrentDirectory())
		.AddJsonFile("AppSettings.json", true)
		.Build();

	return configuration.GetConnectionString("DefaultConnection");
}

private static ConnectionStringSettings GetFromAppConfig()
{
	var directory = Environment.CurrentDirectory;
	var configFileNames = new[] { "web.config", "app.config" };

	foreach (var configFileName in configFileNames)
	{
		var filePath = Path.Combine(directory, configFileName);
		
		if (File.Exists(filePath))
		{
			var map = new ExeConfigurationFileMap { ExeConfigFilename = filePath };
			var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
			var connection = config.ConnectionStrings.ConnectionStrings["DefaultConnection"];
			if (connection != null)
			{
				return connection;
			}
		}
	}

	return null;
}

@MintPlayer
Copy link

MintPlayer commented Feb 3, 2020

Hi @BobbyCannon

I'm using the dotnet tools to do this kind of stuff.

cd Speedy.Website
dotnet ef migrations add Initial --project ..\Speedy.Website.Data.Sql
dotnet ef database update --project ..\Speedy.Website.Data.Sql

I'm able to generate and run the migrations, without problems.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.UseSqlServer(configuration.GetConnectionString("SpeedyWebsite"), options => options.MigrationsAssembly("Speedy.Website.Data.Sql")); // Assembly where your migrations should end up
}

This should grab the SpeedyWebsite connection string from your website configuration.

Can you try this? I'd be amazed if it wouldn't work for you...

@BobbyCannon
Copy link
Author

BobbyCannon commented Feb 3, 2020

@MintPlayer I need to know how you created the variable "configuration" so I can attempt to reproduce your results. Also my migrations are stored in a different location than my website. Maybe this is why it works for you and not me.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.UseSqlServer(***configuration***.GetConnectionString("SpeedyWebsite"), options => options.MigrationsAssembly("Speedy.Website.Data.Sql")); // Assembly where your migrations should end up
}

Also note, I'm using the "Package Manager Console" inside Visual Studio (full version, not code).

@MintPlayer
Copy link

Hi,

My migrations are also stored in my Data project (options.MigrationsAssembly("Speedy.Website.Data.Sql")).

The configuration variable is simply injected in the DbContext:

internal class MintPlayerContext : IdentityDbContext<User, Role, Guid>
{
    private readonly IConfiguration configuration;
    public MintPlayerContext(IConfiguration configuration) : base()
    {
        this.configuration = configuration;
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
    }
}

@BobbyCannon
Copy link
Author

@MintPlayer I think you may have miss a critical part of my issue.

Both projects reference System.Configuration.ConfigurationManager 4.7.0 nuget package

I can read configuration from an "AppSettings.json" but not from an "app/web.config" file from a .NET 4.7.2 Web Application and / or WPF application.

The problem is that something changed between EF Core 2.2 to 3.1 that has broken or prevented ConfigurationManager from initializing properly. Now we must take extra steps to open the configuration for app.config and web.config.

@MintPlayer
Copy link

I'm sorry, I have no experience with the https://www.nuget.org/packages/System.Configuration.ConfigurationManager you're refering to. What limitations are you experiencing with https://www.nuget.org/packages/Microsoft.Extensions.Configuration?

@ajcvickers
Copy link
Member

@BobbyCannon In trying to figure out what changed from 2.2 to 3.1, the first thing to rule out is whether or not you also changed from .NET Framework to .NET Core. The behavior you are seeing is expected on .NET Core. If you're still on .NET Framework then we will investigate more.

@BobbyCannon
Copy link
Author

@ajcvickers I'm only using .NET 4.7.2 (full framework) with EF 2.2 and EF 3.1 libraries.

Details from the original post below:

Further technical details
EF Core version: 2.2, 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET FX 4.7.2
Operating system: Windows 10
IDE: Visual Studio 2019 16.4

@jsabrooke
Copy link

jsabrooke commented Mar 30, 2020

@BobbyCannon @ajcvickers @bricelam I've found exactly the same problem with EF Core 3.1.3 and .NET Framework 4.8 (no .NET Core involved). The applications themselves work fine with EF Core 3.1.3; it's only the migrations that don't seem to.

The first result I found from Googling was https://docs.microsoft.com/answers/questions/20091/wpf-core-connection-strings-inside-appconfig-not-w.html , so I made sure that my Startup Project was creating the exe.config file, and still get the same result.

Thanks for your temporary workaround code @BobbyCannon!

In the output below, the line

` data source=.\SQLEXPRESS;Integrated Security=SSPI AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

is because I added
foreach (var connectionString in ConfigurationManager.ConnectionStrings) { Console.WriteLine(connectionString.ToString()); }

Presumably it's just falling back to a default. And the exception at the end is because
ConfigurationManager.ConnectionStrings[""].ConnectionString is throwing a null reference exception.

Further technical details
EF Core version: 3.1.3
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Framework 4.8
Operating system: Windows 10 Pro -10.0.18363 Build 18363
IDE: Visual Studio 2019 16.5.0

Output from PM> Add-Migration InitialCreate
PM> Add-Migration InitialCreate -Verbose
Using project '<MyDbContextProject>' .
Using startup project '<MyStartupProject>' .
Build started...
Build succeeded.
...\packages\Microsoft.EntityFrameworkCore.Tools.3.1.3\tools\net461\any\ef.exe migrations add InitialCreate --json --verbose --no-color --prefix-output --assembly <MyStartupProjectPath> \bin\Debug\ <MyDbContextProjectNamespace> .dll --startup-assembly <MyStartupProjectPath> \bin\Debug\ <MyStartupProjectExe> .exe --project-dir <MyDbContextProjectPath> --language C# --working-dir <MyWorkingDir> --root-namespace <MyDbContextProjectNamespace>
Using assembly '<MyDbContextProjectNamespace>' .
Using startup assembly '<MyStartupProjectNamespace>' .
Using application base '<MyStartupProjectPath> \bin\Debug'.
Using working directory '<MyStartupProjectPath>' .
Using root namespace '<MyDbContextProjectNamespace>' .
Using project directory '<MyDbContextProjectPath>' .
Using configuration file '<MyStartupProjectPath> \bin\Debug\ <MyStartupProjectExe>.exe.config'.
Using assembly '<MyDbContextProjectNamespace>' .
Using startup assembly '<MyStartupProjectNamespace>' .
Using application base '<MyStartupProjectPath> \bin\Debug'.
Using working directory '<MyStartupProjectPath>' .
Using root namespace '<MyDbContextProjectNamespace>' .
Using project directory '<MyDbContextProjectPath>' .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext '<MyDbContext>' .
data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true
Using context '<MyDbContext>' .
System.NullReferenceException: Object reference not set to an instance of an object.
at <MyDbContextProjectNamespace>.<MyDbContext>.OnConfiguring(DbContextOptionsBuilder optionsBuilder) in <MyDbContextProjectPath><MyDbContext>.cs:line 443
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<> c__DisplayClass3_0`1. <Execute> b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.

@BobbyCannon
Copy link
Author

I feel this will not be fixed as future focus is on .NET Core. I do wish there were better .NET FX validation as this worked in EF Core 2.2. However I guess this will be another reason to encourage us to move to .NET Core. I do feel for those who cannot due to time and effort.

@bricelam bricelam removed this from the 5.0.0 milestone Apr 7, 2020
@ajcvickers ajcvickers added this to the 3.1.x milestone Apr 17, 2020
@ajcvickers ajcvickers removed this from the 3.1.x milestone May 18, 2020
@dglozano
Copy link

We have experienced the exact same problem as @BobbyCannon

@BobbyCannon BobbyCannon changed the title EF 3.1 Add-Migration failing to create new migratin with -StartupProject, but EF 2.2 works EF 3.1 Add-Migration failing to create new migration with -StartupProject, but EF 2.2 works May 27, 2020
@ajcvickers
Copy link
Member

/cc @bricelam

@bricelam
Copy link
Contributor

bricelam commented May 29, 2020

It looks like we have two options for fixing this:

  1. Wait for Provide a way to override the global configuration file path runtime#931
    • Unlikely to be patched in 3.1
    • Would the EF Core 5.0 tools work on EF Core 3.1 projects?
      • dotnet-ef is probably fine
      • Installing the PMC tools might try and lift the core and relational assembles, but you could just install them into a dummy project...
  2. Update EFCore.Design to cross-target net461 again and bring back code removed by PR Clean up residual net461 code #15740
    • Seems unlikely to get approved in a 3.1 patch

Workaround

Don't use ConfigurationManager at design time.

You could load and parse the XML file yourself or switch to something like Microsoft.Extensions.Configuration.

@bricelam
Copy link
Contributor

Crazy idea: We could also call some internal code in ef.exe to get .NET Framework working again.

@ajcvickers ajcvickers added this to the 5.0.0 milestone Jun 5, 2020
@ajcvickers ajcvickers removed their assignment Jun 10, 2020
@bricelam
Copy link
Contributor

bricelam commented Jun 15, 2020

Workaround

You can work around this issue by adding an implementation of IDesignTimeDbContextFactory that updates the config file location:

class MyDesignTimeContextFactory : IDesignTimeDbContextFactory<MyContext>
{
    public MyContext CreateDbContext(string[] args)
    {
        // Work around dotnet/efcore#19760
        var startupAssembly = Assembly.Load("MyApp"); // TODO: Update this
        AppDomain.CurrentDomain.SetData(
            "APP_CONFIG_FILE",
            new Uri(startupAssembly.CodeBase).LocalPath + ".config");
        typeof(ConfigurationManager)
            .GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, 0);
        typeof(ConfigurationManager)
            .GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, null);
        typeof(ConfigurationManager).Assembly
            .GetType("System.Configuration.ClientConfigPaths")
            .GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, null);

        return new MyContext();
    }
}

@bricelam bricelam added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jun 15, 2020
@bricelam bricelam modified the milestones: 5.0.0, 3.1.7 Jul 15, 2020
@mark-monteiro
Copy link

mark-monteiro commented Nov 5, 2020

EDIT: The underlying issue causing this bug (dotnet/runtime#931) has been fixed in .NET 6 (relevant PR: dotnet/runtime#56748), making the workaround below unnecessary if you update to .NET 6.


This workaround may also be useful for anyone porting an application from .NET Framework to .NET Core and isn't ready to switch to Microsoft.Extensions.Configuration.

It is mostly the same as the previous suggestion, but instead of setting APP_CONFIG_FILE (which has no effect in .NET Core), the config file is copied to the default expected location before resetting the configuration system. For example, when running with the dotnet ef CLI tools, the configuration system expects a file named "ef.dll.config".

class MyDesignTimeContextFactory : IDesignTimeDbContextFactory<MyContext>
{
    public MyContext CreateDbContext(string[] args)
    {
        // Copy the app config file to the expected location (i.e. "ef.dll.config")
        // See: https://github.com/dotnet/corefx/blob/v3.1.9/src/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs#L63
        var mainProjectAssembly = Assembly.Load("MyApp");  // TODO: Update this
        string mainProjectConfigPath = new Uri(mainProjectAssembly.CodeBase).LocalPath + ".config";
        var entryAssembly = Assembly.GetEntryAssembly();
        string newConfigPath = new Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, entryAssembly.ManifestModule.Name)).LocalPath + ".config";
        File.Copy(mainProjectConfigPath, newConfigPath, overwrite: true);

        // Reset the configuration system
        typeof(ConfigurationManager)
            .GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, 0);
        typeof(ConfigurationManager)
            .GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, null);
        typeof(ConfigurationManager).Assembly
            .GetType("System.Configuration.ClientConfigPaths")
            .GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, null);

        return new MyContext();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
Development

No branches or pull requests

6 participants