2013-04-04 877 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事务的实际问题 - 看起来像在并发数据库操作期间导致返回无效数据的表中的中间结果;除非我们看到实际的查询和表格模式,否则我不能多说。