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



嗨,我正在使用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 多分钟,我在哪里才能使此查询更好,或者我应该使用存储过程而不是框架?

据我所知,EntitiesEPayVoucherDatas之间存在 1:1 的关系(否则您的代码_contextRegister.EPayVoucherDatas.Where(m => m.EntityId == itm.Id)将无法正常工作(。因此,首先请确保已在 EF 模型中对此关系进行建模。

如果这是真的,你可以写这样的东西:

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

这已经消除了您的部分问题。

另一部分是您使用另一个数据库_contextFRAMEWORK,它似乎包含相同 ID 下的一些其他数据。在当前的实现中,您分别要求每个项目的特定区域。但是,根据此表的大小,将整个表拉取一次(在 for 循环之外(并在本地进行查找可能更明智。此外,您还有此 if 语句,如果凭证状态也是 10,则将付款状态设置为 10。在所有其他情况下是什么?也许您可以随时从凭证状态映射付款状态?

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

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()(。

最新更新