2013-04-04 910 views
1

我有收集共享信息和結果寫入數據庫, 的方法我用Parallel.Foreach這就增加了性能,特別是如果掃描100 TBParallel.ForEach遞歸方法

如果我在本地運行這段代碼數據庫,我覺得沒有問題,但沙盒數據庫上我得到噸例外/ innerExceptions

代碼:

private static INodeCollection NodesLookUp(string path, int maximumLevel) 
     { 

      var shareCollectionNode = new ShareCollection(path); 
      shareCollectionNode.GetNodeProperties(); 
      shareCollectionNode.GetPermissionEntires(); 
      WriteNodeToDatabase(shareCollectionNode); // write collected infomation to database 
      if (maximumLevel <= 0 && _maximumSubLevels != -1) 
      { 
       return shareCollectionNode; 
      } 

      Parallel.ForEach(Directory.GetDirectories(shareCollectionNode.FullPath), directory => 
      { 
       try 
      { 
        lock (shareCollectionNode) 
        { 
         shareCollectionNode.AddNode(NodesLookUp(directory, maximumLevel - 1)); 
        } 

       } 
       catch (UnauthorizedAccessException unauthorizedAccessException) 
       { 
        lock (_shareIssues) 
        { 
         _shareIssues.Add(new ShareIssue(TraceStatu.UnauthorizedAccess, directory, 
        unauthorizedAccessException.Message, dfsId, currentLevel)); 
        } 

       } 

      }); 

      return shareCollectionNode; 
     } 

寫入到數據庫:

private static void WriteNodeToDatabase(ShareCollection shareCollection) 
    { 
     var nodeId = Persistence.UpsertShare(shareCollection); 
     var sharePermissions = new List<IPermissionRight>(); 
     foreach (var permissionEntry in shareCollection.PermissionEntries) 
     { 
      permissionEntry.NodeId = nodeId; 
      var permissionEntryId = Persistence.InsertPermissionEntry(permissionEntry); 
      permissionEntry.SetPermissions(permissionEntryId); 
      sharePermissions.AddRange(permissionEntry.Permissions); 
     } 
     Persistence.InsertPermissions(sharePermissions); 
    } 

例外:

System.Data.SqlClient.SqlException (0x80131904): Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) 
    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 

如果我刪除Parallel.Foreach和使用正常的循環,然後我有一個應用程序需要年齡運行身邊沒有問題。

+4

請按照刪除或至少減少橫向滾動的方式來格式化代碼。 – 2013-04-04 15:56:02

+2

'Parallel.ForEach'以'lock'結尾? – ken2k 2013-04-04 15:57:27

+0

這就是我不喜歡的口袋妖怪異常處理:我們不知道這個異常拋出的位置。任何想法哪個查詢導致此錯誤? – IdeaHat 2013-04-04 16:08:24

回答

1

首先嚐試用這種

var node = NodesLookUp(directory, maximumLevel - 1); 
lock (shareCollectionNode) 
{ 
    shareCollectionNode.AddNode(node); 
} 

與同爲第二鎖更換這

lock (shareCollectionNode) 
{ 
    shareCollectionNode.AddNode(NodesLookUp(directory, maximumLevel - 1)); 
} 

雖然這是一種更好的方式來通過並行來實現您想要的功能,但也可能有助於在本地重現相同的錯誤,因爲它會增加數據庫活動。

我認爲依賴於DataBase事務的實際問題 - 看起來像在併發數據庫操作期間導致返回無效數據的表中的中間結果;除非我們看到實際的查詢和表格模式,否則我不能多說。