OnModelCreating - forcing new creation - entity-framework

In some situations, during the application run, I need to turn on identity insert:
modelBuilder.Entity<Activity>().Property(p => p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
But, since OnModelCreating is executed only once, what would be the best way to achieve this? Is it possible to recreate model?

OnModelCreating will always be called only once. If you need to recreate model you must manually create DbModelBuilder.
var builder = new DbModelBuilder(DbModelBuilderVersion.Latest);
// setup whole model
DbModel model = builder.Build(connection);
DbCompiledModel compiledModel = model.Compile();
// cache compiledModel for future usage - compilation is very expensive
var context = new DbContext(compiledModel);
You should try to avoid this. Identity insert doesn't work very well with EF so you will most probably have to insert data directly with SQL and that doesn't need changing the mapping.

Related

EF6 Force in-memory model creation for code-first before data access

As far as I know for code first the in-memory model is created on the first data access leading to a delay on a first data access (several seconds in my case).
Is there a way to force the in-memory model creation on application start to avoid delay during the first data access?
Thanks.
You can initialize the database by using an EF database initializer and calling the IDatabaseInitializer<TContext>'s InitializeDatabase method.
You can use any of the built-in database initializers to do this.
An example using the DropCreateDatabaseIfModelChanges initializer in the Application_Start method of Global.asax:
protected void Application_Start()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DataContext>());
using (var context = new DataContext())
{
context.Database.Initialize(false);
}
}
The DropCreateDatabaseIfModelChanges initializer will check to see if there are any model changes each time your application starts and if there is, it will drop and recreate the database based on the latest model.
You can use one of the following initializers instead of DropCreateDatabaseIfModelChanges:
CreateDatabaseIfNotExists
DropCreateDatabaseAlways
MigrateDatabaseToLatestVersion (if you're using DbMigrations)

Best way to save a sometimes store-generated column

I have an entity that has one column with strange behavior. On insert sometimes it is set to a value passed by the application and sometimes it uses the newly-created identity value from another column. This is currently implemented using a stored procedure. Is there a clean way to do this with Entity Framework?
I'm using Entity Framework 6 with Code First, but I'm not doing database generation or using migrations.
I know that I can essentially use a DbContext.Database to manually call a procedure as if I'm not using EF, but then I lose all of EF's automatic updates of the entity on save, participation in a SaveChanges transaction, etc. What's the best way to mitigate this?
Edit:
I will try to describe my ideal solution in pseudo code. The question is really how close can I get to this with real code given Entity Framework 6's current functionality.
Ideally I could just configure a column to sometimes be an "identity" column. In other words, sometimes generated by the database on insert, sometimes not. Something like this:
public sealed class WidgetConfiguration : EntityTypeConfiguration<Widget>
{
public WidgetConfiguration()
{
HasKey(d => d.Id);
Property(e => e.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(e => e.Number)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.SometimesIdentity);
MapToStoredProcedures(s => s.Insert(i => i.HasName("InsertWidget")));
}
}
Since this is not possible, I'm wondering if there is some other way of participating in SaveChanges so that I can take advantage of the EF goodness like dependency analysis and automatic transaction management rather than:
Creating a transaction
Populating a context with new/changed entities that a Widget depends on and saving it.
Inserting the Widget.
Populating a context with new/changed entities that depend on the Widget and saving it.
Committing the transaction.
In other words, is it possible to tell EF, "Hey, I know how to save Widgets. Here's a callback when you need to save one." or something like that?
EF does not refresh the entities that may be affected by a StoredProcedure you have to do it manually by calling:
dbContext.Entry(myEntityToRefresh).Reload();
//or
dbContext.Entry(myEntityToRefresh).ReloadAsync();
Please change the title of this question. It says nothing.

How to clear Validation Results in an Entity Framework Object

It is possible to clear the Validation Results in an ObjectContext associated with an Entity Framework? What I wanted is something like this code:
public void ClearValidationResults (ObjectContext db)
{
var dbContext = new DbContext(db, true);
var validationResults = dbContext.GetValidationErrors();
validationResults.Clear();
}
I want to implement this functionality to use in unit tests to test the validation rules without to have to save changes in DataBase.
Thanks.
DbContext does not store validation errors, it validates entities each time you call DbContext.GetValidationErrors() or DbContext.SaveChanges(). So, if you have an invalid entity that is being tracked by your context DbContext.GetValidationErrors() will always return errors. You need to detach or fix the invalid entity/entities and the error will go away since there will be no invalid entities tracked by your context.
Clear Entity Local Storage.
When we adding Entity to Collection, its adding it to its Local Storage and we kept getting errors as the Local Storage of that Entity is not clear and still having old entries. So you Clear Entity Local rows.
dbContext.EntityName.Local.Clear();
I resolve the problem by creating a new ObjectContext object every time I need to clear the validation errors. Is not the most elegant solution but it works. Since this process is in the context of unit tests and the unit tests are fast enough, I will maintain this code until best solution arrived.
public void ClearValidationResults (ObjectContext db)
{
db = new MyObjectContext();
}

View's in Entity Framework won't update

I have a view which includes data from multiple tables.
When I call that view, the results are loaded into the memory and stored. After I make some changes to the other tables which should effect the view, the view don't know anything about the changes.
So when I call that view again, for example a Get() method, EF returns the values of the stored data.
Of course I want the updated data. How can I force the view to get the data from DB and not from memory? Or is there a better strategy?
Better if I can make the view aware of the changes being made. Is this achievable with entity configuration, maybe by using HasRequired() method to map FK's?
EDIT:
I am using repository and unit of work pattern. So I am not creating and disposing a new context each time. Please consider this.
When you execute the Linq query on the view use AsNoTracking() extension method. This will force EF to always use data from database instead of memory:
var result = from x in context.ViewSet.AsNoTracking()
select x;
EF will not handle any automatic data refresh for you.

Best way to incrementally seed data in Entity Framework 4.3

I have been using Entity Framework 4.3 on an existing database and I have a couple of scenarios that I am trying to cater for.
Firstly, if I delete my database I would like to EF to recreate if from scratch - I have successfully used a CreateDatabaseIfNotExists database initialiser for this.
Secondly, if I update my model and the database already exists I would like the database to be updated automatically - I have successfully used Entity Framework 4.3 Migrations for this.
So here's my question. Say I add a new table to my model which requires some reference data, what it the best way to ensure that this data gets created both when the database intialiser runs and also when the migration runs. My desire is that the data gets created when I'm creating the db from scratch and also when the database gets updated as the result of a migration running.
In some EF migrations examples I have seen people use the SQL() function in the UP method of the migration to create seed data but if possible I would rather use the context to create the seed data (as you see in most database initialiser examples) as it seems strange to me that you would use pure sql when the whole idea of EF is abstracting that away. I have tried to use the context in the UP method but for some reason it didn't think that a table that was created in the migration existed when I tried to add the seed data directly below the call to create the table.
Any wisdom greatly appreciated.
If you want to use entities to seed data you should use Seed method in your migrations configuration. If you generate fresh project Enable-Migrations you will get this configuration class:
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(CFMigrationsWithNoMagic.BlogContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
The way how migrations seed data are not very efficient because it is supposed to be used for some very basic seeding. Every update to new version will go through whole set and try to update existing data or insert new data. If you don't use AddOrUpdate extension method you must manually ensure that data are seeded to database only if they are not present yet.
If you want efficient way for seeding because you must seed o lot of data you will get better result with common:
public partial class SomeMigration : DbMigration
{
public override void Up()
{
...
Sql("UPDATE ...");
Sql("INSERT ...");
}
public override void Down()
{
...
}
}
I wouldn't recommend using Sql() calls in your Up() method because (IMO) this is really intended for actual migration code for which there is no built-in function, rather than seed code.
I like to think of seed data as something that could change in the future (even if my schema does not), so I simply write "defensive" checks around all of my inserts in the seed function to make sure that the operation did not fire previously.
Consider a scenario where you have a "Types" table that starts out with 3 entries, but then you later add a 4th. You shouldn't need a "migration" to address this.
Using Seed() also gives you a full context to work with, which is a lot nicer than using the plain sql strings in the Sql() method that Ladislav demonstrated.
Also, keep in mind that the benefit of using built-in EF methods for both the migration code and seed code is that your database operations remain platform-neutral. This means your schema changes and queries are be able to run on Oracle, Postgre, etc. If you write actual raw SQL then you are potentially locking yourself in unnecessarily.
You might be less concerned about this since 90% of people using EF will only ever hit SQL Server, but I'm just throwing it out there to give you a different perspective on the solution.