Entity Framework: How to handle the multiple result sets from store procedure (Sprocs) in edmx

This page will show you multiple ways that you can use to access more than one result set 
(here i taken 3 result sets)  from a stored procedure in Entity Framework.

Step 1: create the table like below:

I. tblPurchasedHistory:

create table tblPurchasedHistory(PurchasedID int identity(1,1),
PurchasedItemID uniqueidentifier primary key default newid(),
PurchasedItemName varchar(40),
PurchasedBy varchar(30),PurchasedMonth varchar(3) not null,PurchasedYear int not null,Amount float default 0.00 not null)

select * from tblPurchasedHistory order by PurchasedID

insert into tblPurchasedHistory values(NEWID(),'LED Television','Arunachala','Jan','2018',20000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Arunachala','Jan','2018',30000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Arunachala','Jan','2018',20000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Venkadesh','Feb','2018',20000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Venkadesh','Feb','2018',40000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Venkadesh','Feb','2018',20000.00)
insert into tblPurchasedHistory values(NEWID(),'Television','Dinesh','Mar','2018',50000.00)
insert into tblPurchasedHistory values(NEWID(),'Robot','Tony Stark','Apr','2018',50000.00)
insert into tblPurchasedHistory values(NEWID(),'Automated Vechile Launcher','Tony Stark','Apr','2018',50000.00)
insert into tblPurchasedHistory values(NEWID(),'System','Tony Stark','Apr','2018',70000.00)
insert into tblPurchasedHistory values(NEWID(),'Big size Elctro Magnet','Tony Stark','Apr','2018',80000.00)
insert into tblPurchasedHistory values(NEWID(),'Transparent Iron Suit','Tony Stark','Apr','2018',210000.00)

II.tblTest

create table tblTest(UserID uniqueidentifier primary key,UserName varchar(30),UserEmail varchar(30))

Note: Please do it yourself for data insertion

III. tblTestOne

create table tblTestOne(ID int identity(1,1) primary key,
UserIdentity uniqueidentifier foreign key references tblTest(UserID),UserAdhaarNumber varchar(40))

Note: Please do it yourself for data insertion


Step 2: create the strored procedure like below:

CREATE PROCEDURE USP_EXAMPLE_PIVOTANDSUBQUERY    
AS      
BEGIN      
DECLARE @COLS AS NVARCHAR(MAX)       
DECLARE @COLSTWO AS NVARCHAR(MAX) 
DECLARE @COLSTHREE AS NVARCHAR(MAX)
DECLARE @QUERY  AS NVARCHAR(MAX)        
DECLARE @SECONDQUERY AS NVARCHAR(MAX) 
DECLARE @THIRDQUERY AS NVARCHAR(MAX)

SET @COLS=STUFF((SELECT DISTINCT',' +QUOTENAME(PURCHASEDBY)     
                      
      FROM TBLPURCHASEDHISTORY WHERE PURCHASEDBY='TONYSTARK' 
           FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')      
      
SET @QUERY='SELECT ' + @COLS + '        
             FROM         
             (        
                SELECT PURCHASEDBY,PURCHASEDITEMID, PURCHASEDITEMNAME      
                FROM TBLPURCHASEDHISTORY        
    WHERE PURCHASEDBY=''TONYSTARK''      
          
            ) XV        
            PIVOT         
            (        
               MAX(PURCHASEDITEMNAME)      
                FOR PURCHASEDBY IN ('+@COLS+')        
            ) PV '   
      
SET @COLSTWO=STUFF((SELECT DISTINCT',' +QUOTENAME(PURCHASEDBY)     
                      
      FROM TBLPURCHASEDHISTORY WHERE PURCHASEDBY='ARUNACHALA' OR PURCHASEDBY='TONYSTARK'
OR PURCHASEDBY='VENKADESH'
           FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')      
      
SET @SECONDQUERY='SELECT ' + @COLSTWO + '        
             FROM         
             (        
                SELECT PURCHASEDBY,PURCHASEDITEMID, PURCHASEDITEMNAME      
                FROM TBLPURCHASEDHISTORY        
    WHERE PURCHASEDBY=''ARUNACHALA''  
OR PURCHASEDBY=''TONYSTARK''
OR PURCHASEDBY=''VENKADESH'' 
    --Here i declared where clause. because i need above three members output only.       
            ) V        
            PIVOT         
            (        
               MAX(PURCHASEDITEMNAME)      
                FOR PURCHASEDBY IN ('+@COLSTWO+')        
            ) P '      
             -- pivot table used to change row as column.

SET @THIRDQUERY='SELECT T.USERNAME AS ''USERNAME''      
INTO #TEMPTBL      
FROM  TBLTEST T      
LEFT JOIN TBLTESTONE T1 ON T1.USERIDENTITY=T.USERID       
      
SELECT * FROM #TEMPTBL '    

SET @QUERY=@QUERY+@SECONDQUERY+@THIRDQUERY

EXECUTE(@QUERY)  

      
END


Step 3: Find the below to the output of the stored procedure.



Step 4: Open Visual Studio (Your System Version. Here i used 2017 - express).



Step 5: Create New Project like below:



Step 6: Choose Project Template and make sure .net framework version like below or anything else.





Step 7: Choose the MVC project like below:








Step 8: Add the Entity framework 5 or 6 and System.Data into our project. please see the below:



 Step 9:



Step 10:




Step 11: Still we not get Entity framework. so we go to use Nuget.




Step 12: Here we got the entity framework under the Browse panel.



Step 13: 



Step 14:




Step 15: confirm Entity framework installed successfully.



Step 16: Add the new item. Then only we create the edmx. 



Step 17:



Step 18:



Step 19: 




Step 19: We need to make the new connection for our entity framework. 



Step 20:




Step 21: After made the new connection wizard.




Step 22: Once Finished then we choose the Tables, Views & Stored Procedures and Functions.




Step 23: Once Finish the above the step, please don't forget to give "Save All". 

Once edmx is produced result then open web.config file and confirm the below. Also confirm "MultipleActiveResultSets=True".





Step 24: This is the edmx diagram surface. Here we can view our Tables, Relationships etc., 




Step 25: Here is our store procedure. please note, the edmx returns it as int value but we need to convert this as collection.



Step 26: Before that we do some changes or creating the properties like below. So open the "model browser".




Step 27:




Step 28: After open model browser (righ click on edmx design surface), to be create "complex types" (give any name to this type)   and this property exactly matched with result set's "column name" from stored procedure  output 's column name.



Step 29: 



Step 30: create the result set as complex types. 




Step 31: Create the properties which name should exactly match with sql output column name.




Step 32: Repeat the step 31 to create the properties.




Step 33: Make sure properties are allow the nullable values and set the maximum length as well.



Step 34:



Step 35: After that Close edmx design and right click on edmx in solution explorer and choose   "open with" then "XML(Text) Editor" or "Automatic Editor Selector(XML)" or anything.



 Step 36:



Step 37: XML edmx overview is here. So the edmx has three types. 1. Storage Models 2. Conceptual Models 3.Mappings



Step 38: We should make sure our store procedure is in "Storage Model" or not and set the result mapping in the below: 





Step 39:

1. edmx:StorageModels => our store procedure must kept here.

2. edmx:ConceptualModels => we can customize our return result types here. it may be one or more than one return type. 
  
 it is an declaration part. what we declare here then mappings part also be same.

         default value for our store procedure in edmx=> 

<EntityContainer Name="testdbEntities" annotation:LazyLoadingEnabled="true">
<FunctionImport Name="USP_Example_PivotAndSubQuery" />
</EntityContainer>

         customized value: 

<edmx:ConceptualModels>
      <Schema Namespace="testdbModel" Alias="Self" annotation:UseStrongSpatialTypes="false" 
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" 
xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" 
xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
:
:
:
<EntityContainer Name="testdbEntities" annotation:LazyLoadingEnabled="true">
       <FunctionImport Name="USP_Example_PivotAndSubQuery" >
            <ReturnType Type="Collection(testdbModel.USP_MultipleResult_One)"/>
            <ReturnType Type="Collection(testdbModel.USP_MultipleResult_Two)"/>
            <ReturnType Type="Collection(testdbModel.USP_MultipleResult_Three)"/>
        </FunctionImport>
</EntityContainer>

<ComplexType Name="USP_MultipleResult_One" >
          <Property Type="String" Name="TonyStark" Nullable="true" MaxLength="50" />
        </ComplexType>

        <ComplexType Name="USP_MultipleResult_Three" >
          <Property Type="String" Name="USERNAME" Nullable="true" MaxLength="50" />
        </ComplexType>

        <ComplexType Name="USP_MultipleResult_Two" >
          <Property Type="String" Name="Arunachala" MaxLength="50" Nullable="true" />
          <Property Type="String" Name="TonyStark" Nullable="true" MaxLength="50" />
          <Property Type="String" Name="Venkadesh" Nullable="true" MaxLength="50" />
        </ComplexType>
:
:
:
</Schema>
    </edmx:ConceptualModels>

3. edmx:Mappings => default value: 

<FunctionImportMapping FunctionImportName="USP_Example_PivotAndSubQuery" FunctionName="testdbModel.Store.USP_Example_PivotAndSubQuery" />

After Customized:

<edmx:Mappings>
      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="testdbModelStoreContainer" CdmEntityContainer="testdbEntities">
:
:
:

  <FunctionImportMapping FunctionImportName="USP_Example_PivotAndSubQuery" FunctionName="testdbModel.Store.USP_Example_PivotAndSubQuery">

            <ResultMapping>
              <ComplexTypeMapping TypeName="testdbModel.USP_MultipleResult_One">
                <ScalarProperty Name="TonyStark" ColumnName="TonyStark"/>
              </ComplexTypeMapping>
            </ResultMapping>

            <ResultMapping>
              <ComplexTypeMapping TypeName="testdbModel.USP_MultipleResult_Two">
                <ScalarProperty Name="Arunachala" ColumnName="Arunachala"/>
                <ScalarProperty Name="TonyStark" ColumnName="TonyStark"/>
                <ScalarProperty Name="Venkadesh" ColumnName="Venkadesh"/>
              </ComplexTypeMapping>
            </ResultMapping>

            <ResultMapping>
              <ComplexTypeMapping TypeName="testdbModel.USP_MultipleResult_Three">
                <ScalarProperty Name="USERNAME" ColumnName="USERNAME"/>
              </ComplexTypeMapping>
            </ResultMapping>
          </FunctionImportMapping>


:
:
:
:
 </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>

Step 40: Screenshot for the above codings.

Conceptual Models:




Mappings:




Step 41:

In solution explorer, open "WebApple.Context.cs" and change "public virtual ObjectResult<USP_MultipleResult_One> USP_Example_PivotAndSubQuery()"
instead of "public virtual int USP_Example_PivotAndSubQuery()".

Here i change the object result instead of int by mannually. because the sql data reader executes one by one.

So,here based on my setting, the data reader executes the function and returns the 3 result set in single execution.

In "WebApple.Context.cs", i set first result object to the above method.

"public virtual ObjectResult<USP_MultipleResult_One> USP_Example_PivotAndSubQuery()"

Because the sql data reader executes the store procedure in single execution.  Here we get first result set automatically.

Here after we can get next result set from data reader, once first result set read is completed. 

So we got 3 types of result set from sql data reader one by one like using the method "GetNextResult<Model>()". How means, Already we set 3 types of "ResultMapping" in above xml coding.

Example:

if(dr.Read())
{
  if(dr(0).Read())
  {
    if(dr(1).Read())
   {
     //..Some Work Needed
   }
  }
}
Please find the below codings in controller:

using System.Linq;
using System.Web.Mvc;

namespace WebApple.Controllers
{

 public class HomeController : Controller
    {
protected internal testdbEntities _dbEntity;

        public HomeController()
        {
            _dbEntity = new testdbEntities();
        }
        public ActionResult Index()
        {

            var firstResultSet = _dbEntity.USP_Example_PivotAndSubQuery().ToList();          

            var secondResultSet = _dbEntity.USP_Example_PivotAndSubQuery().GetNextResult<USP_MultipleResult_Two>().ToList();

            var thirdResultSet = _dbEntity.USP_Example_PivotAndSubQuery().GetNextResult<USP_MultipleResult_Two>().GetNextResult<USP_MultipleResult_Three>().ToList();


            return View();
        }
}

}


Step 42: Ouputs.


Output-1:




Output-2:





Ouput -3:





Refrence:

 https://msdn.microsoft.com/en-us/library/jj691402(v=vs.113).aspx#Multiple%20Result%20Sets%20with%20Configured%20in%20EDMX



Thanks..

Comments