views:

616

answers:

6

I have two databases, one is an MS Access file, the other is a SQL Server database. I need to create a SELECT command that filters data from the SQL Server database based on the data in the Access database. What is the best way to accomplish this with ADO.NET?

Can I pull the required data from each database into two new tables. Put these in a single Dataset. Then perform another SELECT command on the Dataset to combine the data?

Additional Information: The Access database is not permanent. The Access file to use is set at runtime by the user.

Here's a bit of background information to explain why there are two databases. My company uses a CAD program to design buildings. The program stores materials used in the CAD model in an Access database. There is one file for each model. I am writing a program that will generate costing information for each model. This is based on current material prices stored in a SQL Server database.


My Solution

I ended up just importing the data in the access db into a temporary table in the SQL server db. Performing all the necessary processing then removing the temporary table. It wasn't a pretty solution but it worked.

A: 

First you need to do something on the server - reference the Access DB as a "Linked Server".

Then you will be able to query it from within the SQL server, pulling out or stuffing in data however you like. This web page gives a nice overview on how to do it.

http://blogs.meetandplay.com/WTilton/archive/2005/04/22/318.aspx

Tomalak
+3  A: 

You don't want to pull both datasets across if you don't have to do that. You are also going to have trouble implementing Tomalak's solution since the file location may change and might not even be readily available to the server itself.

My guess is that your users set up an Access database with the people/products or whatever that they are interested in working with and that's why you need to select across the two databases. If that's the case, the Access table is probably smaller than the SQL Server table(s). Your best bet is to pull in the Access data, then use that to generate a filtered query to SQL Server so that you can minimize the data that is sent over the network.

So, the most important things are:

  1. Filter the data ON THE SERVER so that you can minimize network traffic and also because the database is going to be faster at filtering than ADO.NET
  2. If you have to choose a dataset to pull into your application, pull in the smaller dataset and then use that to filter the other table.
Tom H.
Agreed.. since there's an Access database on each client, it seems unreasonable to set up that many 'temporary' linked servers.
neonski
Does each Access database have different data? If so, who was the idiot who designed this setup?
David-W-Fenton
It's not that uncommon actually. There is a corporate database that has all sales, but the east-coast regional manager has an access database with just east coast clients which they use for reporting. Or a statistics team has narrowed down who they are looking at, etc.
Tom H.
BTW, those were just possible examples above. I don't know the precise situation for the original post. I was just making an educated guess.
Tom H.
A: 

Have you tried benchmarking what happens if you link from the Access front end to your SQL Server via ODBC and write your SQL as though both tables are local? You could then do a trace on the server to see exactly what Jet sends to the server. You might be surprised as to how efficient Jet is with this kind of thing. If you're linking on a key field (e.g., and ID field, whether from the SQL Server or not), it would likely be the case that Jet would send a list of of the IDs. Or you could write your SQL to do it that way (using IN SELECT ... in your WHERE clause).

Basically, how efficient things will be depends on where your WHERE clause is going to be executed. If, for instance, you are joining a local Jet table with a linked SQL Server table on a single field, and filtering the results based on values in the local table, it's very likely to be extremely efficient, in that the only thing Jet will send to the server is whatever is necessary to filter the SQL Server table.

Again, though, it's going to depend entirely on exactly what you're trying to do (i.e., which fields you're filtering on). But give Jet a chance to see if it is smart, as opposed to assuming off the bat that Jet will screw it up. It may very well require some tweaking to get Jet to work efficiently, but if you can keep all your logic client-side, you're better off than trying to muck around with tracking all the Access databases from the server.

David-W-Fenton
A: 

If I read the question correctly, you are NOT attempting to cross reference across multiple databases.

You need merely to reference details about a particular FILE, which in this case, could contain:

primary key, parent file checksum (if it is a modification), file checksum, last known author, revision number, date of last change...

And then that primary key when adding information obtained from analysing that file using your program.

If you actually do need a distributed database, perhaps you would prefer to use a non-relational database such as LDAP.

If you can't use LDAP, but must use a relational database, you might consider using GUID's to ensure that your primary keys are good.

Arafangion
A: 

Since you don't give enough information, i'm going to have to make some assumptions.

Assuming:

  1. The SQL Server and the Access Database are not on the same computer
  2. The SQL Server cannot see the Access database over a file share or it would be too difficult to achieve this.
  3. You don't need to do joins between the access database and the sql server, only use data from teh access database as lookup elements of your where clause

If the above assumptions are correct, then you can simply use ADO to open the Access database and retrieve the data you need, possibly in a dataset or datatable. Then extract the data you need and feed it to a different ADO query to your SQL Server in a dynamic Where clause, prepared statement, or via parameters to a stored procedure.

The other solutions people are giving all assume you need to do joins on your data or otherwise execute SQL which includes both databases. To do that, you have to use linked databases, or else import the data into a table (perhaps temporary).

Mystere Man
+1  A: 

Assuming Sql Server can get to the Access databases, you could construct an OPENROWSET query across them.

 SELECT a.* 
 FROM SqlTable 
 JOIN OPENROWSET(
     'Microsoft.Jet.OLEDB.4.0', 
     'C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb';'admin';'',
     Orders
 ) as b ON
     a.Id = b.Id

You would just change the path to the Access database at runtime to get to different MDBs.

Mark Brackett