情况是我有一个长时间运行的方法,它循环遍历数千行并进行处理和更新。这个循环嵌套在我的using语句中。
问题是当我上午上班时,我发现我的连接在晚上8点因SQLException而失败,我失去了12小时的处理时间。如何以编程方式重新连接并继续处理我的循环?
我的想法是这样的:
using (var _data = new My.EF.MyEntities())
{
for (int i = 1; i < 17348; i++)
{
try
{
//Do lots of stuff
}
catch (SqlException ex)
{
WriteLogFile("Error at id" + i.ToString(), ex);
i--;
if (_data.Database.Connection.State != System.Data.ConnectionState.Open)
{
_data. // What? nothing looks useful here to reconnect
}
}
}
}
这只是开发代码,不适用于任何生产或用户环境。我正在做的就是播放一个包含10'000的记录和链接记录的数据库以获得负载测试的想法,所以我不是为所有可能性编程,我只是希望能够处理断开连接并重新连接如果这是可能的。
谢谢,
答案 0 :(得分:1)
我将评论移至答案。这是我的建议,不知道你在do lots of stuff
做了什么。
通常使用EF,您希望在使用块内花费尽可能少的时间。从this EF tutorial(以及其他)转述:
- 从DB获取现有对象。
- 将对象名称更改为上下文范围(断开连接模式)
- 将修改后的实体传递给方法以获取其DBEntityEntry对象,然后将其状态标记为已修改
- 调用SaveChanges()方法将对象信息更新到数据库中。
醇>
在using
上下文中花费12个多小时听起来需要重新设计。话虽如此,如果你修改现有的实体(从内存中,可能需要一些语法调整),这里有一个建议:
IEnumerable<EntityTypeYouveDefined> listOfEntities;
using (var _data = new My.EF.MyEntities())
{
listOfEntities = _data.YourTableName.Where(e => e.SomeConditionOrPropertyOrWhatever);
//Or some other search predicate to pull what you want to change.
}
foreach(var entity in listOfEntities)
{
entity.SomeProperty = "what you want to change";
}
using (var _data = new My.EF.MyEntities())
{
foreach(var entity in listOfEntities)
{
_data.Entry(entity).State = EntityState.Modified;
}
_data.SaveChanges();
}
如果您正在创建新实体,请参阅以下代码:
var listOfEntities = new List<EntityTypeYouveDefined>();
for (int i = 0; i < 17348; i++)
{
var newEntity = new EntityTypeYouveDefined();
//Build the newEntity relationships here
listOfEntities.Add(newEntity);
}
using (var _data = new My.EF.MyEntities())
{
foreach (var entity in listOfEntities)
{
_data.Attach(newEntity)
//You may have to set the entity state to modified here. Can't remember, I'm doing this from memory
}
_data.SaveChanges();
}
这将最大限度地减少您在该循环中花费的时间并使其更清洁。此外,如果您需要重复执行此操作,请使用using
块的外循环。 using
块为您处理与数据库的连接。您不需要在app/web.config
文件中的连接字符串之外自行管理。
答案 1 :(得分:0)
据我所知,解决此问题的一种方法可能是处置旧的_data
对象,然后再次初始化它。
var _data = new My.EF.MyEntities();
try
{
for (int i = 1; i < 17348; i++)
{
try
{
//Do lots of stuff
}
catch (SqlException ex)
{
WriteLogFile("Error at id" + i.ToString(), ex);
i--;
if (_data.Database.Connection.State != System.Data.ConnectionState.Open)
{
((IDisposable)_data).Dispose();
_data = new My.EF.MyEntities()
}
}
}
}
finally
{
if (_data != null)
{
((IDisposable)_data).Dispose();
}
}