当发生SQLException时,如何使用语句重新连接实体数据集?

时间:2016-02-05 14:05:34

标签: c# entity-framework

情况是我有一个长时间运行的方法,它循环遍历数千行并进行处理和更新。这个循环嵌套在我的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的记录和链接记录的数据库以获得负载测试的想法,所以我不是为所有可能性编程,我只是希望能够处理断开连接并重新连接如果这是可能的。

谢谢,

2 个答案:

答案 0 :(得分:1)

我将评论移至答案。这是我的建议,不知道你在do lots of stuff做了什么。

通常使用EF,您希望在使用块内花费尽可能少的时间。从this EF tutorial(以及其他)转述:

  
      
  1. 从DB获取现有对象。
  2.   
  3. 将对象名称更改为上下文范围(断开连接模式)
  4.   
  5. 将修改后的实体传递给方法以获取其DBEntityEntry对象,然后将其状态标记为已修改
  6.   
  7. 调用SaveChanges()方法将对象信息更新到数据库中。
  8.   

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();
    }
}