Create SQL View With Entity Framework 6 Code First - c#

I am new to Entity Framework 6 Code First and am trying to perform what I thought would be a simple task. I want to create a SQL View and then have an Entity in my database context that I can use to query the view.
I have tried articles such as this but the key difference in my case is that the SQL View is not an existing view coming from another existing database.
I examined the proposition made in this article but it seems like overkill to me that I would need to create some extension methods to do something as simple as create a view/entity combo and use it in my database context.
Am I missing something? I know it would be much easier if I weren't using Code First but please keep in mind it's Code First and I am trying to create a view, not reuse one from an existing database.

Colin and Kevin, Thank you for the link to your answer on the other post and your concise answer. I have used several resources to finally create a queryable entity based on a new SQL view. Just in case anyone else is new to EF 6.0 Code First and is just getting their feet wet, I do have a few steps that will hopefully benefit others in the future.
It may seem obvious to more seasoned Entity Framework developers, but in order to execute the 'Migration' approach you need to disable automatic migrations and actually dive into the guts of the Code First Migrations inner workings. Since automatic migrations is turned on out of the box, I had already created a fairly complex database with seed scripts all relying on automatic migrations and rebuilding the database on every run of my application. This post helped me wipe my migrations history and get to square 1 with automatic migrations turned off (I went with the web.config approach in case you were wondering)
After I had cleared my migrations information, I deleted the mdf from within solution explorer. That guaranteed that I wouldn't run into any problems when running Update-Database (further down the list of steps).
In the Package Manger console, I then executed Add-Migration Initial to generate an "Initial" migration. The result of this was the editable Up and Down methods as described in Colin's answer. I then followed the steps in Colin's answer by commenting out the table create statement (Entity Framework tries to create a table but we really want to create a view and map it to the Entity) and inserting my own view create sql statement at the end of the Up method. It's important to put the create statement after the creation of any tables that it may depend on. I also performed my Seed activities in the Configuration.Seed method instead of in my Context's Seed method. I see how this would be important if you were dealing with multiple migrations. Finally, as Colin suggested I added the table mapping to my context's OnModelCreating event.
The final step in this was to actually apply the migration to the database. In order to do that, in the Package Manager console you execute the Update-Database command. That statement will rebuild the database with the "Initial" migration you created and edited in earlier steps.
It still surprises me that I need to do all of this custom work to create a view and map it to an entity with Code First, but at the end of the day it was helpful in getting me started on migrations as you can only rely on the "automatic migrations" for so long anyways.

You can manually add the sql to create the view to a migration then consume it as per your first link.

The answer in the link provided by Colin does the job.
In case there are lots of views to be created, it can be a good idea to save the view queries in separate files and add them in a resource (.resx) file instead of hard-coding the sql queries in the Migration Up() method.
For e.g.
public override void Up()
{
Sql("ResourceFileName.ResourceName");
}
instead of hard coding like
{
Sql("EXEC ('CREATE View [dbo].[ClientStatistics] AS --etc");
}

Related

Asp.net MVC DB First Approach - Migrations

For my past Asp.NET MVC projects I have used the Code First approach to create my web applications.
Here I got a new one, there is an old system with an already created SQL Server Database.
I need to recreate a system for the existing database.
So I have started to use Database First Approach.
I connected to the database and models & datasets generated according to the tables.
So I want to know If I want to add a column to the table which I used earlier, update it on the model, and do migration and update the database.
So I can't use it here, right?
If I want to change something, I have to change it from the database from the SQL server side, and then how I updated it on my project?
Personally, I found their database structure is somewhat wrong for certain cases.
But there are already 5000+ data on the tables and they don't wanna lose it or they have not agreed to maintain two databases for their operations.
Ideas for this matter are highly appreciated.
This is a very common scenario. Microsoft calls it Code First with Existing database. You create scaffolding that builds model out of the database. You probably want to apply constraints and generally improve referential integrity in the database and scaffold the model a few times.
Once you are happy with the model - you stop making changes in the database! You are switching to Code First approach, where you make all the changes in the code, create migrations and apply migrations to the database.
I think, Database First referred to the approach in early versions of Entity Framework that created .edmx file. I don't think this approach is even possible today. Certainly, not recommended
So what I have done here on my end using .net core and above was, that I initially created a migration before applying changes to the entities. Then after that, I removed the code inside the initial migration script. e.g.
public partial class InitialDbCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
so that It will not re-create the entities/tables to the existing database, and you'll not have now a problem in applying new changes to your entities.

Do I need a migration for EF code first when the database does not exist in SQL Azure?

