我有一个在涉及第三方API调用的记录上运行的方法,因此它不受CPU限制并在后台运行缓慢,但由于数据集太大而导致内存问题。我不能一次加载整个列表(它会导致异常)所以我正在批量分页。这是有效的,但每个批次都添加到ram用法,因为我假设它正被上下文跟踪。
我认为要解决这个问题,我可以在完成处理后分离每批。我试过这个:
{Binding Source={StaticResource lower1_1}, Converter={ ..... –
批处理完成后会导致此异常:
实体类型List`1不是当前模型的一部分 上下文
我想这是因为我将它枚举到一个列表中,它实际上是跟踪列表中的记录。
分离记录和嵌套记录以使ram不填满的正确方法是什么?我应该以不同的方式接近这个吗?
编辑:
我还尝试分离每个公司的记录,因为我循环它但是ram仍然上升
using (var db = new PlaceDBContext())
{
int count = 0;
while(count < total)
{
var toCheck = db.Companies
.Include(x => x.CompaniesHouseRecords)
.Where(x => x.CheckedCompaniesHouse == false)
.OrderBy(x => x.ID)
.Skip(count)
.Take(1000)
.ToList();
foreach (var company in toCheck)
{
// do all the stuff that needs to be done
// removed for brevity but it makes API calls
// and creates/updates records
company.CheckedCompaniesHouse = true;
db.SaveChanges();
count++;
}
// attemmpted to detach to free up ram but doesn't work
db.Entry(toCheck).State = EntityState.Detached;
}
}
答案 0 :(得分:1)
上下文意味着短暂而且便宜,如果你担心它会占用记忆而这是一个问题,因为你的时间很长,也许你可以试试这个:
int count = 0;
while(count < total)
{
using (var db = new PlaceDBContext()) // create a new context each time
{
var toCheck = db.Companies
.Include(x => x.CompaniesHouseRecords)
.Where(x => x.CheckedCompaniesHouse == false)
.OrderBy(x => x.ID)
.Skip(count)
.Take(1000)
.ToList();
foreach (var company in toCheck)
{
// do all the stuff that needs to be done
// removed for brevity but it makes API calls
// and creates/updates records
company.CheckedCompaniesHouse = true;
db.SaveChanges();
count++;
}
}
}
答案 1 :(得分:0)
当您执行加载时,请var toCheck = ...
使用.AsNoTracking()
在foreach
循环中,保存每行的ID,然后使用第二个db上下文来加载这些公司,除非没有包含大量额外链接对象的Include()。
然后对循环中的那些进行更新,但在循环之后只发出一个db.SaveChanges(),否则你将为每一行进行db往返,即1000一段时间
using (var db = new PlaceDBContext())
{
int count = 0;
while(count < total)
{
var toCheck = db.Companies
.AsNoTracking()
.Include(x => x.CompaniesHouseRecords)
.Where(x => x.CheckedCompaniesHouse == false)
.OrderBy(x => x.ID)
.Skip(count)
.Take(1000)
.ToList();
foreach (var company in toCheck)
{
int tempID = company.ID // Use whatever field is the id
// do all the stuff that needs to be done
// removed for brevity but it makes API calls
// and creates/updates records
var companyUpdate = db2.Companies.Where(c => c.ID == tempid).FirstOrDefault();
companyUpdate.CheckedCompaniesHouse = true;
count++;
}
db2.SaveChanges();
}
}