I have an application which uses Entity Framework Code First models.
The structure of the project looks like this
Application.Models POCO objects
Application.EF EF Data Context and repositories
Application.Web.MVC The web application (the designer)
The context initializer looks like this:
public class DBContextInitializer : DropCreateDatabaseIfModelChanges<DBContext>
{
protected override void Seed(DBContext context)
{
}
}
Now, i have another API Application which gets the data from database as API calls. The project looks like this:
Application.Api.MVC The MVC4 API Project, containing DTO objects
Application.Models Same project
Application.EF Same project
Even if i don't change the POCO classes (inside Application.Models project), Entity Framework detects that the Metadata has changed, and tries to drop and re-create the database. If it does it, when i run the Designer Application (Application.Web.MVC), it drops it again, and so on.
I don't know why is it doing this. I am not changing the models.
Please ignore the question, it is all working. I was pointing to a different database.
Also, this was a good reason to learn about EF Migrations
Related
I am using ASP.Net boilerplate framework + SQL Server 2016 in my project. Recently I have faced a challenge with migration from SQL Server to MongoDB. I have found that it is possible with ASP .NET boilerplate and installed required NuGet packages, however, due to the lack of documentation the only thing I have managed to do is to define respective RepositoryBase class:
public abstract class MyRepositoryBase<TEntity, TPrimaryKey> : MongoDbRepositoryBase<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
protected MyRepositoryBase(IMongoDatabaseProvider databaseProvider)
: base(databaseProvider)
{
}
}
As far as I understand, first of all, I need to define connection string somewhere now. And then populate the database with required basic data(which previously had been done by EF Core migrations). Obviously, EF Core in the new approach is obsolete so does that mean for my DbContext class that it is obsolete as well?
Actually, there are plenty of questions in relation to ASP .NET boilerplate and MongoDB integration, therefore my current post is actually a request for provision of some kind of example of the existing integration. Thank you in advance.
You can register your module by depending on it on your web module.
[DependsOn(typeof(YourMongoDbModule))]
public class YourWebModule : AbpModule
{
}
I think you have to register the repository with:
IocManager.Register(typeof(IMongoRepository<>), typeof(MongoRepository<>), Abp.Dependency.DependencyLifeStyle.Singleton);
You can refer this sample.
Look at this comment also.
Here is a framework which maps EF Core to Mongo DB.
It takes a while (3 minutes+) to 'create/compile' my DbContext. The web server starts in about 5 seconds, but when I do the first query to my database, Entity Framework has to 'build/create/compile' the database in memory or something, I think? The next requests are almost instant. This was a Database First creation of the DbContext, the database already exists in MSSQL and has data. The DbContext contains about 500 DbSet's with relations.
Is there a way to speed this up by doing the 'creation(mapping?)' of my Entity Framework's DbContext before running the web server, create the file/mappings it needs, so the first request is fast too?
EDIT1:
I've tried the Power Tools, but they give me an error that the DbContext has no constructor that can be used, while it has a normal constructor
public DbContext() : base() {}
Any other things I could try?
The Entity Framework documentation describes how to generate views using EF Power Tool here.
Once you have in stalled EF Power Tools you have to:
Right click on the class containing your DbContext or on your .edmx file
Select "Generate Views"
This will generate the class containing the pre-computed mapping, which will automatically load on startup. If you change your database and don't regenerate the views EF will throw an exception.
Whether it will work for EF7 though, who knows...
I'm experimenting with the latest EF 5 CF (in VS2010, not VS2012). I'm generally following the MSDN EF 5.0 Quickstart: Creating a Model with Code First...
Rather than using a console app, my DbContext is in a Windows Service, which will eventually expose various data service methods by hosting a WCF Service (the client will be WPF MVVM)
In the OnStart of the Windows Service, I invoke SetInitializer, and then do a simple query to trigger initialization:
// Start the Windows service.
protected override void OnStart(string[] args)
{
Database.SetInitializer<MediaLibraryContext>(new MediaLibraryContextInitializer());
using (var context = new MediaLibraryContext())
{
var firstMedia = (from m in context.Medias select m).FirstOrDefault();
}
...
And EF CF creates the database from the model and seeds it, as expected.
But when I stop/restart the Service, EF appears to delete the database and recreate it (or perhaps it's just dropping the tables and recreating them?). All post-initialization changes I've made to the database are gone, and only the "seed" data is present.
I've worked with EF 4.1 and 4.3, but I've never seen this behavior. Any ideas where to look???
DadCat
EDIT: I found the problem just after posting this... the Quick start code has the database initialization strategy set to DropCreateDatabaseAlways.
That's what I get for copy/pasting code without carefully looking at it!
DC
I found the problem just after posting this... the Quick start code has the database initialization strategy set to DropCreateDatabaseAlways.
Whenever I try to actually unit test a presenter and a mocked view, I end up running into too many database dependencies
public EditAccount(IAccountEditPage _view, ISession _session, IResponse _response)
{
}
public void view_SaveUser()
{
//Class that takes the view's data and persists it to DB
}
Obviously I can't write unit tests for this presenter because I have a concretion of using my model class that has a strong database dependency.
How am I supposed to removed the dependency on the database without constructor injecting every class that touches the database in my presenter? I don't want to do this every time in every view I have.
I'm using moq, if it helps.
Edit : Also I should mention that the code in "view_SaveUser" is very lean and isn't direct database access or anything like that. It's usually only a few lines. I'm not overstepping the scope of the presenter, AFAIK.
If you don't want to inject the instances on the constructor another option you have is using a setter injection using a IoC framework as Spring.Net or Castle Windsor to inject the dependencies.
Doing this, you would only need to specify on the framework configuration which classes are used for real code and for test project, dependencies would be automatically injected and you would avoid having to use the contructor.
I have a database called ApplicationName_Development running on SQL Server 2008 R2 Developer edition on my development box.
I added .NET membership tables to the database with no problem. When I tried to get Code First working I received the following error message:
The server encountered an error
processing the request. The exception
message is "Model compatibility cannot
be checked because the database does
not contain model metadata. Ensure
that IncludeMetadataConvention has
been added to the DbModelBuilder
conventions.
After some googling, I discovered that I had to delete the database and let EF create the database. That's fine but I lost all my .NET membership tables. I can go back in and add the membership tables again but if my model changes and EF needs to recreate the database then I have to add the membership tables in again.
How do I get around this?
This is how code-first work. Main idea of code first is that you do not touch your database because it is responsibility of the model to create the database. If you want to customize your database you must create custom IDatabaseInitializer and add your custom SQL.
public class MyDbInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
// Here run your custom SQL commands
context.Database.ExecuteSqlCommand("CREATE TABLE ....");
}
}
Now you only need setup your cutom intializer on the startup of your application:
Database.SetInitializer<MyContext>(new MyDbInitializer());
If you don't want to do it this way you must manually maintain your database and set initializer to null.
Found a easier workaround here. I hope this helps.
http://www.paragm.com/ef-v4-1-code-first-and-asp-net-membership-service/
Another option could be to use the System.Web.Management namespace. I've had great success with the code below:
string connectionString = ConfigurationManager.ConnectionStrings["MyDatabaseContext"].ConnectionString;
string database = "MyDatabaseName";
SqlServices.Install(database, SqlFeatures.All, connectionString);
It will just create the database and after that you can add users with the standard membership API.
Here's another possibility.
If you look at the MvcMusicStore sample - there's a SampleData class that is responsible for seeding the database on a rebuild. The SampleData class inherits from DropCreateDatabaseIfModelChanges, and overrides the Seed method. This class is passed to the Database.SetInitializer in the Application_Start method in global.asax.
I was getting the same error as you until I changed the parent class of SampleData to CreateDatabaseIfNotExist.
Then you can override the Seed method to insert any data you desire at startup, without it blowing away the database.
While you are developing, create 2 databases and two connection strings. One for SqlMembership (using aspnet_regsql) and one for your EF Application. If you would like to merge them into a single DB in production, just change the connection string in web.config.release to be the same. Then, EF model changes will just drop your apps db and not your membership DB.
By treating your authentication component separately, you will naturally decouple your authentication system from your application system. Then, if you wish to change membership providers, you will be better setup.
As the system grows, you will likely need to support non-pure models without EF code first, so this is a good template for going down that path.
I found the easiest way without playing with anything else was the following.
I ran the application first time with DropAndRecreatedatabase always in the Initilizer.
This created my database for the first time.
Following this I changed this to DropCreateDatabaseIfModelChanges.