I have used EF many times, but i cant seem to figure out why this is happening.
I have a solution with 2 projects, one is my common library used in a few other applications that has all my entities and one is my updater console application. In the common library i have my context which looks like so.
public class DalContext : DbContext
{
public DalContext() : base(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString)
{
Database.SetInitializer(new CreateDatabaseIfNotExists<DalContext>());
}
public DbSet<UserAccount> UserAccounts { get; set; }
public DbSet<GameImport> GameImports { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
then in my console application i go to create an instance of the context, and i get the error
"Object reference not set to an instance of an object".
I am using a basic using statement to create my context so everything gets disposed properly.
using (var db = new DalContext())
{
....
}
i get the error when the using statement is creating the DalContext object.
both applications are using the same version of EF 6.1.3. I was able to do an add-migration just fine. i dunno, i'm stumped.
I have referenced other applications where i have used this and i cannot find any differences as to why this would be happening. I know its going to be something blatantly obvious.
In this kind of situation, it's always a good practice to do a binary search debugging. That is, keep on removing stuff until it works. Narrow down the error. Until the bare minimum.
You can try:
Replace this by the actuall connection string: ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString. This is the most likely one. "DefaultConnection" may not be on your web.config/app.config file, that would explain why the same code works for other host projects.
Remove/replace this: Database.SetInitializer(new CreateDatabaseIfNotExists<DalContext>());
Remove/replace this: modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();.
Given the info you have provided, it's impossible for us to help you further.
Related
I'm trying to use EF6 in my project and I've got two databases I'm trying to interact with. My app.config has connection strings for both, and I have two DbContext classes that pass in the app.config's key for the corresponding connection string. One context:
public LogProcessorContext() : base("LogProcessorDb")
{
}
public DbSet<LogFile> LogFiles { get; set; }
the other context:
public MessageTrackingContext() : base("MessageTrackingDb")
{
}
public DbSet<JournalLog> JournalLogs { get; set; }
but when I add the migration using add-migration NewBranch and update the db, a log file table gets added to the message tracking db (the wrong one), and the journallogs table doesn't get added at all. If anyone has any experience getting ef to play nice with multiple db/contexts, i'm all ears. I'm sure its just some simple mistake I'm making.
btw,
"LogProcessorDb"
and
"MessageTrackingDb"
are the keys in my app.config for my connection strings.
Thanks!
Following is a part of code in my DbContext that creates data and seeds data.
public class labSchedulerDbContext :DbContext
{
static abDbContext()
{
Database.SetInitializer(new abDatabaseInitializer());
}
public abDbContext() :base (nameOrConnectionString:"abDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Rest of the code is just declaring models.
In my setinitializer class with seed
public class abDatabaseInitializer : DropCreateDatabaseIfModelChanges<abDbContext>
{
.....
}
Code is working fine. Problem I have is when I created site in IIS and ran it. It runs fine but after few hours it will delete the database and initialize and seed data again. Thus we lose the data added. I tried to comment out lines where setinitilizer file is being called. Still didn't work. I refreshed apppool and site maybe it was cached files. But still no luck.
Can you please tell me how I can disable the whole initializer file once a database is created so no matter what it doesn't go and drops db and create a new one.
Cod
You can use this other initializer:
CreateDatabaseIfNotExists: This is default initializer. As the name suggests, it will create the database if none exists as per the configuration. However, if you change the model class and then run the application with this initializer, then it will throw an exception
The only thing that you have to do is to drop the database yourself before you deploy a new version with a different model. (Provided that's what you want to do).
Unable to cast object of type 'MvcMiniProfiler.Data.EFProfiledDbConnection' to type 'System.Data.SqlClient.SqlConnection'.
I am trying to upgrade to MvcMiniProfiler 1.9.0 and I keep getting this when I call MiniProfilerEF.Initialize(). I have removed the system.data config section. I don't know what I am doing wrong. I have followed the steps on the site, but maybe I missed something?
I am using EF code first 4.1 and I am passing in the name of my connectionstring into a constructor to create my datacontext.
Web Activator
using Project.Web.App_Start;
using WebActivator;
[assembly: PreApplicationStartMethod(typeof(MiniProfiler), "Start")]
namespace Project.Web.App_Start {
public class MiniProfiler {
public static void Start()
{
if (Eco.Environment.IsDevelopment) {
MiniProfilerEF.Initialize();
}
}
}
}
StructureMap Registry:
using Project.Domain.Repositories;
using StructureMap.Configuration.DSL;
namespace Project.Web.DependencyResolution.Registries {
public class RepositoriesRegistry : Registry {
public RepositoriesRegistry() {
For<IProjectDataContext>().HybridHttpOrThreadLocalScoped().Use(() => new ProjectDataContext(Eco.Database.Name));
}
}
}
DataContext Constructor:
public ProjectDataContext(string nameOrConnectionString)
: base(nameOrConnectionString) {
Active = new Active(this);
}
I have removed system.data dataproviders fron my config since the documentation says I only need to call MiniProfilerEF.Initialize().
**Update
Previously in 1.7 MvcMiniProfiler I had to set the Database.DefaultConnectionFactory property, but I've removed that. The Database.DefaultConnectionFactory always comes back as SqlConnectionFactory, shouldn't it be ProfiledConnectionFactory or something like that?
I was seeing this same error. It drove me nuts but I finally figured it out. My issue had nothing to do with web.config, assemblies, Initialize_42 or Initialize(false) hacks or anything.
Here's where I went wrong...
I had enabled automatic application of migrations like this:
App_Start:
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<DataContext, Migrations.Configuration>()
);
Migrations/Configuration.cs:
internal sealed class Configuration
: DbMigrationsConfiguration<Path.To.DataContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
}
And that was being triggered via WebActivator like this:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(service_tracker_mvc.App_Start.DatabaseInitializer), "Start")]
I accidentally found that disabling this process resulted in the profiler working. The issue, as it happens, is that this init process was happening too soon. It normally happens during Application_Start (if you're not using this fancy WebActivator stuff) so I changed it to PostStart. Now it works:
▼▼▼▼
[assembly: WebActivator.PostApplicationStartMethod(
typeof(service_tracker_mvc.App_Start.DatabaseInitializer), "Start")]
I made the mistake of adding MiniProfiler.EF rather than MiniProfiler.EF6. Removing MiniProfiler.EF and replacing it with the EF6 version fixed my issue.
see https://stackoverflow.com/a/10814033/311289
This is caused by doing DB operations before initializing miniprofiler, put a breakpoint in the contstructor for your db context, and another on the MiniProfilerEF.Initialize(); line, and revise until the initialization is first.
The problem I see here, is that ProjectDataContext encapsulates some data context into property "Active", which could not be found by MvcProfiler proxy.
More than that, EFProfiledDbConnection is actually DbConnection child, but not SqlConnection's child. It is made in terms of abstraction to use different Db providers, like MySql, Postgres, etc. Please, try to review all variables in code, they should be DbConnection, but not SqlConnection (this is a provider of MsSql).
I had this same problem and the way I found to fix it was to move to Glimpse: http://getglimpse.com/. In my opinion, it is a lot better than miniprofiler, easy to use, complete, etc.
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);
I just started trying my hands on EF4 code first this morning and I created my POCO, data context and Initializer classes in a separate class library, I believe it's the regular boiler plate type code. I reference the class in an MVC3 application and set the initializer in the Global.asax. On running the app, I notice the following problems
1. No database is created anywhere (Then I add an entry in the web.config for a connection string named after the Context class, still no result)
2. When I try to access the initalized values, I get a null error, obviously because there is no data.
Can anyone please help me with pointers on how to get thi thing to work (would be a shame if I spent my entire christmas day learning this and I still can't get it to work :( )
Thanks
p.s. I tried inserting break points and I hit the app initialization method, but it never hits the Seed method in the initializer even though I add a break point there as well!!
Thanks.
Initializer class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using F2AController.Models;
namespace F2AController.DataObjects
{
public class F2AInitializer : DropCreateDatabaseAlways<F2AContext>
{
protected override void Seed(F2AContext context)
{
var countries = new List<Country>
{
new Country(){ CountryName="Germany", Active = true},
new Country(){ CountryName="Britain", Active = true}
};
countries.ForEach(s => context.Countries.Add(s));
context.SaveChanges();
var providers = new List<Providers>()
{
new Providers(){ ProviderName="InfoBip", ContactDetails="Rturo Manovic", Active=true, MessageRates= new List<ProviderRates>(){new ProviderRates(){ CountryId=1, DateCreated=DateTime.Now, DateModified=DateTime.Now, Rate=0.05M, Active=true}}}
};
providers.ForEach(p => context.Providers.Add(p));
context.SaveChanges();
var usermobiles = new List<MobileTerminal>()
{
new MobileTerminal(){ Active= true, Credits=200, DateCreated=DateTime.Now, MSISDN="4477565444865"}
};
usermobiles.ForEach(u => context.MobileTerminals.Add(u));
context.SaveChanges();
}
}
}
Context Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
namespace F2AController.Models
{
public class F2AContext : DbContext
{
public DbSet<Country> Countries;
public DbSet<MobileTerminal> MobileTerminals;
public DbSet<Providers> Providers;
public DbSet<ProviderRates> ProviderRates;
public DbSet<Property> Properties;
public DbSet<ShortMessage> ShortMessages;
public DbSet<UserProperties> UserProperties;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
Global.asax App initialization method
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
Database.DefaultConnectionFactory = new SqlConnectionFactory(ConfigurationManager.ConnectionStrings["F2AContext"].ConnectionString);
Database.SetInitializer<F2AContext>(new F2AInitializer());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Eureka..finally!
While searching for a solution, I came across this post Entity Framework Database.SetInitializer simply not working
Applying the solution suggested there to force my database to create worked at start up like I expected, but then while running the seed code, it threw a null pointer exception. While investigating, I realized that any attempt to reference the DBSet collections from the Context class yielded the same exception. Inspecting further I realised that instead of using
public DbSet<MobileTerminal> MobileTerminals { get; set; }
I had used
public DbSet<MobileTerminal> MobileTerminals;
Which meant that I did not get any implicit object initialization, hence the null pointer exception. I removed the forced initialization code and ran the app again, this time the seed code didn't run until I accessed a page which actually queried the data context and it ran perfectly.
Apparently, due to Lazy loading, the initialization code is not run until it is actually needed, i.e. the first time the data context is queried in the application.
I hope this helps anyone who has the same problem in the future.
I wanted to share another issue when using a class library for code first & stumbled across this post. I had my code first POCO and DataContext classes in a library project too and wanted to use this project to create my code first database. I figured out that there is a -ProjectName flag with which one can specify the class library project to look for when creating the database.
add-migration -Name 'InitialCreate' -ProjectName 'MyProject.Data'
update-database -ProjectName 'MyProject.Data'
The issue might be with the connectionstring you are using in your web.config.
For SQL CE use following
<add name="YourContext"
connectionString="Data Source=|DataDirectory|yourDB.sdf"
providerName="System.Data.SqlServerCe.4.0"/>
For SQL Express use following
<add name="YourContext"
connectionString="Data source=.\SQLEXPRESS;Integrated Security=True;Initial Catalog=YourDatabase;"
providerName="System.Data.SqlClient" />
I guess this should make things work.
Also, I think you should look at this article EF Code First DB Initialization Using Web.Config. It's better to initialize the database from web.config rather than from global.asax file