EF usage from thread spawned from Role.OnStart() - entity-framework

I'm using EF code-first to manage my DB connection, with an explicit connection string declared in web.config. I would like to schedule some DB cleaning process (like deleting test transactions every day), so I'm spawning a thread from Role.OnStart() with proper concurrency management among the instances.
But I'm getting DB database exceptions, like the DB not matching my model, whereas I'm sure it does (the same code used from "inside" the app works well). So my guess is that web.config is not used from the thread, so EF probably uses the default connection string.
What would be the best way to use my connection string from there ?
Thanks

The OnStart method doesn't run in the same process as your web application meaning it doesn't make use of the web.config. I suggest you store the connection string in the service configuration and read it from here when initializing your context.
An other advantage is that you change the setting without re-deploying the application.

Related

.NETCore PostgreSQL "A command is already in progress"

I am developing a WebAPI on .NETCore accessing data to a POSTGRESQL DB.
I have troubles with the non-MARS support of PostgreSQL. NPGSQL is unable to support multiple connections from the same instance (as described in EntityFramework DbContext lifecycle + Postgres: "An operation is already in progress."). For Asynchronous management, this is blocking.
Unfortunately, I cannot find any solution to this.
At the moment, I inject my DB context with:
services.AddEntityFrameworkNpgsql().AddDbContextPool<DBApiContext>(opt => opt.UseNpgsql('connectionString');
I use EntityFramework.
Just for people who got stuck in this - In my case, it was a simple code change in the end of the method to fix this:
reader.close();
reader is an object of NpgsqlDataReader.
For who may be interested in: my problem was all about service scope and dependency injection.
The requestor was not a transient service, so that for every requests, even parallel, it was trying to access the DB.
Postgresql doesn't support MARS, then the second requests were rejected.
You need to have transient service requesting the access, for every invokation to use a different DB handler.

How do I tell EntityFramework Migrations to use the connection used by the current context?

When I create my context using a connection string name, that connection is used as expected, but not by the code running Migrations!
That code creates a new context with the parameter-less constructor which then obviously uses its default connection resolving mechanism and thus connects to a different database!!
This seems very undesirable default behavior to me. Why does Migrations not use the current context, or at least the same connection string as the current context?
Am I missing something or is this a flaw in Code First Migrations? And what is the best way to work around this? Implementing IDbContextFactory? Or do somting with Database.SetInitializer in the context constructor?
I actually ended up querying my database without any exceptions occurring (since I did not run any code relying on the migration), and at the same time secretively creating a completely new database in SQLEXPRESS.
Version used is Entity Framework 6 with .NET 4
To prove my findings I added some screenprints from the debugger. The first one shows that the connection taken from connection-string SiteSqlServer is actually used. The second one shows that the connection used in the database initialization code is different.
The third shows the stacktrace at the time of the screenprints.
(Hopfully the prints are readable, zooming in helps)

lifetime of Entitymanager instance

I have a requirement in which we create a single Statelebean which creates a Container Managed EntityManager instance(using #PersistenceContext) in EJB3 environment.
In this single Stateless bean created, we create threads which are executed in specific time intervals. This thread would be running for months.
I have a doubt as to whether the single EntityManager instance obtained from the container (using CMP) can be used for the entire lifetime(> 1yrs).
To the lifetime of EntityManager: I think it is more a question of the DB connection lifetime. In this case, when the JPA provider detects a connection time-out, if you configured your JDBC connection string wth autoReconnect=true you would expect that another connection is built. Also you should search for possibilities of setting a big timeout.
On the other side, you probably ignore that in EJB you are not allowed to open new Threads. In your case, you would have some problems when it comes to managed entities (that are changed in different threads) and to transaction problems. Instead I would use the Timer Service.
An EntityManager seems meant to represent a transactional space. To me, it doesn't make sense to use a single transactional space for the entire life of a thread that will be long lived but it depends on your design and provider implementation how feasible this is. If you are going to use a single EM, make sure it is not shared between threads, and monitor its resource usage, as they are required by JPA to cache every entity read through them as managed instances; you might want to occasionally call em.clear() to detach managed instances so they can be garbage collected at logical points.
I don't think injection will work, as the container should tie the EntityManager to the life of the bean it is injected into, not the life of your thread. You will want to obtain the EntityManagerFactory and obtain/manage your own EntityManager lifecycles for your threads.

Reworking EF nested connections to avoid MSDTC on Azure

I've deployed to Azure and Azure SQL, which doesn't support MSDTC and I'm having trouble understanding how to rework my code to prevent what I assume is nested connections. I'm fairly new to EF and my knowledge of TransactionScope is not wonderful, so I'm not sure that I have the right pattern.
I am trying to use repos, which call on a shared instance of the ObjectContext (I tried to dispose on EndRequest but had issues, so this is another problem for me).
I have a transaction which calls SaveChanges on the ObjectContext instance several times, but at some point it becomes disposed. What is governing this and can you recommend what I can do to get it working correctly?
If you want to avoid issues with distributed transaction you must handle connection manually because you need only one opened connection per TransactionScope = one context instance with one connection used for all queries and database updates. The code should look like:
using (var context = new YourObjectContext()) {
context.Connection.Open();
...
}
I am trying to use repos, which call on a shared instance of the
ObjectContext (I tried to dispose on EndRequest but had issues, so
this is another problem for me).
If you share your context instance among multiple request or even worse if you use just single context instance to handle all your requests you should stop now and completely redesign your application. Otherwise it will not work correctly.

WF4 TransactionScope containing several custom activities with EF4 database updates

I have created several custom activities that update tables in my DB (in this case SQL Server Compact), using Entity Framework 4 with POCOs.
If I put more than one of these inside a WF4 TransactionScope activity, I'm running into problems: EF disposes the DB connection after the first activity has finished, and when the next DB activity tries to do a DB update a new connection is built up. At this moment an exception is thrown.
System.Activities.WorkflowApplicationAbortedException : The workflow has been aborted.
----> System.Data.EntityException : The underlying provider failed on Open.
----> System.InvalidOperationException : The connection object can not be enlisted in transaction scope.
Do I have to keep the EF connection open during the whole transaction scope? How can I do that? Create an explicit custom activity for that, or is there a standard way?
My current workaround goes like this: I created a new code activity that creates our ObjectContext and explicitely calls dbContext.Connection.Open(). It returns the ObjectContext, which is then saved in a workflow variable. That one is passed to all the DB related activities as an InArgument<>. Inside my DB activities, I use this ObjectContext if it is passed in, otherwise I create a new one.
This does work, but I'm not satisfied with this solution: It needs the new InArgument for every DB related activity. In the workflow designer, I have to insert that special OpenDatabaseConnection activity inside the transaction scope, and then make sure that the correct variable is passed into all DB activities. This seems to be very inelegant and error prone, especially if other team members have to use these DB activities.
What would be a better way to handle this?
The problem is that when you open a second connection in the same transaction scope, an attempt is made to promote the transaction to a distributed transaction (even though there's nothing distributed about it since you connect to the same database). SQL Server CE doesn't support this scenario.
What I would do is create a custom 'container' activity that opens (and closes) the connection and makes it available to child activities. This is still not optimal but at least you no longer need to pass InArgument's around. You get the following activity tree:
TransactionScope
InitializeConnection
Sequence
CustomDataActivity1
CustomDataActivity2
CustomDataActivity3
InitializeConnection is a NativeActivity that uses NativeActivityContext.Properties to expose the connection (or the ObjectContext) to child activities.
Make sure you implement proper error handling to ensure you close the connection at all times.
NOTE: Distributed transactions are supported by the full SQL Server only through a Windows service called MSDTC (Microsoft Distributed Transaction Coordinator). You can find this one in your 'Local Services'. Since SQL Server CE is a database that should be able to operate completely standalone, it makes sense that it has no dependency on MSDTC. Therefore it has no support for distributed transactions.