views:

91

answers:

4

Before LINQ I would have my main application return the results of a SQL query into a dataSet. I would then transfer the dataset as a parameter to the external dll. Now I am bringing through a LINQ to SQL query that is returned as an IQueryable(Of vClientTable) object. I want to be able to transfer that set of vClientTable results to my external dll in order for the dll to work with the data included in the results.

I am probably doing it all wrong as well as trying to do it all wrong, but would like some advice on what would be the best method to use.

DB Query

Public Shared Function getClientData(ByVal clientID As Int32) As IQueryable(Of vClientTable)
Try
 Dim r = From p In dbLINQ.vClientTable _
    Where p.ltClientID = clientID _
    Order By p.cdCode _
    Select p
 Return r
Catch ex As Exception
 Return Nothing
End Try
End Function

App Sub that retrieves the Data through the DB Query

Dim recordData As IQueryable(Of vClientTable) = getClientData(clientID)

Call to External DLL sub

dataComplete = outputClientData(Now, recordData)

DLL sub

public static Boolean outputClientData(DateTime rptDate, IQueryable<vClientData> clientData)
 {
  //Do something with the data
  return true;
 }

Obviously in the external dll it has no idea what an IQueryable(vClientData) object is and even if I create a dbml file and datacontext in my external project for the dll that includes the same class to the DB table/view it still says that the objects are different types.

Any ideas how I should be proceeding with this?

Thanks

+1  A: 

Can the external dll reference the assembly with the entities in them? Then you can return any collection/set/whatever of your types. That is the simplest use.

I would, however, tend to avoid exposing IQueryable<T> on the API, since it is very hard to guarantee full support for all operations, and hard to guarantee that the caller doesn't break your DAL (accidentally or on purpose); I would have discreet operations that return known constructs such as List<T>, T[], etc.

If you can't add a reference, then other options include:

  • serialization (this is essentially how WCF transfers such objects; just enable serialziation on the designer surface, and use DataContractSerializer; you will need a matching data-contract at the other end, but it doesn't have to be the same type)
  • transfer into a known type such as DataTable - a bit like this and this, although I'm not really a fan of DataTable
  • expose it as object, and use reflection (ho-hum)
Marc Gravell
Marc, the external dll is actually a dll/class that has a separate project within my solution and is used purely to export data into an Excel format. I have full control over how the 'external' dll works.I am only using IQueryable as this was what appeared to return the best results and was relatively easy to use within the application.
TravisPUK
I am using DataTable in other areas, but only when I have a small amount of columns. In this particular example I am returning something like 30-40 columns and multiple rows. Building the datatable seems to be a cumbersome way of doing this, although it was my first thought. But then I thought I would throw the quessie out there to see if there was a better way.
TravisPUK
+1  A: 

I'm assuming that once you get to your external dll that your IQueryable would have had it's context closed, so right there you have a problem. If you try to enumerate through the result set you could get an exception since it's most likely that the context has already been disposed. FYI, the context is basically the thing that connects your IQueryable to your database.

As for what to return, I would suggest starting by returning an IList first, instead of an IQueryable. You can do this by calling .ToList() on your IQueryable, and then you would have an

IList<vClientData>

This should at least get you started in learning how to get around with LINQ. Learning how to properly use the IQueryable construct is going to take some practice and learning, but pushing the result set out to an IList or array of some sort should get you on your way.

Joseph
Joseph, exactly the external dll has no knowledge of the context, even if I create its own context it appears that it sees them as different anyhow. I will attempt to make the IList type work. My data though is multi-row, multi-column would that cause any issues with the IList?
TravisPUK
@Travis What you should expect to see is a list of vClientTable instances get populated once you enumerate through the result set. So, for instance, since you're looking for only instances where ltClientID = clientID, lets say there are 4 records in your table that match that criteria. You will have 4 instances of vClientTable objects in your list. If your expecting only one record from that query, I would change it from returning an IList and use First or FirstOrDefault instead, which will just return the first vClientTable object the query gets.
Joseph
@Joseph, definitely expecting more than one record.
TravisPUK
A: 

What is the external DLL method signature? More specifically, whats the type it expects recordData to conform to?

Cheers, Florian

Florian Doyon
+1  A: 

My first reaction here would be to abstract the data access layer into it's own assembly and to give both your application and your DLL references to it. This would allow you to reference the vClientData class in both as it's only that which you need to share.

Lazarus
Sounds like a great idea, but I am a bit too newbie to make that happen. I will certainly see if I can work out how it works though thanks.
TravisPUK
Have a look around the web for information on the repository pattern, that should give you a good idea of what kind of thing you are looking for. There are examples out there in C# I'm sure.
Lazarus