Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I'm changing my EF linq query to a stored procedure. Is there an easy way to setup complex mappings?

I have an Entity Framework project containing 5 separate tables. When I query data from these tables and use .Include(), the query it generates is extremely slow and times out.

I have moved the query to a stored procedure, and now am looking for a way to query this stored procedure, and easily map the data it returns to the existing data classes.

My original Linq query to EF's DataContext looked like this:

var data = (from a in context.A
                    .Include("B")
                    .Include("C")
                    .Include("D")
                    .Include("E")
            where a.Id == someValue
            select a);

It return an Entity data object that resembled this:

class A
{
    int Id;
    string otherProperties;

    List<B> B;
    List<C> C;
    List<D> D;
    List<E> E;
}

The query that EF generated to run on SQL server returned a result set that looks something like this:

C1    C2    C3    C4    C5    C6    C7    C8    C9    C10
----------------------------------------------------------
A1    A2    B1    B2        
A1    A2                C1    C2
A1    A2                C1    C2
A1    A2                C1    C2
A1    A2                            D1    D2
A1    A2                            D1    D2
A1    A2                            D1    D2
A1    A2                                        E1    E2
A1    A2                                        E1    E2

(Assumes 1 B record, 3 C records, 3 D records, and 2 E records.

I have reproduced this query in a stored procedure and reduced its runtime to practically nothing, however I am stuck at trying to figure out how to map the result set to my Entity Framework data class (class A from above).

EF is definitely capable of this as it does it already somewhere behind the scenes when I use the Linq query, but I'm not sure if that's something I would have access to.

Is there an easy way in Entity Framework to map a single stored procedure (Function Import) to an multi-level Entity Framework class?

like image 302
Rachel Avatar asked Jan 17 '13 17:01

Rachel


People also ask

Which is better LINQ or stored procedure?

Stored procedures are faster as compared to LINQ query since they have a predictable execution plan and can take the full advantage of SQL features. Hence, when a stored procedure is being executed next time, the database used the cached execution plan to execute that stored procedure.

Which is faster EF or stored procedure?

In most cases, EF will outperform raw SQL/stored procs in terms of development speed. In order to avoid synchronisation problems between your object code and your database code, the EF designer can (upon request) update your model from your database as it changes.

Which is better stored procedure or Entity Framework?

Stored procedures handle large quantities of data much better; in fact EF has some limitations on how much data can be handled.

Can we use Entity Framework with stored procedure?

You can use stored procedures either to get the data or to add/update/delete the records for one or multiple database tables. EF API creates a function instead of an entity in EDM for each stored procedure and User-Defined Function (UDF) in the target database.


1 Answers

I found a blog post that explains how this can be done with Entity Framework.

http://blogs.infosupport.com/ado-net-entity-framework-advanced-scenarios-working-with-stored-procedures-that-return-multiple-resultsets/

To summarize it briefly, you need to write your stored procedure so it returns your data in a specific way that is expected by Entity Framework, and then you can use some EF extensions to customize your stored procedure execution, and to materialize your object graph.

It looks like this is built into Entity Framework in future versions (5.0+ I believe), however this workaround looks like it should work for lower versions.

Although in my case, I found if I just got rid of the .Include() in my Linq query and manually triggered loading the other properties by referencing them in the code before returning the object, my problem with performance got fixed. This is because instead of building one massive query between the 5 tables with unoptimized joins, it runs 5 separate queries that each only pull the specific data it needs.

like image 75
Rachel Avatar answered Sep 23 '22 14:09

Rachel