MigrationHistory as entity in DbContext in Entity Framework 7 - c#

I'm trying to get the (by Entity Framework generated) table __EFMigrationsHistoryas an entity into my database context:
In Entity Framework 6 this worked fantastically, but did anyone tried it in EntityFramework 7?
What I tried is, to just add a new class __EFMigrationsHistory - but it'd be too easy - there is already a table named __EFMigrationsHistory in the database (thanks...)
Then I read about that HistoryRow, I shall inherit a class from. So I created the class
public class MigrationsHistory : HistoryRow
{
//... constructor etc.
}
started a migration and: I got two migration-history-tables (but only the original one works)
So I read on and searched for interfaces and classes to implement/inherit from. I found SqlServerHistoryRepository - looks nice. I created an new database context inheriting from SqlServerHistoryRepository (like I'd have done it in EF6). - But this is not a context-class, so I can not add it in Startup.cs (like I did with my default applicationcontext)
So I checked the DbContext for maybe add the history-table somewhere (like in EF6), but there is nothing for adding the table to my context.
So: Anyone already tried to add the migration-history to his context? Anyone was successful?

Whilst I experimented with bricelam's answer with no success with EF Core 2.0,
in
Microsoft.EntityFrameworkCore there's a method;
// .NET Core 1.0 + Platform Extensions
// Microsoft.EntityFrameworkCore.Relational, Version=1.1.0.0, PublicKeyToken=adb9793829ddae60
namespace Microsoft.EntityFrameworkCore
{
public static class RelationalDatabaseFacadeExtensions
{
public static IEnumerable<string> GetAppliedMigrations(this DatabaseFacade databaseFacade);
}
}
Call it as follows;
var dbcontext = new DbContext();
IEnumerable<string> history = dbcontext.Database.GetAppliedMigrations();

Mapping to the table by name should work (it is that easy), you just need to ensure you don't try to re-create it (e.g. by accidentally calling DbContext.Database.EnsureCreate())
class MyContext : DbContext
{
public DbSet<AppliedMigration> AppliedMigrations { get; set; }
}
[Table("__EFMigrationsHistory")]
class AppliedMigration
{
[Column("MigrationId")]
public string Id { get; set; }
[Column("ProductVersion")]
public string EFVersion { get; set; }
}

Related

Consuming View in EF Code First conflicts with migration

I have a Table "IncomingChecks" in my database. I've created it using EF Code first. Now, I've added a view to my database based on this table named "ViewIncomingChecks" using Sql Server Management Studio and I want to use its data in my app using Entity Framework.
I copied the model class and changed its name and added it to the context:
public class ViewIncomingCheck
{
[Key]
public int Id { get; set; }
//...
}
public class CheckDataContext : DbContext
{
public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks { get; set; }
//...
}
now when I run the app, it throws an exception saying the DB Context has been changed and needs a migration. I even tried to add a migration (which seems to be the wrong option) and when I add the migration, it says that the object ViewIncomingChecks is already in the database.
How can I use this view in my code?
Edit
My current solution is to have another context just for the views. This way it doesn't conflict with the EF Migrations. Is this the best option or is there a better way to deal with it.
According to what I have done in my project:
First add public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks
{ get; set; } to your DbConext
Now create a migration something called ViewDbSetAdded
Remove all the code from the both Up and Down method and it will look like as follows:
Migration Code:
public partial class ViewDbSetAdded : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Now run update-database command and it will run an empty migration.

Entity Framework 7 Update DbContext after migration

I've got an existing DB and new WPF project.
1) I scaffolded db context with Scaffold-DbContext and recieved DbContext.cs and a file for each entity that represents a DB tables. That's OK.
Here is example of one of them:
public partial class SomeEntity
{
public long SomeEntityID { get; set; }
public int SomeInt { get; set; }
}
2) I've manually updated this entity (no changes in DbContext.cs) :
public partial class SomeEntity
{
public long SomeEntityID { get; set; }
public int SomeInt { get; set; }
public string SomeString { get; set; }
}
3) I've used Add-Migration command. Now I've got a migration file that describes required changes and DbContextSnapshot.cs. Snapshot includes changes I've just made with SomeEntity. Database is not updated.
4) I've used Update-Database command. Database updated to match last migration. But my DbContext.cs doesn't know anything about changes in DB. It is still the same old good DbContext that I had after scaffolding DB.
Is this OK? Should I now change DbContext manually to match changes that I've made to my entities and applied them to DB? Is there a way to update DbContext.cs from DB after changes without 'rescaffolding'? (Because, for example, all comments and attributes in entity files will be lost, because they will be replaced with new ones if I use Scaffold-DbContext again)
You will have to run scaffolding again, but keep in mind that the generated classes are partial, so you can put your changes in another file

Entity Framework 6 DBContext with only a subset of all tables

