How to get environment variable in OnModelCreating()? - c#

I'm calling a method in OnModelCreating() in DbContext.
I do not want it to be called in every environment.
Saw this question on stackoverflow.
Tried to implement it like this.
OnModelCreating() in DbContext implementation.
var env = this.GetService<IWebHostEnvironment>();
if (env.EnvironmentName == "Development")
{
modelBuilder.SeedData();
}
In Program.cs
services
.AddDbContext<TDbContext>((serviceProvider, options) => options.UseSqlServer(configuration.GetConnectionString(connectionStringName))
.UseInternalServiceProvider()
.AddInterceptors(serviceProvider.GetRequiredService<SOMESERVICE>()));
UseInternalServiceProvider() is not recognized and I get compile-time error.
I'm using .net 6 and maybe, question I linked used an old version.
UPDATE : Tried
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
But it returns null

In net core 6 I used like this, the app is the app=builder.build(); in Program.cs
if (app.Environment.IsDevelopment())
{
}

Related

How to get the Log property of DatabaseFacade?

When I googled for "entityframework" and "logging", this article popped up and several people from here have also mentioned the same article.
However, when I tried it, I can't seem to get the Log property. What am I missing?
My implementation of the DbContext (btw, this was generated by Entityframework's own scaffolding):
internal partial class SharedContext : DbContext
{
public SharedContext()
{
}...
}
Here's how I tried to use:
SharedContext context = new();
//I am getting CS1061 (DatabaseFacade does not contain a definition for Log....
context.Database.Log = Console.Write;
Please help. Thanks!
Your question is tagged with .NET 6 and EF Core while the article refers to EF 6 which is previous iteration of EF for .NET Framework. You should look into logging documentation for EF Core. For example using simple logging via overloading OnConfiguring method:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
Also probably you should consider setting up context via dependency injection (DbContext Lifetime, Configuration, and Initialization):
services.AddDbContext<SharedContext>(opts => opts // or AddDbContextFactory
.Use{YourDatabaseType}(...)
.LogTo(Console.WriteLine));

Get link/API path in .NET 6

I have create a program that using .NET Framework 4.7.2 and I want to convert to .NET 6 (just for training purpose or future use.
The way when I get the link like "/jsonAPI/prxy001" in .NET 4.7.2 like this :
log.EndPoint = HttpContext.Current.Request.Url.AbsolutePath.ToString();
log.Endpoint is just a model
And I try to use it in .NET 6 said that "Current" is not available in HttpContext. I think the way or reference is defference. Can you tell me how?
P.S =
I generate that not in controller, but in another helper class.
Inject HttpContextAccessor in the startup configureservices method like below
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
then inject it via constructor in any class you need
public class Test
{
private IHttpContextAccessor context;
public Test(IHttpContextAccessor ctx) {
this.context = ctx;
}
}

How do I pass a parameter to a scoped service in .NET 5?

I have some .Net code that I need to migrate to .NET 5. Specifically, I'm registering a number of services. I've migrated most of the services, except, I'm stuck on those that need to have a parameter passed. My legacy code looks like this:
private void RegisterItem<T>(ContainerBuilder builder) where T : Item
{
builder
.RegisterType<StoreItem<T>>()
.As<IItem<T>>()
.WithParameter(ResolvedParameter.ForNamed<IStore>(nameof(MyContext)))
.InstancePerLifetimeScope()
;
}
I was trying to modify the code above to use:
services.AddScoped<IItem<T>, StoreItem<T>>();
However, this does not pass in the parameter that was set in the original implementation. My question is, how do I pass a parameter to a scoped service in ASP.NET Core?
Simply add them as a parameter to your constructor, and they will be resolved by the dependency injection engine:
public StoreItem(IStore store)
{
...
}
Note that IStore must be registered as well:
services.AddScoped<IStore, MyStore>();

no parameterless constructor defined for type dbcontext

I search many posts in stack and another sites about this error but it wasn't my answer
this is my DbCintext
[Table("AspNetUsers")]
public class ApplicationUser : IdentityUser { }
public class EMSContext : IdentityDbContext<ApplicationUser> {
public EMSContext (DbContextOptions<EMSContext> options) : base (options) { }
public DbSet<Ambulance> Ambulances { get; set; }
}
and this is mu StartUp.cs
services.AddControllers();
services.AddDbContext<EMSContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
but when I want to generate api controller I got this error
no parameterless constructor defined for type dbcontext
The error is clear, you don't have a parameterless constructor.
But that said, the tooling shouldn't need it since you are calling AddDbContext and passing in your connection string. The tooling scaffolds controllers/etc. by actually running your program and then requesting the DbContext from the host's service provider. It does this by looking for methods with very specific names.
My guess is that your main Program.cs is not following the prescribed upon pattern and thus cannot construct your Host nor locate its ServiceProvider.
Your options are as follows (my personal choice is #2):
Add a paremeterless constructor like the message says
Make sure your main entry point uses the correct conventions for the host builder methods
Create a Design-Time context factory
Parameterless Constructor
This is the obvious answer, though it's not always possible. Furthermore it should not be necessary since the scaffolding has other means by which to read from your DbContext. Adding a constructor just for this purpose is not something I would do nor recommend.
Correct Naming / Method Signature
The scaffolding looks for a very specific method signature when it attempts to run your program. Basically, it is looking for something like this:
public class Program
{
public static void Main(string[] args)
=> CreateHostBuilder(args).Build().Run();
// EF Core uses this method at design time to access the DbContext
public static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(
webBuilder => webBuilder.UseStartup<Startup>());
}
Now it doesn't need to look exactly like this. The important part is the name and signature of the CreateHostBuilder method.*
If there are any errors raised while attempting to construct the service, for example because there are dependencies that cannot be resolved or configuration is missing then this method will fail. I'm pretty sure you will get either the same error or a DI-related one.**
Design Time Factory
Supposing that still doesn't work or you'd like better control you can create a Design-Time Factory for your context. The tooling will scan your project for types implementing IDesignTimeDbContextFactory<EMSContext> and then use that during scaffolding:
public class EMSContextFactory : IDesignTimeDbContextFactory<EMSContext>
{
public EMSContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<EMSContext>();
optionsBuilder.UseSqlServer("Your Connection String");
return new EMSContext(optionsBuilder.Options);
}
}
See this link for more information.
* Note: You've not specified what version of aspnet core you are running. If you aren't using the generic host (Host.CreateDefaultBuilder) but are instead using WebHost, then the expected method signature will look a bit different. That said it will match that of creating a new project with the same settings.
If you've ever written integration tests for your controllers, the WebApplicationFactory looks for similar methods/signatures. Those same signatures should satisfy the controller scaffolding. I can't seem to find documentation on either other than the link above.
** When the scaffolding runs, it executes as the 'Production' environment. DI errors can occur if service resolution/configuration fails due to being in the "wrong" environment. This is one of the reasons the context factory solution exists.
The error is exactly located in this line:
public EMSContext (DbContextOptions<EMSContext> options) : base (options) { }
No parameterless constructors for DbContext... of course, because your constructor takes one parameter DbContextOptions options,
so you have two options to fix it, fix the call to the constructor or make the constructor take 0 parameters
Here's the error I was getting, sounds very similar to yours.
I had encountered this problem when trying to create a View (the one circled in red). My issue was the Startup.cs file. I had recently done a re-name from LeaveHistory... to LeaveRequest..., and when editing my Startup.cs file I made an incorrect change.
Line 39 should read:
services.AddScoped<ILeaveRequestRepository, LeaveRequestRepository>(); // no "I"
The error I was getting mentioned that the dbContext class didn't have a parameterless constructor - so it was totally deceptive, or at least not that helpful.
So to anyone else looking at this error, don't take it on it's face! I am fairly deep into this project, and none of my other controllers have parameterless constructors, at least not written out.
Think about other clerical changes you've made - class name changes, things like that. Perhaps the error message is not actually what it seems, and you've made a small error somewhere else that is simply generating a confusing error message.

IDesignTimeDbContextFactory not found on new asp.net .net Core project when trying to initialize db for first time [duplicate]

This question already has answers here:
How to add an implementation of IDesignTimeDbContextFactory to add migration to .Net core 2.0 application?
(3 answers)
Closed 5 years ago.
I'm following this get started tutorial with .net core (2.0):
https://learn.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db
But when I run the command:
Add-Migration InitialCreate
I get the response:
Unable to create an object of type 'MyContext'. Add an implementation of 'IDesignTimeDbContextFactory<MyContext>' to the project
The error basically tells you, that u have no class implementing the IDesignTimeDbContextFactory.
To solve this issue create a class implements the interface, that could look like following:
public class Foo : IDesignTimeDbContextFactory<MyContext> {
//Add interface methods here
}
That should solve the issue, because then u have your class Foo which implements this interface, which seems to be necessary.
Option2
If that does not help in any case, please check if your class "MyContext" inherits from DbContext.
Your class should look like the following:
public class MyContext : DbContext {
//some stuff here
}
Option3
You may have missed to edit your Startup.cs
The tutorial tells you to add the following into your Startup.cs file in order to register your context
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var connection = #"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;";
services.AddDbContext<MyContext>(options => options.UseSqlServer(connection));
}

Categories