ADO.NET Best Practices for Connection and DataAdaptor Object Scope - follow-up - ado.net

I had the exact same question that was asked by Mark Lansdown some time ago. Mark's question
The answers in that thread were somewhat helpful but left me still extremely puzzled; particularly as it relates to the recommended practice of employing "using" blocks.
The first answer seemed to indicate that the Connection object and the DataAdapter object should be created within using blocks...
DataTable dt = new DataTable();
using (OleDbConnection conn = new OleDbConnection("my_connection_string"))
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn))
{
adapter.Fill(dt);
}
Thus, the DataTable object is retained but both the DataAdapter and Connection object go out of scope the instant the table is filled.
Yet a follow-on answer indicated that the DataAdapter Object should be retained. That makes perfect sense to me as it does appear to me that the DataAdapter was designed with handling multiple commands in mind.
So this leaves me with multiple questions:
BTW, I am using vb.net with SQL Server
Question 1) In order to retain the DataAdapter object doesn't that mean I cannot create it with a using block?
Question 2) In order to create an instance of a DataAdapter don't I need an instance of a Connection object which would make it impractical to create the Connection object with a using block?
How would I implement the using blocks in code like this?
Private Class frmMain
Dim adapter as SqlDataAdapter
Dim conn as SqlConnection
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
conn = new SqlConnection("My_Connection_String")
adapter = new SqlDataAdapter("Select * from Employees", conn)
adapter.fill(MyDataSet, MyTableName)
End Sub
Private Sub SaveButtton_Click(sender as Object, e As EventArgs) Handles SaveButton.Click
adapter.Update(MyTableName)
End Sub
End Class
I have seen a bunch of sample code for all this on msdn and every sample code I saw incorporated using blocks but always created a table via code and performed updates via code all inside the using blocks which seems to me like it could never work in the real world.
Thanks for any advice.

a follow-on answer indicated that the DataAdapter Object should be retained...
Question 1) In order to retain the DataAdapter object doesn't that mean I cannot create it with a using block?
No. The response is flawed. Remember, DataAdpater was in .Net 1.0. At this time there was no good way to dispose your objects, so you did the best you could. Using blocks and good IDisposable support were added for .Net 2.0, and this caused a change in direction for how things should be done. Yes, a DataAdapter can have different kinds of queries, and has the ability to support longer lifetimes if that's really want you want, but it's rarely a good choice anymore to use it that way.
If you really want, you can still create another DataAdapter later on if you need it for the different type of query, or you can use ExecuteNonQuery() for things like DELETE, INSERT, and UPDATE. But if you want the framework to do more of that kind of work for you, you should really go for a full ORM. If you want to write your own SELECT statements in code, you're usually better off also writing your own INSERT, UPDATE, and DELETE (etc) statements by hand, as well (and be sure to use parameterized queries!).
Question 2) In order to create an instance of a DataAdapter don't I need an instance of a Connection object which would make it impractical to create the Connection object with a using block?
How would I implement the using blocks in code like this?
Don't write code like that. Rather than repeat myself I'll link to a previous answer explaining why:
https://softwareengineering.stackexchange.com/questions/142065/creating-database-connections-do-it-once-or-for-each-query/398790#398790
But the short version is an ADO.Net connection object is a thin wrapper around much "heavier" and more expensive items in a connection pool. When you try to re-use a connection throughout a class or application, you gain efficiency in the relatively cheap wrapper at the expense of the much larger real underlying connections. You really are much better off creating a new connection each time. Only the connection string should be preserved for re-use.
every sample code I saw incorporated using blocks but always created a table via code and performed updates via code all inside the using blocks which seems to me like it could never work in the real world.
I assure you, it works very well. Again, if you don't like it, maybe you're looking for a full ORM like EntityFramework.

Related

Intercepting databases accesses with EF Core

