2011-05-05 77 views
0

我有一个奇怪的问题,我试图弄清楚它是我的代码还是已经搞乱了数据库。我有一个WebClienteLogin表,它有一个属性Id(主键,自动增量)。当用户在网站上注册时,我插入新记录。LINQ to SQL存储库模式自动增量问题

昨天早上最后注册用户的ID值达到了9000左右,下午开始有趣地跳起来,所以下一个用户有了1200,25000 .....并且它达到了290000.但是,今天它继续正常(增加1)。从统计数据看,当有大量用户同时注册时,就会发生这种情况。

用到的技术:SQL Server 2008 R2中,ASP.NET MVC2,.NET 3.5

我使用Repository模式与LINQ。这是我的一个仓库的实现。

public SQLWebClientLoginRepository(string connectionString) 
{ 
       dataContext = new DataContext(connectionString); 
       tabla = dataContext.GetTable<WebClientLogin>(); 
} 


public bool Save(WebClientLogin user) 
      { 
       bool success = true;    

       try 
       { 
        if (user.Id == 0) 
        { 
         tabla.InsertOnSubmit(user); 
        } 
        else if (tabla.GetOriginalEntityState(user) == null) 
        { 
         tabla.Attach(user); 
         tabla.Context.Refresh(RefreshMode.KeepCurrentValues, user); 
        } 
        tabla.Context.SubmitChanges(); 
       } 
       catch 
       { 
        ...... 
       } 

       return success; 
    } 

此外,用户还附加了其他对象,因此它将INSERT插入到两个表中,并将LINQ包装到事务中。

var user = new WebClientLogin(); 
    // assigning other properties 
    user.WebClient = new WebClient { // setting propeties } 

    webClientLoginRepository.Save(user) 

在日志中我得到异常:

试图删除WebClientLogin和Web客户端之间的 关系 然而,这种关系的一个外键 (WebClient.WebCLientLogin_id)不能设置。为空”异常

我不知道为什么会这样做,任何人都经历过类似的事情

回答

0

启动数据库的状态:?

WebClientLogin 
ID = 900 

WebClient 
ID = 1, WebClientLogin_Id = 900 

在存储器修改之前:

WebClientLogin 
ID = 900 

WebClient 
ID = 1, WebClientLogin_Id = 900, WebClientLogin = that instance with 900 

检查WebClientLogin的Web客户端属性。在的SubmitChanges的时间内存:

WebClientLogin 
ID = 900 

WebClient (original instance) 
ID = 1, WebClientLogin_Id = 900, WebClientLogin = null 

WebClient (new instance!) 
ID = 0, WebClientLogin_Id = 900, WebClientLogin = that instance with 900 

数据库试图进行的改革:

WebClientLogin (no change) 
ID = 900 

WebClient (new row, inserted) 
ID = 2, WebClientLogin_Id = 900 

WebClient (original row, updated) 
ID = 1, WebClientLogin_Id = 900 -> null (error, rollback transaction) 
+0

感谢您的回复。所有似乎都是正确的,WebClientLogin属性正确分配。这是相当困难的情况,因为它只发生在用户“轰炸”注册表时,所以我实际上无法调试它。我将不得不写入记录每个正在注册的用户的属性值。 – 2011-05-05 12:23:11

+0

在这种情况下,我会实际记录一切。您还应该为您的应用程序构建一个压力测试,并针对您的本地调试代码运行该测试,以模拟注册轰炸并重现问题。 – 2011-07-12 18:06:15

0

我稍微修改仓库里面,似乎它固定的问题,但现在我已经得到了另一个。

public bool Save(WebClientLogin login, WebClient client) 
     { 
      var created = false; 

      using (var transaction = new TransactionScope()) 
      { 
       try 
       { 
    // insert WebClientLogin first 
        tablalogin.InsertOnSubmit(login); 
        dataContext.SubmitChanges(); 

    // insert WebClient second 
        client.WebClientLogin_id = login.Id; 
        tablacliente.InsertOnSubmit(client); 

        dataContext.SubmitChanges(); 
        created = true; 
        transaction.Complete(); 
       } 
       catch (Exception ex) 
       { 
        // 
       } 
      } 
      return created; 
     } 

当有大批量我只WebClientLogin插入用户,但没有WebClient的 ,我得到这个异常:其他

Internal .Net Framework Data Provider error 60 
+0

您不应该这样做直接ID管理。查看WebClient的WebClientLogin属性,看看自动生成的属性如何管理ID。应该能够致电SubmitChanges。 – 2011-05-05 14:46:43

+0

我意识到这一点。这就是我之前做的事情,因为SubmitChanges()将整个事件包装到事务中,但是当我这样做时,只有当有大量用户同时注册时,才会得到Id的有趣跳转。否则很好。上面的代码似乎解决了这个问题。但是,有时无法使用TransactionScope对两个表执行INSERT操作。所以我最终只有一个用户被输入到一个表中。这件事我疯了! – 2011-05-05 16:06:19

0

嘛....整个应用程序是给负载奇怪的例外。所以我们访问了我们的主机,我们发现了它的原因。主机配置了3个专用Web服务器和1个数据库服务器。他们为Web服务器配置了负载平衡器和dfs。他们关闭了3台服务器中的2台,并进行了压力测试。从那时起,没有错误/异常或错误的交易。看起来像服务器问题。