Rounding the Corner

Thoughts About Software Development From the MST Staff.

Entity Framework 5 – Multiple Entity-Typed Result Sets from a Stored Procedure

/ 19. March 2012

Using Entity Framework (EF) to call a stored procedure that returns multiple result sets (aka “MARS”) is something of a moving target. This post will explain how to use MARS in the upcoming Entity Framework 5 (currently available in the VS 2011 beta or via NuGet). In particular, I want to expand on this Microsoft Post showing how to leverage entity types.

History

But First, a little history on the topic.  Why is MARS a moving target?   In EF 4 it was impossible—well, sort of.  Once entity framework extensions were released it was possible to write the ADO  connection/command yourself  while still leveraging the conceptual model and hydration capabilities of EF.  The process hinged on a snippet of code something like:  Translate<MyEntityFrameworkType>(myADO_Reader).

Then along came the June 2011 CTP and hallelujah “stored procedures can now have multiple result sets.”   EF 4.2 and 4.3 were subsequently release and the feature was missing. Huh? Well, the CTP apparently required some changes to the core EF object and would only be released with .NET 4.5.  

So EF 5 will apparently support MARS.  From the commentary, however,  it appears that MARS will be supported in EF’s plumbing, but the modeling tools won’t expose the option.  This leaves one editing the EDXM manually—not fun, but arguably better than writing your own ADO code like EF 4 required.  

The Microsoft Article

Over in Redmond the ADO.NET team was kind enough to post a walk through for using MARS detailing how to fill two complex types.  The article is pretty long, but if you’re already using EF step 7 and 8 explain how the EDMX file needs to be edited. Then step 9 shows the syntax for retrieving subsequent result sets.

If you’re familiar with EF you know there are Entity Types, which loosely correspond to the tables you see in your model browser. There are also Complex Types, which the tool cajoles you to use as the return type for most stored procedures.

Unfortunately, what the article doesn’t explain is how to return entity types.  As an EF user Entity Types are a large portion of your model, and leveraging these types is likely important.  Following is some simple EDXM to show how Entity Types can be returned.

 

MARS & Entity Types

Once you’re familiar with  the Microsoft article there isn’t much to say…all you need is the syntax for returning Entities.   Figuring out that syntax is, well, not very fun.  It took quite a bit of digging in the MS-MSL and MS-CSDL specs listed at the end of the article.  I managed, however, to coble together a working example and the result is fairly easy to understand..

My working example consisted of a tiny two table model:  Two tables (Table_A and Table_B) and a single stored procedure (MyMARS_Proc which SELECT’s * from A & B).    Given this model, your EDX would be as follows.

In the CSDL section of your model :

<edmx:ConceptualModels>
   <Schema Namespace="myModel" ...>
     <EntityContainer Name="myModelEntities" ....>
     ......
     <!--  
        this is what “function import” wrote, that I’m overwriting…          
        FunctionImport Name="MyMARS_Proc" ReturnType="Collection(myModel.Table_A)"/> 
      --> 
      <FunctionImport Name="MyMARS_Proc" > 
         <ReturnType Type="Collection(myModel.Table_A)" EntitySet="Table_As"/> 
         <ReturnType Type="Collection(myModel.Table_B)" EntitySet="Table_Bs"/> 
      </FunctionImport> 
 

Then down in the MSL (C-S mapping) section you’ll want:

<!-- C-S mapping content -->
<edmx:Mappings>
  <Mapping Space="C-S" ....>
    <EntityContainerMapping  ....>

       <FunctionImportMapping FunctionImportName="MyMARS_Proc"
                               FunctionName="myModel.Store.MyMARS_Proc"> 
            <ResultMapping> 
                <EntityTypeMapping  TypeName="myModel.Table_A"/> 
            </ResultMapping> 
            <ResultMapping> 
                <EntityTypeMapping TypeName="myModel.Table_B"/> 
            </ResultMapping> 
       </FunctionImportMapping>

 

Research

Development ,

Comments (3) -

fred lauriello
fred lauriello
6/8/2012 8:28:09 AM #
Great- I was successful getting this to work for the first two returns.

I cannot for the life of me figure how to materialize a third or forth
record. There are no examples that I can find. Can you help with a short example??    
fred lauriello
fred lauriello
6/9/2012 7:33:54 PM #
Never mind, I figgured it out !
ebarr
ebarr
8/1/2012 10:24:10 AM #
@Fred - sorry I didn't see this until now.  Adding a 3rd, 4th, or 5th, record set is as simple as moving on to "Table_C" "D" or "E" in my example

Add comment


(won't show your email and don't even know how to sell it!)

  Country flag

biuquote
  • Comment
  • Preview
Loading