为什么在使用.Entity Framework中的.ToList()和.Include时速度非常慢,如何加快它的速度?

4

我正在使用EF4查询Oracle数据库。

我有两个表POINTS(大约有10万行)和COUNTRIES,每个点都有一个作为外键的countryCode

在存储库中,我有以下两种方法:

public List<PointsTable> GetAll()
{
    using (Entities context = new Entities())
    {
        List<PointsTable> theList = context.POINTS_TABLE.ToList();
        return theList;
    }
}

public List<PointsTable> GetAllComplete()
{
    using (Entities context = new Entities())
    {
        List<PointsTable> theList = context.POINTS_TABLE.Include("Countries").ToList();
        return theList;
    }
}
GetAll需要5秒钟,但是GetAllComplete需要2分钟!
我已经使用了AsParallel(),但是效果微乎其微。
我能否加快速度或者是什么造成了它的缓慢?

GetAllComplete正在与Countries表进行连接,并获取所有的点和国家信息,而GetAll只是获取所有的点而已,没有关联表。 GetAllComplete获取的行数据要比GetAll多得多。在处理大数据时,使用ToList()获取所有项并不是一个好主意。 - Kamil Budziewski
但是我在这里完全迷失了,如果我在PL/SQL中运行这个查询,下面的两个查询之间没有任何区别: select * from POINTS_TABLEselect * from POINTS_TABLE a left join COUNTRY_TABLE b on B.CountryCode = A.CountryCode - DonQi
1
这是EF而不是SQL,ORM比SQL客户端慢得多,如果你真的需要一次获取20万行,请使用ADO.NET而不是EF。但我宁愿使用LINQ逐行或以100点为单位获取。 - Kamil Budziewski
@wudzik 在你对 GetAll 的解释中说“只是获取所有点而不包括引用表”,但我在调试时可以通过快速监视看到整个图形。那么这是因为调试功能遍历了整个图形吗? - Anto Varghese
2个回答

7
原因是对于每个记录,您都要检索其国家/地区,对于20万个记录,这将乘以许多个记录。
如果您将来要查询此数据以将其减少到特定需求,请勿立即使用".ToList()"。
将您的存储库方法更改为返回"IQueryable",这样您可以在后面限制查询到特定数据,从而减少放入内存的数据量。
private Entities _context;

public PointsRepository(Entities context)
{
    _context = context
}

public IQueryable<PointsTable> GetAll()
{
    return context.POINTS_TABLE;
}

public IQueryable<PointsTable> GetAllComplete()
{
    return context.POINTS_TABLE.Include("Countries");
}

然后,您可以添加特定的过滤器并将结果ToList,例如:

using (Entities context = new Entities())
{
    var rep = new PointsRepository(context);

    // This will change the query you send to sql to only 
    // retrieve the specific data you want and should result 
    // in much quicker execution
    var result = rep.GetAllComplete()                    // get all with includes
                    .Where(p => p.Property = "Specific") // refine the query 
                    .ToList()                            // retrieve the data and add to memory
}

希望这可以帮到你。

0

AS Parallel() 只能与 Linq to Object 一起使用,无法与 Linq to Entities 一起使用。

使用 EF 加载 200K 不是一个好的选择。

您可以通过只读加载来提高性能:

context.POINTS_TABLE.MergeOption = MergeOption.NoTracking;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接