We have a huge database with 770 tables and want to do some performance testing with EF 6.1x.
We want to query only 5 of those 770 tables. Is it possible to create a "light" DBContext with only 5-6 entities/DBSets instead of using the full 770-tables-context?
When we use the full context, a simple query with 4 joins takes 45 seconds. Thats' 44 seconds too long.
We are using code-first (reverse engineered).
The problem:
When we create such a "light" version of the full context (i.e. 5 tables only), EF complains that all the other entities that are somehow related to these 5 tables have missing keys. We only map the keys, properties, relationships for those 5 tables, but not the rest.
Since the query written in LINQ only queries 5 tables, EF should simply ignore the other 765 tables, but it won't.
Why not? LazyLoading=true/false doesn't seem to have any bearing on this.
Note: Obviously one could create a view in the DB that does what we do in code with a LINQ query. The question is can it be done with a "light" DbContext as above.
There's the "light" version of the context:
public class ItemLookupContext : DbContext
{
static ItemLookupContext()
{
Database.SetInitializer<ItemLookupContext>( null );
}
public ItemLookupContext()
: base( "Name=ItemLookupContext" )
{
//Configuration.LazyLoadingEnabled = true;
}
public DbSet<Identity> Identities { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<Price> Prices { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Brand> Brands { get; set; }
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Configurations.Add( new IdentityMap() );
modelBuilder.Configurations.Add( new ItemMap() );
modelBuilder.Configurations.Add( new PriceMap() );
modelBuilder.Configurations.Add( new DepartmentMap() );
modelBuilder.Configurations.Add( new BrandMap() );
//ignore certain entitities to speed up loading?
//does not work
modelBuilder.Ignore<...>();
modelBuilder.Ignore<...>();
modelBuilder.Ignore<...>();
modelBuilder.Ignore<...>();
modelBuilder.Ignore<...>();
}
}
what you trying to something like "Bounded Context" which is one of DDD patterns
So, you can check this article by Julie Lerman, Shrink EF Models with DDD Bounded Contexts
Simply just create your DBContext for your tables. To prevent Entity Framework moaning about the not mapped tables, you have switch off the db initialization in your application. Put this in your global.asax/Startup.cs
Database.SetInitializer<YourDbContext>(null);
It tells EF to stop comparing your actual DB structure against your DbContext.
It also means that if someone changes your EF mapped tables, you have no chance of getting notified about that.
When you have a many-to-one relation between class A and class B:
public class A
{
public B b {get; set;}
}
public class B
{
public ICollection<A> As {get; set;}
}
and define following DbContext, EF automatically includes DbSet<B> to the DbContext:
public class MyContext : DbContext
{
...
public DbSet<A> As { get; set; }
}
So, if you want your light DbContext does not includes the related DbSets, simply use Ignore method:
public class MyContext : DbContext
{
...
public DbSet<A> As { get; set; }
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Ignore<B>();
}
}
It looks like you used a tool like Entity Framework Power Tools to generate the entity classes and mappings. This would have generated a class for each table in the database, a huge context, mappings for all these classes and all possible associations. This is way too much.
First remove all classes and mappings that you don't need. Then remove all associations to removed classes in the few classes you have left, not the primitive foreign key fields. Also remove all DbSets from the context except the few you need.
This slimmed-down class model will be consistent in itself. It won't have associations to all entities in the database, but it will be possible to filter by foreign key values that refer to entities outside the context.
If you generated/created the code in any other way this is still the crux: only use navigation properties to other classes in the class model. For other references use primitive foreign key properties.

Set up database creation/migrations from code for Entity Framework 6 + MySQL

I've previously used NHibernate and Fluent Migrator in projects to create a database (if it didn't already exist) and update the schema through migration scripts. I'm looking over Entity Framework (6) to do a comparison and I'm having trouble replicating that functionality.
In my App.config, I've set up my connection string and db providers. I then went ahead and created a data model that I would like to be represented as a table in the database.
namespace DataModels
{
public class StoreClient
{
public int Id;
public string DisplayName;
public StoreClient()
{
}
}
}
I then went ahead and created a database context.
namespace DataModels
{
public class StoreContext : DbContext
{
public DbSet<StoreClient> StoreClients { get; set; }
}
}
On service start I created an instance of StoreContext and tried to add and call db.SaveChanges();, but this is failing because there is no schema that matches my StoreClient.
My question is simple. How do I configure my StoreContext (or EF in general) to automatically create my database schema, and how do I set it up to migrate when I make changes to that schema?
This seems simple, but my searching around hasn't gotten me anything that looks remotely familiar coming from the NHibernate world.
If you want your db to be created automatically try to put some code in your Application_Start() method.
for example:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<StoreContext, Configuration>());
StoreContext context = new StoreContext();
context.Database.Initialize(true);
Where Configuration class is created upon automatic migrations are enables in the console. Check out this msdn demo.
Also i am not shure that your code firs model will work that way. If not try changing your fields with properties.
namespace DataModels
{
public class StoreClient
{
public int Id { get; set; }
public string DisplayName { get; set; }
public StoreClient()
{
}
}
}

Code First Entity Framework not building database

I am trying to implement Entity Framework using code first but it is not building the database tables. I'm not sure what i'm doing wrong. I am using this tutorial -http://msdn.microsoft.com/en-us/data/jj193542 but I am trying to use it with a web application instead of a console application. I created a Models folder and put my context class in that folder. Here is my dbcontext code:
namespace GroceryAssistant.Model
{
public class GroceryShopperContext : DbContext
{
public DbSet<List> Lists { get; set; }
public DbSet<ListItem> ListItems { get; set; }
public DbSet<User> User { get; set; }
}
}
I created put the connection string in the web.release.config and the web.debug.config files. I'm not sure what else I have to do. Where should i put my DbContext code so that the tables will be created?
If you do not change the default behavior, the first time you use the DbContext it will create your database.

Categories