Has anyone been able to create temporary tables or triggers using Microsoft's Entity Framework and SQLite? I have a working application that can create permanent tables and triggers, but not temporary ones. Listing sqlite_temp_master turns up no entries, and any attempts to interact with the temporary tables fail with "no table" errors. These interactions are taking place through a single SQLiteConnection though there is at least one other connection active in the application at the time.
I am using Database.ExecuteSqlCommand() to create the tables and triggers. If the TEMPORARY keyword is supplied, there are no errors and no tables/triggers. If the TEMPORARY keyword is not supplied, there are no errors, and permanent tables/triggers are created.
Any help would be appreciated.
The System.Data.Entity.Database object opens and closes the connection as it deems appropriate. In the way I was using ExecuteSqlCommand, it will open and close the connection for each command. So temporary tables will be discarded as soon as they are created.
Manually opening and closing Database.Connection won't work because of an apparent problem in the DbContext class. However, the internal ObjectContext object can do the job.
Here's the best summary that I've found for the solution (many thanks to Brent McKendrick)
(dbContext as IObjectContextAdapter).ObjectContext.Connection.Open();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// perform a list of queries
// The connection will not close!
scope.Complete();
(dbContext as IObjectContextAdapter).ObjectContext.Connection.Close();
}
I used that technique in conjunction with SQLiteCommand to create a set of temporary tables and triggers, perform my operations, use LINQ to get the results, then end the transaction, and close the connection. The temporary objects were dropped only at the end, as expected.
I did not check to see if Database.ExecuteSqlCommand can be used in place of SQLiteCommand when using this technique.
Edit: The TransactionScope is not necessary, and certainly adds to the overhead of any operation. The critical part is the opening and closing of the connection through the dbContext's ObjectContext.
Related
I am writing unit test cases for testing a framework. The unit test adds and modifies the data in an existing database. I need to rollback all the changes done to database after a test finishes, i.e. delete the rows added and revert the rows modified.
I am using Entity Framework 6 for accessing the database. The underlying database is SQL Server. Is there any support provided by EF6 to achieve this?
Presently I am storing the changes in a list and I refer the this list for cleaning up the database. But using this approach leaves some residue randomly. I am not sure of the reason though, maybe some race condition or something.
Looking for some minimal and smart alternative for it. Thanks in advance :)
you can wrap your test in a transaction and don't commit changes:
using (TransactionScope scope = new TransactionScope()) {
//do your stuff
}
But for unit testing propouses you can use Effort - Entity Framework Unit Testing Tool which provide in-memory database operations.
EDITED to reply last comments
You can use an overloaded TransactionScope contructor to control the IsolationLevel, so you can choose to read uncommited changes or not.
If your proxy isn't inside the Transaction, please, check that the connection string is the same, so ado.net can identify the connection and enlist the connection in the same transaction.
If the connection string is not the same, you probably will need to activate the Distributed Transaction Coordinator. Here you have an explanation how DTC scalation occurs: TransactionScope automatically escalating to MSDTC on some machines?
How can I tell an EF4 DbContext to clear its internal cache/state?
I have a database updater program which executes a large number of inserts on a variety of tables via EF4 within a transaction. I find the inserts to a common Permissions table get slower and slower as the update proceeds.
There are the following constraints at play:
1) Everything must occur within a single (giant) transaction.
2) Can't introduce dependency on MSDTC - so I can't have a cross-connection transaction.
3) Can't seem to open a new DbContext for a SqlConnection which is already open - encounters "EntityConnection can only be constructed with a closed DbConnection" error. (note that I am already sharing a SqlConnection between multiple DbContext's, but only opening the connection after they are all initialized)
Given these constraints, I can't create a new DbContext for each chunk of the work, as it breaks the transaction.
I've satisfied these functional constraints, but the performance is poor. I suspect the DbContext is struggling to handle the volume of data being inserted into the DbSet.
How can I tell the DbContext to reset its internal cache (eg. the rows I inserted recently and don't care about any more)?
IIRC, you get a decent speedup on insert if you:
myDbcontext.Configuration.AutoDetectChangesEnabled = false;
myDbcontext.Configuration.ValidateOnSaveEnabled = false;
Perhaps it might be better to take a read of this: http://patrickdesjardins.com/blog/entity-framework-4-3-with-poco-and-track-change
I'd probably abandon EF for a gigantic insert go with SqlBulkCopy. The relevant section is here: http://msdn.microsoft.com/en-us/library/tchktcdk.aspx#sectionSection2
In your application you can use a mix of Entity Framework for reading your data and doing small insert and updates and use ADO.NET DataAdapters for Bulk Inserts and Updates http://msdn.microsoft.com/en-us/library/aadf8fk2.aspx
Alternatively you could use the ExecuteSQLCommand of EF5 http://msdn.microsoft.com/en-us/library/gg679456(v=vs.103).aspx to do your inserts in combination with stored procedures and passing a Table parameter to pass the bulk data. In EF4 it's ExecuteStoreCommand http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.executestorecommand.aspx
I want to find a way to control EF's underlying db connection & transaction to make sure my application is using only one connection at a time during one transaction (I will need to support both Oracle and SQL Server).
I found this good article which comes with a lot of recommendations, but brings up (like all the other articles I have read) the TransactionScope. Well, I would like to stay away of TransactionScope, if possible...
Could I have a solution for this playing with only pure DbConnection & DbTransaction or this is simply impossible or wrong?
Even more, I found this article here, stating at section :
"Specifying Your Own Transaction"
Just as you can override the default behavior with connections, you
can also control transaction functionality. If you explicitly create
your own transaction, SaveChanges will not create a DbTransaction. You
won't create a System.Common.DbTransaction, though. Instead, when
creating your own transactions, you need to use a
System.Transaction.TransactionScope object.
But there is no explaination...
I am using Entity Framework 5.0. Could you please help me understand in order to choose correct for my application? It would be ideal to show me some good patterns of usage.
Thanks in advance!
Note: I am planning this because of the transactions escalating to DTC for Oracle Data Provider.
Entity Framework 6 has two features which may help with this:
Explicit Transaction Support
Ability to create a DbContext from a DbConnection.
If you did want to use EF5, you'd need to use a TransactionScope:
var context = new MyContext();
using (var transaction = new TransactionScope())
{
MyItem item = new MyItem();
context.Items.Add(item);
context.SaveChanges();
item.Name = "Edited name";
context.SaveChanges();
transaction.Complete();
}
As mentioned in the linked article, you will need to reference System.Transactions to get TransactionScope.
Entity Framework maintains its own transaction which is sufficient. However it gives you flexibility of committing or discarding the changes in transaction. If you do not call SaveChanges() method then it will discard the transaction. Also if you are using the same DbContext for many transactions, then it would be using same connection. If you use two or more DbContext at the same time, then it will use separate connections which is ideal situation. Here is a very important point I would like to make is that it would be a waste of Entity Framework technology to implement own transaction. If you want to do so, then I would suggest to use your own DB implementation in traditional way.
I am writing integration tests to verify the behaviour in my repositories. The problem I run into is that I want to start with a clean database for every test. I managed to do so by writing the SetUp as follows:
[SetUp]
public void SetUp()
{
_applicationContext = new TestApplicationContext();
_applicationContext.Database.Connection.Close();
_applicationContext.Database.Delete();
_applicationContext.Database.Create();
_tenantRepository = new TenantRepository(_applicationContext);
_userRepository = new UserRepository(_applicationContext);
}
The TestApplicationContext sets the database name to TestDatabase.
This works fine until I want to check the actual database for the result of my test. Then I make a connection from MSSQL server to the same database, which won't close until I either:
shut down MSSQL server
delete the database with the option "close all connections"
The only way I found is via SQL commands. Maybe it's because of my n00b knowledge regarding MSSQL, but I was kinda hoping for a "close connection" button / option.
How can I close the connection to the database from MSSQL server?
Or, is there a way I can do this programmatically from C#?
UPDATE:
Maybe I wasn't very clear. But the test SetUp fails after I opened MSSQL and viewed the contents of a table. This is because MSSQL also creates a connection to the TestDatabase, and my integration test is not able to close that connection. So I am looking for a solution that allows me to close the connection I created from MSSQL server.
You can work around the connection problem if instead of dropping and re-creating whole database you just drop and re-create selected (or all tables).
You could create little script that will do it for you in a way that you do not need to hard-code table names:
http://www.apexure.com/blog/2010/07/29/delete-all-tables-in-sql-server-database/
Alternatively, Julia Lerman in her book "Programming Entity Framework: Code First" mentiones this approach in more mature form, as incorporated as a custom database initializer:
As well as writing your own custom initializers, you can also find
initializers that other people have created. One example of this is
available in the EFCodeFirst.CreateTablesOnly NuGet package. This
initializer will allow you to drop and create the tables in an
existing database, rather than dropping and creating the actual
database itself. This is particularly useful if you are targeting a
hosted database where you don’t have permission to drop or create the
entire database.
You're releasing the connection back to the connection pool, not actually closing it. Instead of creating/deleting the database for each test, begin new transaction in setup and rollback in cleanup. This way no changes will be committed to your database and your test will always start from a clean state.
Also, because you are testing against live database, I wouldn't call your tests "unit" tests. Unit tests do not have any external dependencies.
The only way to reliably get an exclusive lock on a database is to use the SINGLE_USER WITH ROLLBACK IMMEDIATE technique. I recommend that you create a database snapshot with an empty state and restore to that snapshot each time. That will be much faster.
I'm creating and dropping databases on the fly for some integration tests. I'm doing all the database management at the ADO.NET level. For the tests I'm using Entity Framework because the entities is one part of what I am testing. The problem is that after I do this:
using (ProjectEntities db = new ProjectEntities(cs)) {
}
I cannot drop the database anymore. It says it is in use. How do I release it so it can be dropped?
I actually had the same problem at the ADO.NET level and what I did was:
new SqlCommand("USE [master]", DatabaseConnection).ExecuteNonQuery();
but I'm not sure how to perform something with the same effect for the Entity Framework connection. I've trying manually disposing the db object (although the using clause should guarantee that) and I've also tried manually closing the db.Connection. Neither helped. If I could run SQL directly no the Entity Framework connection, I believe I'll be able to do it. Or maybe there's another way?
You might need to explicitly close all connections, I believe that the connection are being pooled and it's one of the pooled connections that is still maintaining an active connection to the DB. Try using SqlConnection.ClearAllPools
I blogged about a similar issue in Entity Framework Object Context - AWAITING COMMAND.