EF Code first database/table initialization - WHEN does it happen? - entity-framework-4

My application is using EF code-first design and all generally works very well.
Via a private configuration file, I can specify how I would like EF to handle changes to the db schema, and so create/recreate the relevant tables as desired - the options are "never" "create", "always", "onSchemaChanged" and (for the future) "onSchemaModified".
This works well - but I am getting lost in a couple of places .....
During development, I would like to use the hook as described in
"Database in use error with Entity Framework 4 Code First" - but this seems to execute on EVERY run of my program"
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context); // Maybe this does nothing if not needed
context.Database.SqlCommand("ALTER DATABASE Tocrates SET MULTI_USER")
}
So .. to real my question: Is there an override that I can use to detect whether EF will ACTUALLY be trying to modify the database, so I can set this SINGLE_USER stuff when needed? And if so, can I detect the reason EF it is doing so (see my list of options above) so I can log the reason for change?...
All help and suggestions are very much appreciated.

Unless you have set the database intializer to null initializers run always once (per application lifetime) when you are using a context for the first time. What then actually happens depends on the initializer (your inner _intializer):
For DropCreateDatabaseAlways and CreateDatabaseIfNotExists it's clear by their name what they do.
For DropCreateDatabaseIfModelChanges there is only the question if the model changed or not. EF detects this by comparing a model hash with a hash stored in the database. You can check this yourself by calling...
bool compatible = context.Database.CompatibleWithModel(true);
...within your custom InitializeDatabase and then decide based on the result if you want to send your SqlCommands or not. (Don't call this with a self-created context because it will cause the database to be intialized first before the model compatibilty is checked.) The parameter bool throwIfNoMetadata (which is true in my example) causes EF to throw an exception if the model hash in the database does not exist. Otherwise the method will return true in that case.
For a custom inner initializer: Whatever your code will do.

Related

typo3 flow isDirty on model

Im trying to find out which attributes of an entity have been changed.
As far I have seen, there is a PersistenceSession with a method to check an object if an attribute isDirty. But its always true because it never registers the old object.
So if I take the demo from the QuickGuide and override the update method in the CoffeeBeanRepository:
/**
* #param \Acme\Demo\Domain\Model\CoffeeBean $coffeeBean
*/
public function update($coffeeBean) {
\TYPO3\Flow\var_dump($this->persistenceSession->isDirty($coffeeBean, 'name'), "name changed before");
parent::update($coffeeBean);
\TYPO3\Flow\var_dump($this->persistenceSession->isDirty($coffeeBean, 'name'), "name changed after");
}
... its always TRUE (both), despite I didn't change anything.
Anyone an idea/reference how this can be accomplished?
I am using it for a REST API where a user can't update several fields and on editing of some fields additional actions have to be executed.
The persistenceSession is part of the generic persistence backend of Flow and is neither maintained, nor really used unless you explicitly deactivate doctrine. Hence persistenceSession will not help you, because all entities are considered new for the persistenceSession as you noticed.
With doctrine you need to get the entity changeset from the "UnitOfWork", which you can get from an injected \Doctrine\Common\Persistence\ObjectManager. See also Is there a built-in way to get all of the changed/updated fields in a Doctrine 2 entity
However, this is a suboptimal solution and a hacky work-around at best. If you need to track changes to your entity, it should be an explicit part of your domain model. For example make your setters record a changed properties list, when the given value is different from the current.
When done, you could even optimize doctrines change tracking on the way with that: http://doctrine-orm.readthedocs.org/en/latest/reference/change-tracking-policies.html#notify

How can I get the current connection

Given Scenratio:
We've built a web application using Asp.net MVC and Entity Framework Code First, which builds a database dynamically for each customer.
Given a connection string (connectionStr) and a certain Configuration, We've made Add Migrations [Name] in order to create an empty migration, which has an empty Up function. We did that on purpose.
We don't wanna use automatic migrations here - we want full control, so we have a program making the migrations using a DbMigrator Class.
Our goal is to run a manual Seed inside this Up function.
This is some of the code incharge of making the migration, which indeed works perfectly:
Dim myConfiguration As New SomeNamespace.Migrations.Config1.Configuration
myConfiguration.TargetDatabase = New Infrastructure.DbConnectionInfo(connectionStr, "System.Data.SqlClient")
Dim dbMig As New Entity.Migrations.DbMigrator(myConfiguration)
If dbMig.GetPendingMigrations.Count > 0 Then
dbMig.Update() ' This makes the Up function work - the problem is inside it.
End If
Problem:
The problem is that when the Up function of the Migration is run, we cannot get the database context. We need it in order to make a Seed.
We hope that there's a way to get the Configuration object (myConfiguration) used to initiate the DbMigration (dbMig) instance, or some other way, so we can get the database context (maybe getting the ConnectionString somehow).
Help getting access to one of configuration object / database context / ConnectionString - would be very appreciated.
I don't think so, because what Up method does is filling Operations collection, and DbMigrator class actually executes these operations. So there is no 'context' when up is called.
What you can do is get connection string via ConfigurationManager class directly

Benefits of object.get() vs object.read() in Grails

I was skimming some of the Grails documentation and found this bit about the read() method in Grails. If I'm understanding this correctly, you can pull a "read-only" version of an object from the database that will only be saved on an explicit save() call. It seems to me then, that you should use a read() call whenever you have an object that you don't expect to be changed.
But why wouldn't you just always use a read() call? Since the object will be changed to read/write permissions if you save() it anyway, wouldn't it be safer to just read in the object instead of getting it?
You're probably correct - it'd be equivalent in most cases. But Hibernate doesn't require that you call save() since it does dirty checking during a flush and since Grails uses an "Open Session in View" interceptor there will always be a flush at the end of each request. This surprises people who make changes in an instance retrieved by get() that were meant to only be temporary while rendering the view but then the changes get persisted anyway without a save() call. read() would make more sense in that scenario.
One performance optimization is to use http://grails.org/doc/latest/ref/Database%20Mapping/dynamicUpdate.html to only push changed fields to the database. The default is to push all fields whether they're changed or not since then there's no need to generate new SQL for each update. If you read() an instance Hibernate doesn't keep the original data so dynamic update wouldn't be possible since there would be no way to know which fields are dirty.

Understanding VS's ability to create database on first run

I'm working with a (.net4 / mvc3 ) solution file downloaded (from a reputable source) where a connection string exists in web.config but I don't see explicit instructions to create the database and there's no included '.mdf'. The first time I build I got a runtime error regarding lack of permissions to CREATE database. So I created a blank db and made sure the string referenced a SQL user that had .dbo/owner rights to the db just created.
But subsequent builds don't seem to execute that same initialize db script - where ever that's stored.
Where is this 'first use' convention for creating databases documented?
thx
That is a feature of Entity Framework Code First. I am not sure what you are looking for exactly, but searching for "EF Code First Initialization Strategy" might help.
For instance read this article: EF Code First DB Initialization Using Web.Config
I assume you are talking about Entity Framework, which allows you to create the database from an instance of an ObjectContext object, which is used in any of the three approaches in EF (database-, model- and code-first).
Look for a line that actually calls ObjectContext.CreateDatabase(). If one of the supported ADO.NET provides is used (SQL Server or SQL Server CE 4.0) this will generate the required SQL Statements. Assuming the classic Northwind example, you might find something like that:
NorthwindContext context = new NorthwindContext();
if (!context.DatabaseExists())
{
context.CreateDatabase();
}
If this is in fact a code-first application, "lalibi" is right about the initialization strategy which by default doesn't require you to explicitly create the database. (But my guess is, that it actually uses a statement internally very similar to mine).

Where is modelBuilder.IncludeMetadataInDatabase in EF CTP5?

With CTP4, I used to be able to do the following (as suggested by ptrandem):
modelBuilder.IncludeMetadataInDatabase = false
With this line of code, EF doesn't create the EdmMetadata table in my database, and doesn't track model changes.
I was unable to find a way to accomplish this in the new CTP5, so now every time I change my model, I get this:
The model backing the 'MyContext'
context has changed since the database
was created. Either manually
delete/update the database, or call
Database.SetInitializer with an
IDatabaseInitializer instance. For
example, the
DropCreateDatabaseIfModelChanges
strategy will automatically delete and
recreate the database, and optionally
seed it with new data.
So, does everybody know where is the IncludeMetadataInDatabase property in CTP5? Thanks.
CTP5 includes a very cool feature called Pluggable Conventions that can be used to Add/Remove conventions. IncludeMetadataInDatabase has been removed and being replaced with a
pluggable convention that does the same thing for you:
modelBuilder.Conventions
.Remove<System.Data.Entity.Database.IncludeMetadataConvention>();
The equivalent in CTP5 to switch off initializer logic: In your Application_Start in Global.asax, enter the following:
System.Data.Entity.Database.DbDatabase.SetInitializer<MyDBContext>(null);
In EF 4.1
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
Have been looking for this all over, and I had to find the answer right after posting my question, DUH. Right from the ADO.NET team blog:
In CTP5 we have removed the need to
perform additional configuration when
mapping to an existing database. If
Code First detects that it is pointing
to an existing database schema that it
did not create then it will ‘trust
you’ and attempt to use code first
with the schema. The easiest way to
point Code First to an existing
database is to add a App/Web.config
connection string with the same name
as your derived DbContext (...)

Resources