Entity Framework 5 log database changes at runtime - c#

In an ASP.NET 4.5 C# Entity Framework 5 Code First project I'd like to log the changes being made in the database at runtime (the logging has to be done in the asp.net app, not at the database). Previously, the SQL statements were built by the code, and those statements were simply logged. Now with EF, the object is retrieved via linq to entities, modified and
db.SaveChanges();
is being called. My first idea was to retrieve the actual SQL statements that EF sends to the DB -- this seems to be rather complex, however. I've found many "solutions" for displaying the SQL during debugging, but no simple way for the code to retrieve it at runtime.
So I'm looking for any solution that can log the changes being made (either the SQL being sent to the DB [preferred], or some other form of textual representation of the changes made to the object), and that doesn't require the inclusion of a number of complex debug libraries.

You should try FrameLog
https://bitbucket.org/MartinEden/framelog/wiki/Home
It is not clearly stated but it supports Entity Framework 5

I haven't tested this on EF 4.5 so it may need to be tweaked a bit, but I find for debugging purposes the extension method written at the bottom of this post:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2a50ffd2-ed73-411d-82bc-c9c564623cb4/
Gives me the correct output of my entities.SaveChanges() call. It doesn't require any external libraries and since it's written as an extension method it won't clog up your code.

Related

How to abtract DBMS requests in a .NET program, while being able to alter database during runtime

I am posting this thread because I didn't find any easy way to abstract my db requests like LinQ does, allowing my program to alter dynamically the database, creating tables or fields.
I am using .NET framework 4.0 and SQL Server 2012, on windows.
I have seen a lot of topics on ORMs such as Entity Framework that allows to run migrations on the db at runtime, only they can't be generated at runtime.
For now, my project creates table at runtime by executing hard-coded SQL Server scripts.
Only, I dont want to use specifically SQLServer, I want to use some generic language that generates a script for the right DBMS according to my c# code.
Example :
I want to alter my data design at runtime because my program is actually running on several machines that have their own database.
When I update the program I would like it to create new tables that are used by the new functionnalities.
Let's say I am adding... a QCM for the user.
I have a winform that allows the user to see the questions and answer it.
Now to keep track of the answers, I want my program to create a new table using Linq and then fill it with the answers.
If I understand well, when using Entity Framework with code-first approach :
I would have to use the packet manager console to Add migrations on every machine, before running :
var migrator = new DbMigrator(configuration);
migrator.Update();
Or is there a way to send to the machine a migration file that will updated with migrator.Update(); ?
It sounds like you want to do something that is not a good fit for for EF (or virtually any ORM for that matter). ORM's are generally designed to map a static data model to a static object model.
While it's not impossible to do what you want, it would require a very deep understanding of EF and it's implementation details, to use the lower-level functions as well as Dynamic Linq. Then you'd have to map this to dynamic C# objects that can change at runtime.
Frankly, you're probably better off writing a custom data layer yourself using standard SQLCommand statements.
As far as migrations go, this is generally a development/deployment tool, not a runtime tool.
The SqlCommand class in .net allows direct access to the database, including the execution of arbitrary scripts. This will allow you to send any valid database instruction script to the database, including schema definition scripts. This will allow you to create, define, backup, restore and destroy databases.

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...

Generate EF stored proc methods from command line

I'm using EntityFramework 6 in VS2013 with database-first. When you pull in the database, you can get stored procedures, which builds methods into your context for each proc, as well as classes for each of the return types which it derives from the procedures.
I'm looking for a way to run this from the command line. The closest I can find is EdmGen, but this apparently does only tables.
I've seen EfGen, but aside from this just being a download from some guy with no source code or peer review, it appears to be at least one version behind.
Building the names and parameters of the methods is easy enough - I could do that myself with the SQL Server metadata - however, building the result classes would be tricker, so ideally I'd like to do whatever VS is doing.
Is there an SDK command or something I can pull from Visual Studio to do this on demand? I often have to re-pull my procs (early in the development process so things are constantly changing), and it's a hassle to do it in the UI.
I don't think what you are trying to do is possible from the command line. As you noticed in the EF6 Designer there is no public API for reverse engineering similar to the one exposed by EdmGen. The lack of the API is not actually the biggest problem here - in general models generated by EdmGen and the new designer are semantically the same - the only difference is that in EF6 two new provider manifest tokens were introduced for SqlServer - 2012 for Sql Server 2012 and 2012.Azure for Sql Azure. You will get these provider manifest tokens when targeting the above databases with the new designer but when using EdmGen you will get 2008. The actual problem here (and the reason why EdmGen does not support generating/importing store functions) is that in the EF provider model there is no way to get the description of the results returned by a store function. To make up for this the designer uses the DDEX provider which is able to return the description of the first result set (now, you also know why the EF Designer does not support stored procedures returning multiple resultsets even though it is supported by the runtime) returned by a store function. Since DDEX is basically a VS thing I don't think you will be able to import store functions from command line using out-of-the-box tooling.

