Question

creating a .net CLR SQL Server 2005 Function to return result sets

Asked by: xersoft

I have the following function. I realize this isn't a good use of CLR functions but I'm just trying to learn right now. What would the return type for this function be or am I returning the result set incorrectly?

I want to use a function so I can later join to this in another query.

   <Microsoft.SqlServer.Server.SqlFunction()> _
    Public Shared Function SelectData(ByVal UserId As Integer) As SqlString


        Using cmd As New SqlCommand
            cmd.CommandText = "select * from SomeTable where userId = " & UserId
            Using dr As SqlDataReader = cmd.ExecuteReader

                SqlContext.Pipe.Send(dr)

            End Using
        End Using

        Return New SqlString("")
    End Function

When I try and register this function I am told via an error that the return type is not correct.

How do I return a result set from a CLR function? Does anyone have any simple examples that pull data from the same database (not some other second data source like an RSS feed)

Thanks so much for the help.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2007-07-24 at 15:11:02ID22718500
Tags

clr

,

sqldatareader

,

sql

Topics

SQL Server 2005

,

Microsoft Visual Basic.Net

,

.Net Editors & IDEs

Participating Experts
1
Points
250
Comments
13

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. dr = cmd.ExecuteReader()
    I have an error on this line: dr = cmd.ExecuteReader() Incorrect syntax near '='. What's wrong with my code? Private Sub verifycus() Dim objConn As New SqlConnection("Server=myhost; Initial Catalog=mydb; User ID=myid; Password=mypw") objConn.Open() ...
  2. generate rss feed
    hi there; i'm just now starting to get familiar with rss and am having issues finding solutions to the following: i have a sql database with tblNews (fldNewsID, fldNews, fldNewsDate) using asp.net (vb 2.0) what i would like, i think, is somewhat simple to implement, but i a...
  3. RSS Feed
    I want to make a visual basic application that is a slide show but it needs to get the slides from an rss feed. How do I even begin to program something like that?
  4. Using RSS Feeds
    I'm trying to use an rss feed on my asp.net website but can't get it to work. Here is the code behind the webpage: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load rssPosts.DataSource = GetRSSFeed("http://www.thepit...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: tedbillyPosted on 2007-07-24 at 20:46:13ID: 19562502

 

by: xersoftPosted on 2007-07-25 at 06:42:52ID: 19565225

Thanks tedbilly for the reply. I'm afraid I don't understand how that works based on those examples. I'm not seeing the link between the InitMethod and the FillRow method. This is what I came up with but it seems odd because I'm creating a datatable full of data which is really not what I need. I just want to stream out the results. Thoughts? Do I have to go through all the work of creating a datatable just so I can enumerate?

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Runtime.InteropServices

Partial Public Class UserDefinedFunctions

    Public Class TabularEventLog
        <SqlFunction(FillRowMethodName:="FillRow", systemdataaccess:=SystemDataAccessKind.Read)> _
        Public Shared Function InitMethod(ByVal UserId As Integer) As IEnumerable

            Dim outDT As New DataTable

            Using adp As New SqlDataAdapter("select fName, lName from SomeTable where userId = " & UserId, New SqlClient.SqlConnection())
                adp.Fill(outDT)
            End Using

            Return outDT.Rows
        End Function

        Public Shared Sub FillRow(ByVal obj As Object, <Out()> ByRef fName As SqlString, <Out()> ByRef lName As SqlString)
            Dim dr As DataRow = DirectCast(obj, DataRow)
            fName = New SqlString(CStr(dr.Item("fName")))
            lName = New SqlString(CStr(dr.Item("lName")))
        End Sub
    End Class

End Class

 

by: tedbillyPosted on 2007-07-25 at 10:20:51ID: 19567701

Well I answered your question literally, which was returning a table from a CLR udf Function and you asked about learning the capabilities of CLR functions which I gave you.

CLR functions can return scalar or non-scalar results.  So, you are returning one discrete value or a data set.  Stored procedures are basically the same.  You are returning values as discrete data types OR a data set.

Can you describe your business requirements?

 

by: xersoftPosted on 2007-08-02 at 06:36:59ID: 19616728

tedbilly,

thank you very much for the response. Part of my question is below. The example you gave does not demonstrate how to do this. It's possable I'm not reading it correctly, if that's the case can you point out the section that talkes about doing this? Thank you again for your help!

How do I return a result set from a CLR function? Does anyone have any simple examples that pull data from the same database (not some other second data source like an RSS feed)

My requirement is to write a CLR UDF function that returns a result set from a query returning data from the database hosting the CLR UDF. I then want to join the results of that query with another query. Basicly exactly as I could with a standard UDF but with CLR.

 

by: tedbillyPosted on 2007-08-02 at 21:37:11ID: 19622602

Hmm, well then the link I gave you is correct. The example I have you shows you how to create a CLR UDF.

If you want the UDF to return a table from the database hosting it you do not need to create a CLR UDF.  You can create a standard UDF function.

Can you give me more details because I've given you everything you need to write a CLR UDF.  By details I mean the database schema and the join you need to do.

 

by: xersoftPosted on 2007-08-04 at 11:23:59ID: 19631729

I thank you very much for your help tedbilly but Im afraid I dont see your solution.

Its possible Im not asking the correct question but as I look back over my previous responses and initial question I believe Im clearly asking how to return data from the host database from a CLR UDF.


At the end of my initial question there is this:

How do I return a result set from a CLR function? Does anyone have any simple examples that pull data from the same database (not some other second data source like an RSS feed)

You provided an example that did satisfy the first question, which was how to return a result set from a CLR function BUT it did exactly what I said I didnt want it to do in the second part which was to NOT pull data from a second data source, in your case the event log.

Now if the example you gave me does indeed pull data from the hosting database and returns it as a result set I think perhaps I need to give it another look, maybe you can point me to the right place in the article.

I mean no disrespect to you but Im not seeing your solution as fitting my question.

 

by: xersoftPosted on 2007-08-04 at 11:29:32ID: 19631742

I looked at the example you gave again: http://msdn2.microsoft.com/en-us/library/ms131103.aspx and I do see that it says it wll return a result set BUT it returns a result set from the event log and not from the database. How can I return the result set generated from Select * from sometable where field='value'

that's what I was trying to do in my inital post. I failed but that's what I'm trying to do.

 

by: tedbillyPosted on 2007-08-04 at 11:44:22ID: 19631775

If you want to return a result set from the database you do not need a CLR UDF.  I've already mentioned this point but I think you missed it.  If you want to return data from the same database or SQL server as the UDF you do NOT need a CLR function.

The purpose of the CLR in SQL is to create custom SQL objects to do things that SQL cannot do.  A standard UDF function can return a table in the same database.

The following article has an example of how to return a table using a standard UDF
http://www.databasejournal.com/features/mssql/article.php/1438081

The following article explains where and when to use the CLR in SQL
http://www.microsoft.com/technet/prodtechnol/sql/2005/clr4dbas.mspx

 

by: xersoftPosted on 2007-08-04 at 13:01:12ID: 19631944

Alright the business case... This is going to be long but perhaps you will see a better way to do this.

I have a table called Transaction, which has an integer primary key along with five foreign keys, which relate back to tables, which contain a single integer primary key along with other fields.

For example, one table is the name table that holds the specific name of the transaction.

Actually, this is just a simple implementation of a star schema.

Another of the foreign keys on the transaction table is UserId.

My goal was to create a view, which would return all transaction Ids which I could then use in other queries in a join situation. This view needed to take a user Id so it only returned those transactions owned by the specific user. So a view that uses a parameter, or a UDF.

One can imagine how easy this particular UDF was. Something along the lines of

Select id from transaction where userid = @userid

Now whenever I wanted to get some piece of data about a users transactions I could just use this UDF, passing in the UserId, and get a list of all transactions that fit. I use this view all over the place trusting that I will ONLY  get transactions for the given user.

Then some time later I wanted to extend the app I was working on to allow for the following:

The user was able to specify a dynamic set of criteria which would be applied and the ENTIRE SET of functionality the app offered would continue to work but with the new filtered results.

So I think to myself that should be easy. I have one single point where I pull data. My UDF takes a user ID and passes back all the data. What if I also passed in a varchar where clause into that procedure and dynamically returned the results. My query ended up being Select Id from transaction where userid = @userid and @WhereClause. Now in the UDF I needed to create a varchar to hold the new dynamic query and then use exec to return the results.

Oops I cant use exec in a UDF. So I thought I was stuck. Changing the entire app was not possible. I couldnt rewrite every single feature to take into account a dynamic where clause.

So I decided this might be a valid use for a CLR UDF. I knew this was slower then standard TSQL so I settled on a compromise. When the UDF was called with the dynamic where clause I would use the CLR UDF from inside the standard UDF but when the where clause was blank I could continue doing it the way I was already.

Therefore, the user will only see a slow down when they have these dynamic where clauses filtering all the data.

So I made the necessary adjustments to the UDF, applying an if/else that would return the correct values.

Now I know how to construct a query with the dynamic where clause. What I dont know is how to select data from my CLR function and return it to the caller.



I realize this is long and complicated but if you get through it and understand what Im trying to do Im more then willing to listen to advice you have. For example, do you know how to run a dynamic SQL statement from inside a UDF? Or do you know how to return a result set queried from the host database from a CLR UDF?


I fall back to my initial question again, just so everyone knews Im not holding the thread hostage.

How do I return a result set from a CLR function? Does anyone have any simple examples that pull data from the same database (not some other second data source like an RSS feed)

Thank you.
This is a lot of text, sorry for any typos.

 

by: tedbillyPosted on 2007-08-04 at 14:00:33ID: 19632068

What you are trying to do can be achieved in stored procedures or the business layer of your application.  You do not need a CLR and it is not well suited for your case.

I've solved your problem quickly and easily many times in transaction SQL using views or stored procedures.

I give up.  You have everything you need to solve this problem.

 

by: xersoftPosted on 2007-08-04 at 19:16:30ID: 19632712

Stored Procedures: Yes that could be done but would require me to rewrite the app, which I said I didn't want to do. Or can the results of a stored procedure be used in joins in other queries (I believe no but I may be wrong)

Business Layer: Yes it could be done here but I don't want to return countless rows of data from the server only to have the BL filter them based on some logic. This is wasteful.
I'm not sure exactly what solution you offered other then saying the CLR was not the correct solution.

A number of times I asked a question, how to return a result set obtained from a query in the host database with a CLR function. If that can't be done let me know. If it can and you know how then tell me and I will award you the points.

 

by: tedbillyPosted on 2007-08-04 at 20:07:31ID: 19632851

The first example I have you showed how to write a CLR UDF and return a table.  The next example shows how to access the host database within a CLR stored procedure.  You'll have to combine the two.

http://www.sqlteam.com/article/writing-clr-stored-procedures-in-charp-returning-data-part-2

 

by: xersoftPosted on 2007-08-30 at 14:25:20ID: 19804326

After a lot of trial and error and some Googleing to get some more results I found what I needed. I used a few of the examples provided by tedbilly to come up with this example of how to pull data from a database, return it from a function.

The schema to perform this test (just made it up, syntax is probably wrong)

CREATE TABLE [dbo].[Person](
      [id] [int] IDENTITY(1,1) NOT NULL,
      [Name] [varchar](100) )

CREATE TABLE [dbo].[Address](
      [id] [int] IDENTITY(1,1) NOT NULL,
      [PersonId] [int] NOT NULL,
      [Address] [varchar](100) )

The VB code

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Runtime.InteropServices

Partial Public Class UserDefinedFunctions

    <SqlFunction(FillRowMethodName:="FillRow", systemdataaccess:=SystemDataAccessKind.Read, DataAccess:=DataAccessKind.Read)> _
    Public Shared Function InitMethod(ByVal WhereClause As String) As IEnumerable

        Dim outDT As New DataTable

        Using adp As New SqlDataAdapter("Select * from Person where " & WhereClause, New SqlClient.SqlConnection("Context Connection=true"))
            adp.Fill(outDT)
        End Using

        Return outDT.Rows
    End Function

    Public Shared Sub FillRow(ByVal obj As Object, <Out()> ByRef Id As SqlInt32, <Out()> ByRef Name As SqlString, <Out()> ByRef Age As SqlInt32)
        Dim dr As DataRow = DirectCast(obj, DataRow)
        Id = New SqlInt32(CInt(dr.Item("Id")))
        Name = New SqlString(CStr(dr.Item("Name")))
        Age = New SqlInt32(CInt(dr.Item("Age")))
    End Sub


End Class

How to install it to the server after you added the assembly to the database:

CREATE FUNCTION GetUserNamesWithIdGreater(@WhereClause nvarchar(1000))
RETURNS TABLE (id int, [Name] nvarchar(100), Age int)
EXTERNAL NAME AssemblyName.[Namespace.UserDefinedFunctions].InitMethod;


Now comes the fun part! You can do this:

select * from dbo.GetUserNamesWithIdGreater('Age > 2') Person inner join Address on Person.Id = Address.PersonId

Really quick dynamic SQL which you can join on! Though I realize its not the best solution it is a fast change to an existing app which already uses a function.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...