简体   繁体   English

我将EF linq查询更改为存储过程。 有没有简单的方法来设置复杂的映射?

[英]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. 我有一个包含5个独立表的Entity Framework项目。 When I query data from these tables and use .Include() , the query it generates is extremely slow and times out. 当我从这些表中查询数据并使用.Include() ,它生成的查询非常慢并且超时。

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: 我对EF的DataContext的原始Linq查询如下所示:

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: 它返回类似于以下内容的Entity数据对象:

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: EF生成的在SQL Server上运行的查询返回的结果集如下所示:

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. (假设1 B记录,3 C记录,3 D记录和2 E记录。

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). 我已经在存储过程中重现了此查询,并将其运行时减少到几乎没有,但是我一直试图找出如何将结果集映射到我的Entity Framework数据类(上面的A类)。

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. EF绝对有能力做到这一点,因为当我使用Linq查询时,它已经在后台进行了处理,但是我不确定是否可以访问。

Is there an easy way in Entity Framework to map a single stored procedure (Function Import) to an multi-level Entity Framework class? 实体框架中是否有一种简单的方法将单个存储过程(函数导入)映射到多层实体框架类?

I found a blog post that explains how this can be done with Entity Framework. 我找到了一篇博客文章,解释了如何使用Entity Framework做到这一点。

http://blogs.infosupport.com/ado-net-entity-framework-advanced-scenarios-working-with-stored-procedures-that-return-multiple-resultsets/ 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. 概括地说,您需要编写存储过程,以便它以Entity Framework期望的特定方式返回数据,然后您可以使用一些EF扩展来自定义存储过程的执行并具体化对象图。

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. 看来这是将来版本(我认为是5.0+)中内置的Entity Framework,但是这种解决方法似乎应该适用于较低版本。

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. 尽管就我而言,我发现是否只是在Linq查询中摆脱了.Include() ,并在返回对象之前通过在代码中引用它们来手动触发加载其他属性,但性能问题已得到解决。 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. 这是因为它不是在5个具有未优化联接的表之间构建一个庞大的查询,而是运行5个独立的查询,每个查询仅提取所需的特定数据。

When I am optimizing EntityFramework by converting an expensive query to a storedprocedure, I create a custom class for the results and then do some logic in the DbContext to convert my custom class into the Entities. 当我通过将昂贵的查询转换为存储过程来优化EntityFramework时,我为结果创建一个自定义类,然后在DbContext中执行一些逻辑以将我的自定义类转换为实体。

So you'd create something like 所以你会创建类似

public class StoreProcARow
{
public string Name {get;set;} // properties for every column
}

And then in your DbContext 然后在您的DbContext

public A GetA(int ID)
{
// do stored procedure
IEnumerable<StoreProcARow> procResult = ...
// process procResult into A type

}

Try AutoMapper . 尝试使用AutoMapper

You'd do something like: 您将执行以下操作:

using AutoMapper;

...

Mapper.CreateMap<DataModel.B, ReplyObjects.B>;
Mapper.CreateMap<DataModel.C, ReplyObjects.C>;
...
return new A
{
  B = Mapper.Map<DataModel.B, ReplyObjects.B>(varContainingDataForB),
  C = Mapper.Map<DataModel.C, ReplyObjects.C>(varContainingDataForC)
  ...
};

As long as the properties in your ReplyObjects.B matched the names and types of the DataModel.B, everything will map up automatically! 只要您的ReplyObjects.B中的属性与DataModel.B的名称和类型匹配,所有内容都将自动映射!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM