嗨,我使用的是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分钟,在哪里可以使该查询更好,还是应该使用存储过程而不是框架?
答案 0 :(得分:1)
据我所知,Entities
和EPayVoucherDatas
之间存在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()
)。