在实体框架中处理大数据的最佳方法

时间:2018-09-10 12:06:33

标签: c# performance entity-framework

嗨,我使用的是EF6,我在其中有大量数据可以从数据库中进行查询,如下所示:

var EntityInfo = _contextRegister.Entities.Where(x => x.IsDeleted != true).ToList();
foreach (var itm in EntityInfo)
{
    Entity.Entity entity = new Entity.Entity();
    entity.MainActivityId = itm.MainActivityId;
    entity.SubGroupId = itm.SubGroupId;
    entity.Id = Convert.ToInt32(itm.Id);
-------
    entity.UAECityRegion = _contextFRAMEWORK.UAECityRegions.Where(m => m.Id == itm.UAECityRegionId).Select(m => m.RegionName).FirstOrDefault();
    var voucherstautus = _contextRegister.EPayVoucherDatas.Where(m => m.EntityId == itm.Id).ToList();
    foreach (var item in voucherstautus)
    {
        if (item.VoucherStatus == 10)
        {
            entity.PaymentStatus = Convert.ToInt32(item.VoucherStatus);
            break;
        }
     }

     entityList.Add(entity);
}

此查询耗时超过10分钟,在哪里可以使该查询更好,还是应该使用存储过程而不是框架?

2 个答案:

答案 0 :(得分:1)

据我所知,EntitiesEPayVoucherDatas之间存在1:1的关系(否则您的代码_contextRegister.EPayVoucherDatas.Where(m => m.EntityId == itm.Id)无效)。因此,首先请确保您已建模this relationship in your EF model

如果是这样,您可以这样写:

_contextRegister.EPayVoucherDatas.Where(m => !m.Entity.IsDeleted);

那已经消除了部分问题。

另一部分是您对另一个数据库_contextFRAMEWORK的使用,该数据库似乎包含相同ID下的一些其他数据。在当前的实现中,您分别要求为每个项目指定特定区域。但是根据表的大小,明智的做法是将整个表拉一次(在for循环之外)并在本地进行查找。另外,如果VoucherStatus也为10,则您具有此if语句,该语句将PaymentStatus设置为10。在所有其他情况下,情况如何?也许您总是可以从VoucherStatus映射PaymentStatus?

很多问题而不是真正的答案,通常是取决于。尽量减少对数据库的调用数量,并检查每个调用返回多少个实体。尽早过滤某些条件,以最大程度地减少服务器返回的数据量,并尝试与服务器建立尽可能少的连接。即使这会导致非常复杂的查询。通常,这对于SQL Server来说不是问题,原因在于它的用途。

答案 1 :(得分:0)

1)检查是否为WHERE条件中使用的每个字段创建了数据库索引,例如:

x.IsDeleted
m.Id 
m.EntityId

您可以使用模型构建器创建索引:

modelBuilder.Entity<Person>()
    .HasIndex(p => p.Name)
    .IsUnique();

请参见https://stackoverflow.com/a/47031294/194717

您还可以使用IndexAttribute创建索引

public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Index]
    public int Rating { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

请参见https://blog.oneunicorn.com/2014/02/15/ef-6-1-creating-indexes-with-indexattribute/

2)您不应该为每个实体记录两次访问数据库。尝试将其写为JOIN(.Include())。