Jacksonville Developers User Group

Learn new things...write better code.
Welcome to Jacksonville Developers User Group Sign in | Join | Help
in
Home Blogs Forums

Jonathan Bates

LINQ to SQL: Returning Multiple Result Sets From Stored Procedures

I have been goofing with LINQ for awhile but have gotten the opportunity very recently to really start to get my feet wet with it.  As I was demonstrating some of it to another developer yesterday, he asked about stored procedures and if LINQ to SQL supported stored procedures.  I said sure and showed him some examples of how I was using sprocs to get data.  And then he asked if it supported stored procedures that returned multiple result sets.  I told him I didn't know, but thought it had to.

When I first started working with it, I noticed that every stored procedure returned an object of ISingleResult<T>.  And I wasn't using any sprocs that returned multiple sets.  I also noticed that there was an IMultipleResults interface.  So today I thought I would see what there was to see on it.

I started by creating a simple test sproc:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE multipleResultSets
AS
BEGIN
	SET NOCOUNT ON;

	DECLARE @ResultOne TABLE
	(
		  FieldOne int
		, FieldTwo varchar(50)
	)

	DECLARE @ResultTwo TABLE
	(
		  Id int
		, Color varchar(50)
	)

	INSERT INTO @ResultOne 
	SELECT 1,'Hello'
	UNION
	SELECT 2,'Blue'
	UNION
	SELECT 3,'World'

	INSERT INTO @ResultTwo
	SELECT 1,'Green'
	UNION
	SELECT 2,'Red'
	UNION
	SELECT 3,'Blue'

	SELECT * FROM @ResultOne

	SELECT * FROM @ResultTwo
	
END
GO

With that in place, I moved on to creating a .dbml file in a Visual Studio solution and dragging in the sproc.  No matter what I did, it would always create a method in the designer using the ISingleResult interface.  As an aside, if there is anyone out there that knows how to change that via the designer, please let me know.

Undaunted, I did some research in MSDN and the great book, LINQ in Action, studying the IMultipleResult interface and how to get it to work for me.  The gist is that you write a partial class to extend your datacontext, write a method that returns IMultipleResults and decorate it with the ResultType attributes of the types the method supports.  So that gets you this:

public partial class TestDBDataContext
    {
        [Function(Name = "dbo.multipleResultSets")]
        [ResultType(typeof(FirstResult))]
        [ResultType(typeof(SecondResult))]
        public IMultipleResults GetMultipleResultSets()
        {
            IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
            return (IMultipleResults)result.ReturnValue;
        }
    }

The only other thing I needed was the types that I just referred to in the above method

    public partial class SecondResult
    {
        private int mId;
        public int Id 
        {
            get
            {
                return mId;
            }
            set
            {
                if (mId != value)
                {
                    mId = value;
                }
            }
        }

        private string mColor;
        public string Color 
        {
            get
            {
                return mColor;
            }
            set
            {
                if (mColor != value)
                {
                    mColor = value;
                }
            }
        }
    }

    public partial class FirstResult
    {
        private int mFieldOne;
        public int FieldOne
        {
            get
            {
                return mFieldOne;
            }
            set
            {
                if (mFieldOne != value)
                {
                    mFieldOne = value;
                }
            }
        }

        private string mFieldTwo;
        public string FieldTwo
        {
            get
            {
                return mFieldTwo;
            }
            set
            {
                if (mFieldTwo != value)
                {
                    mFieldTwo = value;
                }
            }
        }
    }

And finally, a test for it all

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace LINQTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TestDBDataContext context = new TestDBDataContext(@"Data Source=LEVIATHAN\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True");
            System.Data.Linq.IMultipleResults results = context.GetMultipleResultSets();

            List<FirstResult> ones = results.GetResult<FirstResult>().ToList<FirstResult>();
            List<SecondResult> twos = results.GetResult<SecondResult>().ToList<SecondResult>();

            Console.WriteLine("\n\nIn One:");
            ones.ForEach(delegate(FirstResult one){Console.WriteLine(one.FieldTwo);});

            Console.WriteLine("\n\nIn Two:");
            twos.ForEach(delegate(SecondResult two){Console.WriteLine(two.Color);});
            
            var both = (from o in ones
                        join t in twos on o.FieldTwo equals t.Color
                        select o).ToList<FirstResult>();

            Console.WriteLine("\n\nIn both:");
            both.ForEach(delegate(FirstResult o){Console.WriteLine(o.FieldTwo);});

            Console.ReadLine();
        }
    }
}

Viola!

Published Saturday, October 04, 2008 2:50 PM by jonathanbates

Comments

No Comments
Anonymous comments are disabled

About Jonathan Bates

Jonathan Bates is involved in the local development community, once even serving time as the President of the Jacksonville Developers User Group.

He has had a long and storied path on the way to I.T. work. At one point, Jonathan had a near Neo-Luddite position about computers, believing them at worst to be the means to humanity's eventual slavery and at best tools for general evil. After landing a job powered by such advanced technologies as Windows 3.11 for Workgroups and MS Access, Jonathan began to change his opinion on computers. He began to believe that they might be for more than just improving the display and sound qualities on his Laserdisc movies. In time, he came to see that computers were nothing more than tools, not much different then a hammer (though not as good to drive nails with).

Jonathan Bates is an industry-certified and proven developer and trainer, facilitating the transfer of knowledge from conceptual client request to delivered and implemented solution. Jonathan enjoys sharing his knowledge and understanding about development principals with like-minded people. You can generally find him enjoying good company discussing his personal Unified Theory and how programming can be used to describe it. And if you can't find him, drop him a line with a time and place and he'll find you.

Contact him at jonathan.bates@batener.org.

This Blog

Post Calendar

<October 2008>
SuMoTuWeThFrSa
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Syndication

Powered by Community Server, by Telligent Systems