How does Entity Framework convert an EntityTransaction into a provider specific transaction? - entity-framework

I've got an Entity Framework 4 data mode. I'm loading data into a database using stored procedures since EF is so slow. We use the entity model to call the stored procedures. Everything has to be in one transaction.
In order to speed up the process, I need to perform some bulk copy operations. I'm using SQL Anywhere and their ADO.NET provider software for this.
When I call context.Connection.BeginTransactin(), I get an EntityTransaction back. Actually, my variable is a DbTransaction, which is the base class for all transactions. But the actual object returned is an EntityTransaction.
I can't cast an EntityTransaction into the provider specific transaction class (SAConnection in this case). If I do, I get a cast exception. Yet, somehow, when the entity context calls the stored procedures, it's enlisting the provider specific command objects it creates into the transaction represented by that EntityTransaction object.
How does the provider do this? Is it a mechanism I can use to get a provider-specific transaction object for my bulk copy operations?
Tony

I have taken a look at the EntityTransaction class and in fact an internal property called StoreTransaction exists. If found some source-code in this SO discussion: This SqlTransaction has completed; it is no longer usable. Entity Framework Code First which might help you out.
Keep in mind, that this won't work in partial trust environments, which do not allow you to access members using reflection.

Related

How to properly use EFCore with SignalR Core (avoid caching entities)

I just found some really strange behaviour which turns out it is not so strange at all.
My select statement (query from database) worked only the first time. The second time, query from database was cached.
Inside Hub method I read something from database every 10 seconds and return result to all connected clients. But if some API change this data, Hub context does not read actual data.
In this thread I found this:
When you use EF it by default loads each entity only once per context. The first query creates entity instance and stores it internally. Any subsequent query which requires entity with the same key returns this stored instance. If values in the data store changed you still receive the entity with values from the initial query. This is called Identity map pattern. You can force the object context to reload the entity but it will reload a single shared instance.
So my question is how to properly use EFCore inside SignalR Core hub method?
I could use AsNoTracking, but I would like to use some global setting. Developer can easily forget to add AsNoTracking and this could mean serving outdated data to user.
I would like to write some code in my BaseHub class which will tell context do not track data. If I change entity properties, SaveChanges should update data. Can this be achieved? It is hard to think all the time to add AsNoTracking when querying from hub method.
I would like to write some code in my BaseHub class which will tell context do not track data.
The default query tracking behavior is controlled by the ChangeTracker.QueryTrackingBehavior property with default value of TrackAll (i.e. tracking).
You can change it to NoTracking and then use AsTracking() for queries that need tracking. It's a matter of which are more commonly needed.
If I change entity properties, SaveChanges should update data.
This is not possible if the entity is not tracked.
If you actually want tracking queries with "database wins" strategy, I'm afraid it's not possible currently in EF Core. I think EF6 object context services had an option for specifying the "client wins" vs "database wins" strategy, but EF Core currently does not provide such control and always implements "client wins" strategy.

How to ExecuteSqlCommand in Entity Framework without it being contained in a transaction

I need to execute a stored procedure with Entity Framework.
Normally I call it like this:
this.Context.Database.ExecuteSqlCommand("EXEC edi_UploadTransmission");
However, this particular stored procedure includes accessing a linked server.
Since EF wraps ExecuteSqlCommand in a transaction, it is failing, as a linked server is not supported in a transaction (as far as I can tell).
Is there a way to execute this stored procedure with Entity Framework without it being in a transaction?
Pass TransactionalBehavior.DoNotEnsureTransaction as the first parameter to the ExecuteSqlCommand method.
For example,
this.Context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "EXEC edi_UploadTransmission");
My recommendation would be to simply not use EF for this part of your code. You can freely combine EF with straight ADO.NET code or with other ORMs such as Dapper or Chain.
https://github.com/docevaad/Chain/wiki/A-Chain-comparison-to-Dapper

Entity Framework - Share Transactions across Bounded Contexts