Updating database for desktop application (patching)

I wonder what you are using for updating a client database when your program is patched?
Let's take a look at this scenario:
You have a desktop application (.net, entity framework) which is using sql server compact database.
You release a new version of your application which is using extended database.
The user downloads a patch with modified files
How do you update the database?
I wonder how you are doing this process. I have some conception but I think more experienced people can give me better and tried solutions or advice.
You need a migration framework.
There are existing OSS libraries like FluentMigrator
project page
wiki
long "Getting started" blogpost
Entity Framework Code First will also get its own migration framework, but it's still in beta:
Code First Migrations: Beta 1 Released
Code First Migrations: Beta 1 ‘No-Magic’ Walkthrough
Code First Migrations: Beta 1 ‘With-Magic’ Walkthrough (Automatic Migrations)
You need to provide explicitly or hidden in your code DB upgrade mechanism, and - thus implement something like DB versioning chain
There are a couple of aspects to it.
First is versioning. You need some way of tying teh version of teeh db to the version of the program, could be something as simple as table with a version number in it. You need to check it on executing the application as well.
One fun scenario is you 'update' application and db successfully, and then for some operational reason the customer restores a previous version of the db, or if you are on a frequent patch cycle, do you have to do each patch in order or can thay catch up. Do you want to deal with application only or database only upgrades differently?
There's no one right way for this, you have to look at what sort of changes you make, and what level of complexity you are prepared to maintain in order to cope with everything that could go wrong.
A couple a of things worth looking at.
Two databases, one for static 'read-only' data, and one for more dynamic stuff. Upgrading the static data, can then simply be a restore from a resource within the upgrade package.
The other is how much can you do with meta-data, stored in db tables. For instance a version based xsd to describe your objects instead of a concrete class. That's goes in your read only db, now you've updated code and application with a restore and possibly some transforms.
Lots of ways to go, just remember
'users' will always find some way of making you look like an eejit, by doing something you never thought they would.
The more complex you make the system, the more chance of the above.
And last but not least, don't take short cuts on data version conversions, if you lose data integrity, everything else you do will be wasted.

EF Code First - SqlServerCE Trigger

i use the entity framework code first for my application and i need a trigger.
My Application should support different database engines like
Sql Server
SqlServerCE
SqlExpress
Trigger, Stored procs are not supported in SqlServerCE, what would you do to get this
functionality?
I could do something after "SaveChanges" or something, what is a good way ?
Yes you can do something inside SaveChanges (by overriding) or after SaveChanges and call SaveChanges again to persist new data but it is not exactly the same as trigger. Simply if your requirement is to use trigger for some functionality SqlServerCE is not a choice for you. If you rewrite the trigger logic to your application you should have two versions anyway - one for big SQL using triggers and one for SQL CE not using triggers.
Code first, although it allows you to send in some raw queries and hence perform your own native database/server manipulations, basically is designed only for building a model and querying upon that model.
Now as for your question: You can directly build 'stored procedure alternatives' by adding methods to your DbContext (or extension methods for seperation of concerns).
Triggers are a little more complex. You can override the SaveChanges method in which you can basically track each change made either before it got persisted back to the database- or after.
Both problems however can also be solved by introducing a repository. See: http://huyrua.wordpress.com/2011/04/13/entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1 This allows you to launch a script (trigger) when adding, updating or removing a certain entity

Categories

Resources