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));
Related
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())
{
}
I have a class called StudentDbContext. I call theOnConfiguring method in it. I saw that dependency injection is used in some training videos. Here we already use context once. Why should I use dependency injection instead of OnConfiguring?
Option-1
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("...");
}
Option-2
public StudentDbContext(DbContextOptions<StudentDbContext> context) : base(context)
{
}
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("...");
}
With this approach, you decide exactly which provider (MySQL) and which connection-string to use within StudentDbContext directly. If you want to change this to use a different provider or connection-string, you'll have to modify the StudentDbContext class directly. For example, consider a situation where you want to use a different provider for Development vs Production.
public StudentDbContext(DbContextOptions<StudentDbContext> context)
: base(context) { }
This approach allows you to configure both the provider and the connection-string from outside of the StudentDbContext.
Using Dependency Injection, you'll see something like this in Startup.ConfigureServices (or Program.cs with ASP .NET Core 6):
services.AddDbContext<StudentDbContext>(options =>
{
options.UseMySQL("...");
});
This second approach becomes more powerful when you want to use different providers/connection-strings (or even other settings) based on an environment, for example:
if (hostEnvironment.IsDevelopment())
{
services.AddDbContext<StudentDbContext>(options =>
{
options.UseMySQL("...");
});
}
else
{
services.AddDbContext<StudentDbContext>(options =>
{
options.UseSqlServer("...");
});
}
With dependency injection the DbContext doesn't need to know about the actual database in use. Furthermore, the DbContext doesn't even need to know which configuration settings should be used for establishing database connections.
This makes your code more independent. This e.g. makes your code more testable. There are other advantages, too.
you can also configure both approaches for use
db context
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseMySQL("...");
}
}
or startup configuration
services.AddDbContext<StudentDbContext>(options =>
{
options.UseMySQL("...");
});
in this case if you don't configure the startup configuration or if you are using you db context in another project without dependency injection will be uses a local db contex configuration, otherwise global.
We have an Azure Functions app that uses three databases, one of which is of type "IdentityDbContext".
Out of the blue, after months of happy use of these contexts, after a rebuild, we run into this error when firing up the Function app:
Method Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContext: type argument 'xxx.ApplicationDbContext' violates the constraint of type parameter 'TContext'.
We've tried to find a change that might cause this, but we are stumped…
Similar questions in Stackoverflow etc suggest it was an issue in earlier versions of Azure Functions, but should be resolved by now.
This is the class for the offending DBcontext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
builder.Entity<ApplicationUser>().HasMany(e => e.Claims).WithOne().HasForeignKey(e => e.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
}
}
And this is where all hell breaks loose:
var services = new ServiceCollection()
.AddDbContext<MobidotContext>(options => options.UseSqlServer(config.GetConnectionString("MobidotDbConnection")))
.AddDbContext<MobilityDbContext>(options => options.UseSqlServer(config.GetConnectionString("MobilityDbConnection")))
.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(config.GetConnectionString("DefaultConnection")));
Well, it appeared that an upgrade to Entity framework caused havoc with the IdentityDBcontext. Downgraded back to 2.2.2, and we're back in business.
I have a feeling we're back in dll hell from ten years ago… :-(
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));
}
I'm working on a project that at can end up with multiple UI versions / variants, but so far I've got two subprojects in my solution Web - containing Web interface with ASP.NET MVC. Service project is place where I have my database context and models defined.
My Goal is to have minimum or possibly no references to EF specific code in my Web project. I want it to be independent so when I switch the dlls with service backend ( from let say SQL to XML or MySQL ) I shouldn't make multiple modifications in my MVC project.
This is how it looks :
My Questions are:
- so far I've found no example of using Database.SetInitializer in other place than Global.asax. I'd like to put database re-creation if model changed in my factory-like DatabaseContextProvider class or in service class that pulls out data from context and provides it to the UI with DTOs. Are there any cons of that location ?
- I would like to have the context's connectionString to be configurable with Properties/Settings.settings file - is that reasonable ?
To avoid the coupling, I would prefer not to set the initializer outside the Assembly that contains the DataContext. So, I added a static constructor for the DataContext. This way every project referencing this Assembly will enjoy the initializer without explicitly setting it, and the initializer is set only once per process.
static MyDataContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDataContext, Configuration>());
}
The connection string will of course be taken from the application configuration file.
You would need a mechanism to call the Database.SetInitializer method before the very first usage of the DbContext. That is why its usually called in the Global.asax file.
You can create a class with an initialization method in your tm.Service project and call it in the Application_Start method and put the Database.SetInitializer in that initialization method.
Its OK to supply the connection string from a setting file.
I put it on the DbContext constructor and works for me.
public myDbContext() : base(connectionToDatabase) {
Database.SetInitializer<myDbContext>(null);
}
The solution above will work, but it is not as efficient as the following code:
protected void Application_Start()
{
Database.SetInitializer<myDbContext>(null);
}
In my case I don't have a reference of my DAL on the UI and for that reason what I did is, I create a EntityFramework config and register my setting using using reflection.
protected void Application_Start()
{
EntityFrameworkConfig.RegisterSettings();
}
public static class EntityFrameworkConfig
{
public static void RegisterSettings()
{
// Use the file name to load the assembly into the current
// application domain.
Assembly a = Assembly.Load("MyAssembly");
// Get the type to use.
Type myType = a.GetType("MyType");
// Get the method to call.
MethodInfo myMethod = myType.GetMethod("MySettingsMethod");
// Create an instance.
object obj = Activator.CreateInstance(MyType);
// Execute the method.
myMethod.Invoke(obj, null);
}
}
public void Configurations()
{
//Other settings
Database.SetInitializer<myDbContext>(null);
}
Updated
With Entity Framework 6, now you can use the NullDatabaseInitializer
Database.SetInitializer(new NullDatabaseInitializer<MyDbContext>());
Microsoft made it possible, for EF6 onwards, to configure one initializer per database context in the config file of the application. See the last section on this Microsoft page: https://msdn.microsoft.com/en-us/data/jj556606.aspx
This, like the "Global.asax" approach, has the advantage that e.g. unit test projects can use a different initializer for the same database context.
Click Global.asax page and you find a Application_Start() method.Inside this method past this following code.For support this code use namespace using System.Data.Entity;
Database.SetInitializer<namespace.modelclass>(null);