Well, the question is clear enough. Is it possible to create spatial indexes using Entity Framework 6.1 fluent API?
The only way I know to do this is through a "custom" migration. In EF6, I add a migration (in the example below it's named "V1"), resulting in an new migration with empty Up() and Down() methods. You can then add custom SQL commands to these methods before running update-database to put these in the "normal" migrations flow.
It's possible to modify an existing migration to add these features, but I prefer in practice to keep my automatically scaffolded migrations separate from my customized ones.
public partial class V1 : DbMigration
{
public override void Up()
{
Sql("CREATE SPATIAL INDEX [IX_UserProfileAddresses_Location] ON [dbo].[UserProfileAddresses](Location)");
}
public override void Down()
{
Sql("DROP INDEX [IX_UserProfileAddresses_Location] ON [dbo].[UserProfileAddresses]");
}
}
Not an ideal method, but not too bad since it does follow the "normal" migrations pattern for EF.
Short answer- No, it is not. I have seen this tangentially referenced throughout blogs and have found no concrete examples of implementation. It seems to be related to the fact that spatial indexes are filtered indexes, which are not supported in Entity Framework.
As support for my answer I constructed a POC console app with the most recent version of Entity Framework (6.1). I took the following steps
Created a model that had a property of the type DbGeography
Enabled automatic migrations
Ran Update-Database -verbose insuring migration with the addition of an index was run. The index used the following:
modelBuilder.Entity<LocationEntity>().Property(t => t.Coordinates).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("ix_locationentity_coordinates")));
No indexes were created, but neither did the app crash. I could try permutations on this, but my example seems to follow the convention of entity framework: Official Fluent Documentation
Related
I would like to use a Database First approach to managing my database with EF Core, and not just for the initial database creation. I'm using this command to generate my entity models and mapping code:
Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=MyDB;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models/Entities -f
Now this works fine. I'm just struggling with identity integration. Currently I have two separate contexts, the one generated by the scaffolding command and an identity context that looks like this:
public class IdentityContext : IdentityDbContext<ApplicationUser> {
public IdentityContext(DbContextOptions<IdentityContext> options)
: base(options) {
}
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);
}
}
Both contexts read from the same database and are registered like this:
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<IdentityContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Is it reasonable to have two separate contexts? Will it cause future problems as I start creating relationships between users and other models? I couldn't find anything in the docs regarding continued use of db-scaffold to generate my entity models and mappings.
Let me know if I can clarify anything.
ORIGINAL CONTEXT
Okay so clearly my original question wasn't any good.
I'd just like some clarification on if my Database First workflow with .NET Core and Entity Framework is the right way. I've read all the articles I can find about using Database First, which all seem to end with: "now you have scaffolded your database so can start using Code First migrations". I want to continue writing my SQL and just keep mapping it to entities.
To manage and update my application I'm using the excellent DbUp project. So I write my scripts, apply them to the database
This appears to be working fine so far. My only problem is integrating identity nicely. Currently I just have two contexts, my application one and an identity one. My application one has also mapped all the identity tables. It is working fine but I'm not sure what will happen going forward as I start linking tables to the user... I believe I did make it work with one context but I had to modify the generated application context each time, removing all the Identity mappings and inheriting from IdentityDbContext (to generate the identity mappings). I could change the schema of the identity tables/my tables and just generate the mappings for my tables, excluding the identity tables. Then I will probably need to manually write mapping properties on ApplicationUser, is that correct?
Basically, I'm not really feeling like Database First is a first class citizen in .NET anymore. Am I just missing something obvious to have this kind of just "work" without modifying generated code? Or am I overthinking this and just need to get on with it?
Apologies for the rambling, one of those days I guess.
I am new to EF Core, and as I tried using it I found out that you need to add migrations for it to create a database from models. My question is, do we have another option aside from migrations to dynamically create the database on run time just like what it was in EF 6?
Thanks.
Until a seeding mechanism is provided in EF Core you can provide your own seeding mechanism.
In earlier phases of a project, when the database is not yet fixed, I don't care that data get lost. When I want to recreate the database dynamically I call the function below. By the setting of a parameter I determine if this "recreateDatabase"-function is called yes or no. The function is included in MyOwnDbContext class.
The seed function you need to write is very similar to the one you use in EF 6.
private static void recreateDatabase(YourOwnDbContext dbContext)
{
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
seed(dbContext);
}
I am still in the process of porting my old MVC project to the latest asp.net 5 MVC and EntityFramework 7. To accomplish this I first reverse engineered an existing database from the old project using the ef commands. That created all of my model classes correctly (or mostly so). I have manually edited the code to get through all of the initial errors. I have that compiling with almost no additional code from the original project. In other words I only have the model classes, and the DbContext class so far in the solution. All of this is in an assembly and I have no migrations at all in the codebase, just the Migrations directory. What I thought would make sense is to add a migration to baseline the database from what was reverse engineered. I should mention that my DbContext inherits from IdentityDbContext
public partial class STOrmContext : IdentityDbContext<ApplicationUser>
{
}
My project is split into two components. All database and models in an assembly, and MVC stuff in a separate project.
when I type
dnx ef command migrations add Initial
I get the following error message
The entity type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin<string>' requires a key to be defined.
I guess I just don't really understand how to bootstrap a legacy database into EntintyFramework 7. Can someone point me in the right direction.
I found the answer myself.
It turns out it was a couple of things I was not addressing.
When I reverse engineered the old database it created models for the
identity stuff from the legacy application.
I deleted those.
I also needed to call the base OnModelCreating() so that it could configure
Identity stuff.
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
}
I guess I should have paid more attention to what was really happening before jumping to a question on StackOverflow
I'm trying to update the database on a build server, and it's failing because it's trying to run automatic migrations, even though they're disabled. The database already exists and I just need to apply the latest migration. Here's my context:
public sealed class Configuration : DbMigrationsConfiguration<CableSenseInstanceConfiguratorContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
I've got a bunch of migration files I've created manually, here's the latest one:
public partial class Settings : DbMigration
{
public override void Up()
{
AddColumn("dbo.MasterInstances", "Settings", c => c.String());
}
public override void Down()
{
DropColumn("dbo.MasterInstances", "Settings");
}
}
If I then manually update the database from the package manager console, I see it tries to run an automatic migration (which fails because the table already exists):
Applying code-based migrations: [201204200805145_NoMoreCerts, 201210311451543_SuperUsers, 201301041036414_Settings, 201301041128583_Settings2].
Applying code-based migration: 201204200805145_NoMoreCerts.
Applying automatic migration: 201204200805145_NoMoreCerts_AutomaticMigration.
My __MigrationHistory table just has the one entry for the initial creation. How can I stop it from doing the automatic migrations?
Check out the answer from jjslagace here:
Update-Database tries to do an automatic migration even with automatic migrations disabled
You are building your migrations manually. My guess is entity framework wants to add something that you don't have in your migration script, or it wants to name columns differently etc. EF has a brain, and that brain is fairly simple. It's expecting things to be a certain way unless you tell it otherwise using fluent (not by manually creating/tweaking migration files). From the answer on the question above it sounds like sometimes that results in the issue you are seeing.
Long story short don't build the migration files manually. Instead run the add-migrations command. This will create the migration for you and you can see what EF is expecting to do before it's applied to your database (because sometimes it's stupid). If you need to override what EF is generating for you add a fluent mapping in your DBContext class by overriding OnModelCreating. Then just run add-migration again with the -force option. Here is a good reference for using the Fluent API to custimize EF mappings. Rinse and repeat until you get the migration you are looking for then run update-database.
Hope that helps!
There are many tutorials on Fluent API, but they all explain it using Entity Framework Code-First code examples. Since I don't know Code-First, do you know of any Fluent API tutorials that would explain the subject using EF Database-First approach?
Thank you
There are no tutorials which would explain the Fluent API together with Database-First approach because Fluent API is made only for Code-First approach. You don't need the Fluent API if you want to create your model via Database-First.
Fluent API (together with Code-First data annotations and conventions) is a tool to define model details in code, such as string length, if a property is required or the type of relationship - many-to-many, one-to-many, etc. When using Database-First or Model-First the EDMX file has the same purpose - it contains all the details and mapping definitions of your model. Fluent API (+ data annotations and conventions) replaces the EDMX file only when using Code-First.
If you create the model via Database-First or Model-First, you will have an EDMX file representing your model. You can apply the T4 DbContext Generator to this EDMX file. The generated files have two characteristics being different from Code-First:
The generated connection string contains a section refering to the EDMX metadata which will be embedded into your assembly:
connectionString="metadata=res://*/Model.csdl
|res://*/Model.ssdl
|res://*/Model.msl;
..."
The generated context DbContext will have an overridden OnModelCreating method which just throws an exception:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
As long as you leave the metadata section in the connection string, EF won't even call OnModelCreating or any code in Fluent API in this method. The metadata section tells EF that your model is DB- or Model-First and that the metadata are defined in the embedded EDMX and not in Fluent API.
However, you can remove the metadata section from the connection string, remove the UnintentionalCodeFirstException and write code with Fluent API in OnModelCreating. You can follow this procedure to create an initial model via Database-First and then build on this initial model for further development with Code-First.
At this point you are not working anymore with Database-First, but Code-First instead and everything you read about Fluent API is valid for you.
There is an interesting post about accomplishing some of the “Database-First” objectives without employing the actual “Database-First” methodology per se.
http://agilenet.wordpress.com/2011/04/11/entity-framework-4-1-rc-with-an-existing-database/
The author uses “Code-First” and “Fluent API”, but disables the auto-generation and seeding of databases and tables.
He shares a sample that shows “how to create an entity model, then manually create your database and then map those entities to your database. Finally it shows using the DatabaseContext to save and retrieve entities”.
The part where he creates a “configuration class for each entity which maps between the entity and the database” is pretty cool. That step replaces the “edmx” files that would be generated when employing a formal “Database-First” approach.
This tutorial in a 6-part Database First tutorial series includes some fluent API examples:
http://www.asp.net/web-forms/tutorials/continuing-with-ef/using-the-entity-framework-and-the-objectdatasource-control-part-3-sorting-and-filtering