I am working on a very large application with over 100 modules, and almost 500 tables in the database. We are converting this application to WPF/WCF using Entity Framework 4.2 Code First. Our database is SQL Anywhere 11. Because of the size of the database, we are using an approach similar to Bounded DbContexts, as described here http://msdn.microsoft.com/en-us/magazine/jj883952.aspx by Julie Lerman.
Each of our modules creates its own DbContext, modeling only the subset of the database that it needs.
However, we have run into a serious problem with the way DbContexts are created. Our modules are not neatly self-contained, nor can they be. Some contain operations that are called from several other modules. And when they are, they need to participate in transactions started by the calling modules. (And for architectural reasons, DTC is not an option for us.) In our old ADO architecture, there was no problem passing an open connection from module to module in order to support transactions.
I've looked at various DbContext constructor overloads, and tried managing the transaction from EntityConnection vs. the StoreConnection, and as far as I can tell, there is no combination that allows ModuleA to begin a transaction, call a function in ModuleB, and have ModuleB's DbContext participate in the transaction.
It comes down to two simple things:
Case 1. If I construct DbContextB with DbContextA's EntityConnection, DbContextB is not built with its own model metadata; it reuses DbContextA's metadata. Since the Contexts have different collections of DbSets, all ModuleB's queries fail. (The entity type is not a part of the current context.)
Case 2. If I construct DbContextB with ModuleA's StoreConnection, DbContextB does not recognize the StoreConnection's open transaction at the EntityConnection level, so EF tries to start a new transaction when ModuleB calls SaveChanges(). Since the database connection in fact has an open transaction, this generates a database exception. (Connection does not support parallel transactions.)
Is there any way to 1) force DbContextB to build its own model in Case 1, or 2) get DbContextB's ObjectContext to respect its StoreConnection's transaction state in Case 2?
(By the way, I saw some encouraging things in the EF6 alpha, but after testing it out, found the only difference was that I could create DbContextB on an open connection. But even then, the above 2 problems still exist.)
I suggest you try use the TransactionScope object to manage this task for you. As long as all of your DbContexts use the same connection string (not connection object) the transaction should not try to enlist MS-DTC.

How to get a detached object from JPA

In my application I need most objects fetched in detached mode (fetched with the find API).
I'm wondering if there is a way to ask a detached object from the JPA provider and save the extra call to detach() API.
In additional I would expect the object created in such mode to be less expensive since the JPA provider doesn't need to add it to the entity manager context.
Is there a way to achieve this with JPA APIs?
Is there a way to achieve such functionality with query results?
Specifically I'm using Eclipse Link so if there is a specific way to do it with this implementation it will be helpful as well.
You can fetch a detached entity without an extra call to detach() if you fetch it outside a transaction. If you are not using container-managed transactions, it's trivial, simply do not start a transaction.
If you are using CMT, you have to make sure the requesting object is not a transaction-enabled EJB:
if in an EJB, suspend the transaction by annotating the appropriate method with:#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED),
or
call the EntityManager from a POJO. You dont have to call it directly, it only impotrant that the query result will end in a non-EJB object.
AFAIK, there is no performance gain to be expected, since the query result will always be put in the current persistence context, however shortlived it may be.
EDIT: There is another possibility to get detached objects which does not depend on transaction demarcations: JPA constructor expressions:
List<DTO> dtos = em.createQuery("SELECT NEW com.example.DTO( o.title, o.version) FROM Entity o").getResultList();
The constructed type must have a constructor with all the relevant attributes. The objects in the list, entities or not, will always be created detached. However there is a small overhead of instantiating a new object.

Does Entity Framework store it's DbContext along with cached query plans?

In my web application, we are using a per request DbContext. We create the DbContext in Application_BeginRequest(), store it in HttpContext.Items, and then call Dispose on it in Application_EndRequest().
We make the current context available through a wrapper class DatabaseContext.Current property.
Sporadically, when executing a query against this database context, we get the following exception:
"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection".
I've searched our code for any possibility that we are calling Dispose on the context elsewhere....we aren't.
A query that commonly fails is this one:
var user = (from u in DatabaseContext.Current.Users
where u.UserName == username
select u).FirstOrDefault();
return user != null;
All I can think of is that deep in the bowels of the EF it is keeping a reference to the DbContext in a cached query plan and then attempting to reuse that context when the query is executed. I've looked at it through reflector and it does seem that some of the internals keep a reference to the ObjectContext.
Is there a way to disable linq query caching? Anyone have any clues?
The other possibility is that a query from a previous call on the Context is leaving the Context in bad state. However, there are no indications of failures that would indicate this.
This is Entity Framework 4.1 using Sql CE (for now, we are soon migrating to a production SQL Server Instance).
Neither of your scenarios should happened. There is no caching you mentioned. There are some possibilities you should check instead:
You are using context after EndRequest or outside of current HttpRequest scope
You are storing entity retrieved from context somewhere in cache or session and using it in other request processing - this can be an issue because entity can keep reference to disposed context and use it for some operations.
There is no automatic LINQ query caching - it is feature planned for upcoming EF release but that feature caches DbCommand instances independent on the context.
You get this exception "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection" - because there is a failed transaction, after that trying to access a data query. Put a try catch and observe the exception. precisely, there is an exception, which is not handled properly.