I'm looking for a way to intercept database queries as a means of getting some more in-depth performance stats. I'm after number of queries, query duration, the result data (for an idea of data magnitude) and ideally some access to any LINQ expression.
I can fall back on extending a base context class, creating another method to get DbSet, returning a wrapper there, but 1) that seems hackier than it ought to be, 2) any code there won't be able to distinguish getting cached results vs actual database accesses..
I've looked through the code and feel like wrapping ExecutionStrategyFactory or Database is the way to go - and while I can create an extension method on RelationalDbContextOptionsBuilder for the former, or /replace/ services, I can't see a way of wrapping either, such that the underlying provider's implementation is still used.
(See also: https://github.com/aspnet/EntityFramework/issues/6967)
Is there a decent place to hook into this?
For the ref of anyone else:
Ok, the trick is:
Replace the IRelationalConnection that EF Core's DI system uses via ReplaceService<IRelationalConnection, MyRc>(). Our new MyRc will wrap the existing connection to add hooks
In our MyRc, have a constructor param of IDatabaseProviderServices. The EF DI system will populate it. Cast that to IRelationalDatabaseProviderServices and then grab the RelationalConnection property from that
Wrap all methods, but have public DbConnection DbConnection { get; } return an instance of a DbConnection-wrapping class
In that wrapping class, have CreateDbCommand() return an instance of a DbCommand-wrapping class
In that wrapping class, have ExecuteDbDataReader() return an instance of a DbDataReader-wrapping class
Then, in the DbCommand and DbDataReader wrappers, we can see what commands and parameters are being sent to the database, and the results coming back.
This only works with relational models.

Is it a bad practice to open a new context or send one as a parameter into sub-methods?

A colleague asked for my opinion regarding the following setup. It's based on a declaration of a context in a method and then providing it into the called submethods. Schematically, it looks like so.
public void SuperMethod()
{
using(Context context = new Context())
{
...
SetMethod(context, ...);
...
GetMethodDuo(context, ...);
...
}
}
public void SetMethod(Context context, ...) { ... }
public Some GetMethod(Context context, ...) { ... }
I advised him against it, motivating my answer by the idea of opening/closing access to the database as near the actual operations as possible. But now that I think about it, I'm uncertain if that was the best advice in any circumstances.
Question 1: Was the suggestion of mine correct in a general case or should I consider altering it?
I also noticed that the super-method calling the sub-methods used the context itself. My suggestion was to move the part that talked to the database in a new sub-method, hence freeing the super-method from any references to the context. I felt that it made sense to make the super-method a controller, while performing all the database related operations in the workers.
Question 2: Does it make sense to have a controlling method that calls a (possibly large) number of sub-methods carrying the actual work?
Please note that both questions are related to the usage of the context while working with Entity Framework and not a general class structure.
IMO, the context should be opened and disposed with every unit of work (so for example, within a simple function) - which doesn't mean you shouldn't pass your context to underlying functions. This can be exactly what you want, especially considering connection pooling and context entry lifetime.
This has a few pretty simple reasons:
It's pretty cheap to open a new context, it will take almost no time relatively to the main performance issues in EF like materializing values (DataSet to object and vice versa) and creating the queries - and those two have to be done with an already open context as well.
One main reason against opening and disposing a context every time is the opening/disposing of connections (some DBMS, I know particularly of SQL CE, have incredible problems with the creation of connections to certain databases - and EF will create a new connection based on the provided connection string whenever it needs one). However, you can easily surpass this, by keeping a connection open (or letting it timeout isn't too bad most of the time either) and pass it to your context upon creating, using the DbContext(Connection, bool) overload with ContextOwnsConnection=false.
When you keep the context open over the whole lifetime, you can't possibly know which objects are already in the change tracker, materialized or there in another form, and which aren't. For me, this was a problem when rewriting the BL of my project. I tried to modify an object, which I added earlier. It was in the context (unchanged) but not in the change tracker, I couldn't set its state, because it wasn't in the change tracker. And I couldn't attach it again, because it was already in the context. This kind of behavior will be pretty hard to control.
Another form of this is as follows. Whenever a new object enters the context, EF will try to set the navigation properties of these regarding the other objects in the context. This is called relationship fixup and is one of the main reasons Include() is working so well. This means that most of the time, you'll have a huge object tree in your context. Then, upon adding/deleting it (or whatever else operation) EF will try to carry out this to the whole tree (well... sometimes ;) ), which can cause a lot of trouble, especially when trying to add a new entry with FK to already existing items.
A database context is, like already mentioned, basically an object tree, which can be, depending on its lifetime, gigantic. And here, EF has to do a few things, like... Checking if an item is already there, because of obvious reasons... In best case complexity O(n*log(n)+m), where m is the number of object types and n the number of objects of this type in the context. ...Checking if an object has been modified since retrieval - well, you can imagine, since EF has to do this for every single object in every single call, this can slow things down pretty far.
A bit corresponding to the last issue. What do you really want, when calling SaveChanges()? Most likely, you want to be able to tell: "ok, these are the actions I did, so EF should now issue these and these calls to the db", right? Well... But, since EF has been tracking the entities, and maybe you modified some values, or another thread did something there and there... How can you be sure, these are the only things SaveChanges() will do? How can you be sure that over the whole lifetime of the context, there's nothing fishy in your database then (which will cancel the transaction, which can be pretty big)?
But yeah, of course, there are a few issues, where you need to keep the context open (well, you don't need to - you could just pass it). For me, this was mostly in a few cases where FK correction was hard to maintain (but still within one function, while sometimes within one function I just had to dispose and re-create the context for the sake of simplicity) and whenever you call sub-functions from multiple places in your code - I had the issue that I had a context open within a calling function, which called another function, which still needed the context. Usually, that's not a problem but my connection handling is kind of... advanced. That led to performance loss, I dealt with this by passing the already open context through an optional additional context parameter to the sub-function - just like what you already mentioned, however it shouldn't really be necessary.
For additional reference, here are some links that might be helpful in this regard. One's straight from MSDN and the other from a blog.
As #DevilSuichiro mentioned the DbContext is meant as a Unit of Work container. By default DbContext stores all loaded objects in the memory and track their changes. When the SaveChanges method is called all changes are sent to a DB in the single transaction.
So if your SuperMethod handles some kind of a logical unit of work (e.g. a HTTP request in a web application) I would instantiate the context only once and pass it as a parameter to submethods.
Regarding your second question - if you instantiate the context only once, it's IMO better to have more methods that are simple, easier to maintain and have meaningful names. If you want to create a new instance of the context in every submethod, it depends on what "possibly large" number means :-)

Correct way to persist and existing JPA entity in database

In one application I am working on, I found that the JPA objects that are modified are not previouly loaded, I mean;
Instead of doing like this:
getEntityManager().find(Enterprise.class, idEnterprise);
//Some modifying operations
They do like this(and works!):
Enterprise obj = new Enterprise (IdEnterprise);
//Some modifying operations
getEntityManager().persist(obj);
This last solution doesnt load from database the object and it modifies the object correctly.
How is this possible?
Is a good practice? At least you avoid the query that loads from database, right?
Thanks
It depends. If you are writing code from a controller class (or any application code) you shouldn't be worried about jpa stuff, so the second approach is bad and redundant.
If, instead, you are working in infrastructure code, maybe you can manually persist you entities to enable some performance optimization or simply because you want the data to persist even if the transaction fails.
I strongly suspect the second bit of code is someone creating an entity from scratch, but mixing application, domain and infrastructure code in the same method: an extremely evil practice. (Very evil, darth father evil, never do that)

What is the correct way to manage dependency injection for Entity Framework ObjectContext in ASP.NET MVC controllers?

In my MVC controllers, I'm using an IoC container (Ninject), but am not sure how to best use when it comes to the Entity Framework ObjectContext.
Currently, I'm doing something like:
using(var context = new MyObjectContext())
{
var stuff = m_repository.GetStuff(context);
}
This is the best way to manage from the point of view of keeping the database connection open for the shortest time possible.
If I were to create the ObjectContext via Ninject on a per request basis, this obviously keeps the database connection open for too long.
Also the above code would become...
var stuff = m_repository.GetStuff(m_myObjectContext);
(And when would I dispose of the context...?)
Should I be creating a factory for the ObjectContext and pass that in via DI? This would loosen the coupling, but does this really help with testability if there is no easy means of maintaining an interface for the ObjectContext (that I know of)?.
Is there a better way? Thanks
This is the best way to manage from the point of view of keeping the
database connection open for the shortest time possible.
If I were to create the ObjectContext via Ninject on a per request
basis, this obviously keeps the database connection open for too long.
Entity Framework will close the connection directly after the execution of each query (except when supplying an open connection from the outside), so your argument for doing things like this does not hold.
In the past I used to have by business logic (my command handlers to be precise) have control over the context (create, commit, and dispose it), but the downside is that you need to pass on this context to all other methods and all dependencies. When the application logic gets more complex, this results in less readable, less maintainable code.
For that reason I moved to a model where the unit of work (your MyObjectContext) is created, committed, and disposed outside the control of the business logic. This allows you to inject the unit of work into all dependencies and reuse the same unit of work for all objects. Downside is that this makes your DI configuration a bit harder. Some things your need to make sure of:
The unit of work must be created as per web request or within a certain scope.
The unit of work must be disposed at the end of the request or scope (although it is probably not a problem when the DbContext is not disposed, since the underlighing connection is closed and DbContext does not implemente a finalizer).
You need to explicitly commit the unit of work, but you can't do this at the end of the web request, since at that point you have no idea whether it is safe to commit (since you don't want to commit when your business logic threw an exception, but at the end of the request there is no way to correctly detect if this actually happened).
One tip I can give you is to model the business logic in the system around command handlers, since this allows you do define a single decorator that handles the transactional behavior (committing the unit of work and perhaps even running everything in a database transaction) at a single point. This decorator can be wrapped around each handler in the system.
I must admit that I have no idea how to register generic types and generic decorators with Ninject, but you'll probably get an answer quickly when asking here at Stackoverflow.

Enlist Entity Framework into a SQLTransaction?

We have a lot of legacy code that uses our own data object. We are slowly trying to introduce EF. We need the ability to enlist EF into a transaction we already started using System.Data.SqlClient.SQLTransaction. EF of course uses System.Transaction.Transaction. Is this possible?
To make things more clear. We have code all over the place that does the following:
public sub DeleteEntity()
Dim InTransaction = ado.InTransaction
if not InTransaction then ado.BeginTran
...
<--want to use EF Here
...
if not InTransaction then ado.CommitTran
end sub
The DeleteEntity routine is not simple. It has a lot of logic. I want to use EF for just want thing in the middle of the code so i need to enlist it in the active transaction. I can't just use transaction scope because of how it is designed. DeleteEntity is called in lots of places and i don't want to visit every place that calls the routine. It more has to deal with System.Transaction.Transaction and SqlTransaction then it does EF itself.
Update: I tried:
context.connection.EnlistTransaction(Transaction.Current)
That doesn't work.
I may be wrong but have you considered using ObjectQuery instead of using to Linq to Entities for the Delete operation. Here is what I found on MSDN here
Promotion of a transaction to a DTC may occur when a connection is
closed and reopened within a single transaction. Because the Entity
Framework opens and closes the connection automatically, you should
consider manually opening and closing the connection to avoid
transaction promotion. For more information, see How to: Manually Open
the Connection from the Object Context.