-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Correct IDbDataAdapter type from ISession.Connection...
PostPosted: Wed Feb 15, 2006 9:40 pm 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
NHibernate is my first experience with creating ADO.net provider independent applications. Unfortunately the reporting tool that I'm using (ActiveReports) doesn't support binding to object collections and so I must use one of those nasty DataSets.

My problem is that ISession.Connection returns an IDbConnection, but I have no way of getting an appropriate IDbDataAdapter instance from it. Unfortunately there is no IDbConnection.CreateDataAdapter() method (something similar to IDbConnection.CreateCommand()).

My current solution is to use reflection to find an adapter type based on the name of the connection, found in the same assembly/namespace. Does anybody know of a better way to generically fill a DataSet?

Code:
public DataSet FillDataSet(string SQL)
{
    DataSet data = new DataSet();

    using (ISession session = _SessionFactory.OpenSession())
    {
        IDbConnection con = session.Connection;
        Type conType = con.GetType();
        string conTypeName = conType.FullName;

        if (!conTypeName.EndsWith("Connection"))
            throw new Exception("Unable to interpret connection type name: " + conTypeName);

        string adapterTypeName = conTypeName.Substring(0, conTypeName.Length - 10) + "DataAdapter";
        IDbDataAdapter adapter = conType.Assembly.CreateInstance(adapterTypeName) as IDbDataAdapter;

        if (adapter == null)
            throw new Exception("Unable to load IDbDataAdapter: " + adapterTypeName);

        IDbCommand cmd = con.CreateCommand();
        cmd.CommandText = SQL;
        adapter.SelectCommand = cmd;

        IDisposable adapterDisposable = adapter as IDisposable;
        IDisposable cmdDisposable = cmd as IDisposable;
        try
        {
            adapter.Fill(data);
        }
        finally
        {
            if (adapterDisposable != null)
                adapterDisposable.Dispose();
            if (cmdDisposable != null)
                cmdDisposable.Dispose();
        }
    }
   
    return data;
}


Top
 Profile  
 
 Post subject: Dialect
PostPosted: Fri Feb 17, 2006 12:44 am 
Regular
Regular

Joined: Tue Jan 03, 2006 7:21 am
Posts: 85
Otherwise you can ask for the Dialect from the _SessionFactory by calling _SessionFactory.Dialect and inspect the type to determine the DB and keep a mapping between DB and DataAdapter to instantiate somewhere and instantiate accordingly


Top
 Profile  
 
 Post subject: Re: Dialect
PostPosted: Sun Feb 19, 2006 10:45 pm 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
samujob wrote:
Otherwise you can ask for the Dialect from the _SessionFactory by calling _SessionFactory.Dialect and inspect the type to determine the DB and keep a mapping between DB and DataAdapter to instantiate somewhere and instantiate accordingly

But my dilemma is that I want a way to map from an IDbConnection (or Dialect, either way) to an IDbDataAdapter without maintaining a mapping lookup table.

Anyway, my solution above worked well until I moved my application to Jet (using NHibernate.JetDriver from the NH contrib project). Instead of using the plain OleDb stuff, they decided to implement the ADO.net interfaces and decided to not include a DataAdapter!

This makes it impossible to fill a DataSet from an existing NH connection object using the JetDriver. You would have to create a new OleDbConnection based on the same connection astring and use an OleDbDataAdapter from there.

There goes my generic approach...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 2:05 am 
Contributor
Contributor

Joined: Thu May 12, 2005 8:45 am
Posts: 226
There are other ways to populate a dataset than IDataAdapter.Fill(DataSet). If you aren't using complex relationships in you data binding, you can just build a DataTable from your returned object array and add that DataTable to a DataSet.

Sorry if you already knew that. :) I would just post the DB agnostic IDataAdapter / DbDataAdapter code I wrote last year, if only I could find it!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 7:16 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
k-dub wrote:
If you aren't using complex relationships in you data binding, you can just build a DataTable from your returned object array and add that DataTable to a DataSet.

Yes, but the whole reason I need the DataAdapter in the first place is because I need to pass the results of a POSQ (plain old sql query) to an ActiveReports document. The report is not based on HQL (and I'm assuming HQL is not compatible with SQL either). I could probably write something that makes a DataTable from a DataReader, but then I'm just reinventing the DataAdapter (but a kind of generic one).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 11:26 am 
Contributor
Contributor

Joined: Thu May 12, 2005 8:45 am
Posts: 226
Quote:
NHibernate is my first experience with creating ADO.net provider independent applications. Unfortunately the reporting tool that I'm using (ActiveReports) doesn't support binding to object collections and so I must use one of those nasty DataSets.


NHibernate is much more than just provider independent. It manages the connection and ado.net provider, writes your SQL for you, caches your queries and data, and lets you use plain objects in a simple manner. In your situation the only different thing you need (it seems) is a DataTable or DataSet rather than a collection of objects.

I understand ActiveReports can use DataReaders, DataTables, DataViews, and DataSets. If you want to use NHibernate but need to give ActiveReports a DataSet, what I suggested works just fine.

Quote:
Yes, but the whole reason I need the DataAdapter in the first place is because I need to pass the results of a POSQ (plain old sql query) to an ActiveReports document.


Is the SQL coming from some other tool or are you writing it yourself? If you are writing it yourself yet want to use NHibernate, use HQL instead.

Quote:
The report is not based on HQL (and I'm assuming HQL is not compatible with SQL either).


I assume the report is based on a need to retrieve data from a database table. HQL fills this need by querying on your mapped objects. Behind the scenes, it creates SQL from your HQL based on the mappings of the objects used in the HQL. So it's not a matter of being compatible, it's a matter of doing the same thing two ways. Rather than:
Code:
SELECT * FROM Employees where LastName = 'Smith';
you can query against the Employee object like this:
Code:
from Employee e where e.LastName = 'Smith'
or even an example using parameters, which creates ado.net parameters behind the scenes:
Code:
IQuery q = mySession.CreateQuery("from Employee e where e.LastName = :lastname");
q.SetString("lastname", "Smith");
return q.List();
So if your app is creating SQL in code, NHibernate allows much more object-oriented query building with HQL, IQuery, and ICriteria.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.