I have tried lots of variations of EF migration v6.0.1 (from no database, to empty databases to existing databases) and I have a particular problem with Azure DB instances not being able to correctly be created on first deploy using Octopus deploy.
There are a number of places where this could be going wrong, so I thought I would check some basics of EF Code First migration with you fine people if I may:
If I create a code-first model, and know that the database does not exist in the intended target database server on Azure. With the default of 'CreateDatabaseIfNotExists' approach and with AutomaticMigrations disabled;
If I then call 'migrate.exe' with the assembly containing my DbContext and migration Configuration will I get a new database created with the current state of the model? or will I get a new database with nothing in it? i.e. do I need to explicitly 'add-migration' for the initial state of the model?
I have read in the documentation that the database instance should be created automatically by the migration process, but no one states clearly (at least to me) that this newly created database will be generated with the current model without a formal 'initial state' migration created.
So the question is this: do I need an explicit migration model generated for migrate.exe to work from?
Through whatever means I try, I get a database but the application launches with the unfriendly message "Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations." Remembering that this is the same application library that just created the database in the first place (from scratch) I fail to understand how this has happened!
I did manually delete the target database a few times via SQL Server management studio, is this bad? Have I removed some vital user account that I need to recover?
Migrations and the Database Initializer CreateDatabaseIfNotExists are not the same.
Migrations uses the Database Initializer MigrateDatabaseToLatestVersion, which relies upon a special table in the database _MigrationsHistory.
By contrast, CreateDatabaseIfNotExists is one of the Database Initializers which relies upon the special database table EdmMetadata. It does exactly as it implies: Creates a database with tables matching the current state of the model, i.e. a table for each DbSet<T>, only when the database does not exist.
The specific error you have quoted here, Model compatibility cannot be checked because the database does not contain model metadata., occurs due to the existence of DbSet<T> objects which were added to the code base after the initial database creation, and do not exist in EdmMetadata.
There are 4 basic Database Initializers available, 3 of which are for use when migrations is not being used:
CreateDatabaseIfNotExists
DropCreateDatabaseWhenModelChanges
DropCreateDatabaseAlways
Also note, the 4th Initializer, MigrateDatabaseToLatestVersion, will allow you to use Migrations even if AutomaticMigrations is disabled; AutomaticMigrations serves a diffierent purpose, and does not interact with the Database Initializers directly.
If you intend to use Migrations, you should change the Database Initializer to MigrateDatabaseToLatestVersion and forget about the other 3. If, instead, you intend to not use Migrations, then the choice of Initializer is situational.
CreateDatabaseIfNotExists will be more appropriate when you are certain that your data model is not undergoing active change, and you only intend to be concerned with database creation on a new deployment. This Initializer will elp ensure that you do not have any issues with accidental deletion of a database or live data.
DropCreateDatabaseWhenModelChanges is most appropriate in development, when you are changing the model fairly often, and want to be able to verify these changes to the model. It would not be appropriate for a production server, as changes to the model could inadvertently cause the database to be recreated.
DropCreateDatabaseAlways is only appropriate in testing, where your database is created from scratch every time you run your tests.
Migrations differs from these 3 Database Initializers, in that it never drops the database, it instead uses Data Motion to execute a series of Create Table and Drop Table SQL calls.
You also can use Update-Database -Script -SourceMigration:0 in the Package Manager Console at any time, no matter which Database Initializer you are using, to generate a full SQL script that can be run against a server to recreate the database.
Firstly, many thanks to Claies who helped me get to the bottom of this problem. I have accepted his answer as correct as ultimately it was a combination of his response and a few additional bits of reading that got me to my solution.
In answer to the actual posts question 'Do I need a migration for EF code first when the database does not exist in SQL Azure?' the answer is yes you do if you have disabled automatic migrations. But there is a little more to be aware of:
The Azure aspects of this particular problem are actually irrelevant in my situation. My problem was two-fold:
The migration being generated was out of sync with respect to the target model. What do I mean? I mean, that I was generating the migration script from my local database which itself was not in sync with the local codebase which created a migration that was incorrect. This can be seen by comparing the first few lines of the Model text in the __MigrationHistory. This awareness was helped by referring to this helpful post which explains how it works.
And more embarrassingly (I'm sure we've all done it) is that my octopus deployment of the web site itself (using Octopack) somehow neglected to include the Web.Config file. From what I can tell, this may have occurred after I installed a transform extension to Visual Studio. Within my nuget package I can see that there is a web.config.transform file but not a web.config. Basically this meant that when the application started up, it had no configuration file to turn to, no connections string at all. But this resulted in the slightly misleading error
Model compatibility cannot be checked because the database does not
contain model metadata.
Whereas what it should have said was, there isn't a connection string you idiot.
Hopefully this helps people understand the process a little better after reading Claies answer and also that blog-post. First though, check you have a web.config file and that it has a connection string in it...

Entity Framework migrations under the hood

I've been using Entity Framework migrations for some time and I started wondering how they actually work under the hood. I mean the following:
How does EF understand that the model in the application and the db scheme are different? As far as I know, there's a table __MigrationHistory in the database where all migrations are stored as well as in the Migrations folder in the application (applies only to code-based migrations). In the __MigrationHistory table, there's a column called model which contains some kinda hash. What is that hash exactly? Is it a snapshot of the model? Is it the changes that EF needs to apply to get from the previous migration to this one?
If it was the model snapshot, it would mean EF would have to figure out how to transform the current model to the snapshot each time we decided to update database.
However, if it was the changes, it would mean EF would have to apply those changes to the current model in order to understand when the db model and the application model are different.
The question is, where can I read something about how the migrations are implemented and what is this model column in the database. I would appreciate any advices or links.
Update:
I've checked the resources provided and as I've found out, the model column is actually the snapshot of the model. That means, when I run the update-database command, EF goes to the db, checks the latest migration model by decoding the XML string and if the current model in the application and the model EF got from the db are different, EF generates a script to update the db. However, I still don't know what EF does when there are multiple migrations pending.
I will describe on example based on the example from the https://channel9.msdn.com/Blogs/EF/Migrations-Under-the-Hood. Say, we have First migration in your db, then Second migration, which adds the Url column and the Third one, which drops this column. If I were to apply these changes to the db which contains the schema similar to First, would EF add the column and then drop it according to the Second and Third, or will it try to calculate the general changes that are required to update the db and then execute the generated script (in the example case it would do nothing?
Also, there's another link I've found if anyone's interested
https://msdn.microsoft.com/en-us/data/dn481501.aspx
This Channel 9 video covers the general concepts. This blog post might be more specific to your question. In particular, the author concludes on the use of model column (spoiler: its a compressed XML string you can decompress and inspect, has code to do so).

How to update EF models when using DB Code first?

I have added added Entity Framework to my project and selected Code first from database when creating my models. But the problem is, i couln't find how find how to update existing models and add new models to my project when i make changes on database.
It is very straightforward. Switch on migrations, change/add you classes, create a migration and update your database. See here for example. There are plenty of other sources.
When you change your DB you can run the EF generation again but it will overwrite the existing files so you will lose any changes. If you want to maintain code outside the generated files then you can use partial classes. Or alternatively just code them by hand after the initial auto generation, it's quick once you get used to it! :)

Prefix tables with entity framework automatic code migrations

I started a new project C#, and I used the "enable-migrations" command in the package console window. This naturally added migrations to my project. I then set automatic migrations to true, so that as I call "update-database" it will create my tables for me with all keys and that.
The only problem is that I have multiple websites where want to do this, which all use the ASP.NET membership provider to login. Which through automatic code migrations create a bunch of account tables for me to use. But the tables are all called the same, so if I do this targeting the same database for different sites they will overwrite eachother. So the question I got is this: How can I specify a prefix for my tables created by the entity framework?
I've seen several ideas on how to do this while searching, but they didn't work for me (the necessary properties wasn't there for some reason and so on.)
Thank you
Xenoxsis
I'm not sure how do you plan to do just that - if I'm getting it right you'd want to keep one database (shared) in between number of web sites - yet, have each site has its own membership tables, named differently, with different prefixes, right?
First problem is that for each Db/table name change - you need a 'code to match' - i.e. code first entities and code, the 'migration table' in the Db - and tables are all in sync - so it could all work together as it should. In that sense, just changing script or table names in Db won't work. It has to be done at the level of attributes (as #Steven suggested) or fluent configuration.
Which in your case, it means that somehow you'd need to 'build' separate configurations for each site, deploy them separately (code) to each site - and build one mega Db that contains all the small variants of each merged together.
That's going to be tough to manage - but you could try (what I described above) - I have no idea if it'd work (as this requires lot of 'infrastructure' to try this one) - but maybe along these lines...
put Table attributes (or via fluent config)
Build code - 'vary' the Table names for each - and rebuild (ideally you might need to employ some tool, code-generator to do this automatically in a batch - i.e. you build, copy files externally, change names and repeat)
Build 'migrations' for each case (Table name) also - save migrations
as files - and also do Update-Database -Script to save the actual
scripts for each case (important).
Save each migration - or we can
say a 'script' to represent.
Once done - you'd need to merge the
migrations - scripts - into one big master script - i.e. remove the
identical set of tables (leave just one of course) - and copy all
different sets for membership tables.
Remove the migration table
from the database - as that'd surely be out of sync and won't let you
do anything (or there is also a flag in code I think to just ignore
that, don't have it right now). For details see below in my other
post.
Deploy one master Db - using script you created
Deploy the
specific code - to each of the sites.
Pray it'd all work :)
There must be something smarter - but on the other hand, migrations are not made to work for such scenarios, so it's going to be hard if not impossible to pull this off.
Some general info that might help...
How to synchronize migrations with existing databases - geared toward production scenarios, maintaining Db-s and CF to match. It's not exactly what you need but has a detailed description, possible ways to resolve this which I wrote a while ago...
MVC3 and Code First Migrations - "model backing the 'blah' context has changed since the database was created"
To summarize...
What works for me is to use Update-Database -Script
That creates a script with a 'migration difference', which you can
manually apply as an SQL script on the target server database (and you
should get the right migration table rows inserted etc.).
If that still doesn't work - you can still do two things...(more inside)...
I don't know of anyway to make Entity Framework do this automatically across all entities. But you could force a table name, or schema using attributes or fluent API to get the desired effect. For example:
[Table("[put prefix here]_Users", Schema = "[put schema here]")]
public class User {
// ...
}

Categories

Resources