none
update security category dataset with a big amount of resources (via PSI) RRS feed

  • Question

  • Hello, 

    Trying to add a big amount of resources  in a security category dataset ( e.g 70000 resources) in bunch of 1000 resources per update, I have encountered the following problem:

    - after updating the security category dataset with 1000 resources per update, at one point, the method SetCategories failed and raised the following error:   System.ServiceModel.FaultException: Unhandled Communication Fault occurred

    //Read the security dataset this.SecurityCategDS = psiHandler.SecurityClient.ReadCategory(this.SecurityCategUID); //in a foreach, multiple rows are added in the security category objects datatable SecurityCategoriesDataSet.SecurityCategoryObjectsRow l_secRow =

      this.SecurityCategDS.SecurityCategoryObjects.NewSecurityCategoryObjectsRow();
                                l_secRow.WSEC_CAT_UID = this.SecurityCategUID;                            
                                l_secRow.WSEC_OBJ_UID =  resourceUID;
                                l_secRow.WSEC_OBJ_TYPE_UID = PSSecurityObjectType.Resource;

    this.SecurityCategDS.SecurityCategoryObjects.AddSecurityCategoryObjectsRow(l_secRow); //update the security category dataset psiHandler.SecurityClient.SetCategories(SecurityCategDS);


    I have tried also to pass to the method SetCategories, only the security category dataset changes but the result was that the changes were saved correctly but the existing resources were automatically removed from the security category.

    Which is the best way to update a security category dataset ( or any other dataset, like Resource Dataset) with a big amount of resources?

    Thanks in advance,

    Cristina


    Wednesday, September 25, 2013 7:35 AM

All replies

  • Cristina,

       I sometimes get that communication fault exception calling the PSI when the dataset being passed is too large.  Remember that datasets by default contain all the rowstates of the data (normal, changed and deleted copies of each row) so one of the tactics to optimise the calls and avoid the exceptions is to call the DataSet.GetChanges() method and pass the result back to the PSI instead.

    In your case you are adding rows in a For loop you need to make sure that the dataset doesn't contain all the rows that are already added in previous calls (otherwise the dataset will just grow and grow) 

    So your approach might be:

    1. Read the dataset from the PSI

    2. Add 1000 rows

    3. Pass the GetChanges() result to the PSI

    4. Call DataSet.AcceptChanges()

    5. loop back to 2 until done

    Cheers,

       James.


    James Boman - http://www.boman.biz Software Consultant for IPMO - http://www.ipmo.com.au


    • Edited by James Boman Wednesday, September 25, 2013 8:16 AM added psuedocode
    Wednesday, September 25, 2013 8:12 AM
  • Hi James,

    Thank you for your answer. I just want to add the fact that I have already implemented  the steps you have described but I have a problem at step no. 3 Pass the GetChanges() result to the PSI.

    psiHandler.SecurityClient.SetCategories((SecurityCategoriesDataSet)this.SecurityCategDS.GetChanges());

    This step will actually save the changes  but the existing rows ( not modified) will be automatically removed from the Security Category , which is quite strange and not the behavior I would expect. 

    Cristina

     

     


    Wednesday, September 25, 2013 9:38 AM
  • Cristina,

        A quick disassemble of the Project Server assembly reveals this code in the SetCategories PSI call:

    	foreach (SecurityCategoriesDataSet.SecurityCategoriesRow securityCategoriesRow in category.SecurityCategories.Rows)
    	{
    		Guid wSEC_CAT_UID = securityCategoriesRow.WSEC_CAT_UID;
    		admin.DeleteCategoryPermissionsAll(wSEC_CAT_UID);
    		admin.DeleteCategoryRelationsAll(wSEC_CAT_UID);
    		admin.DeleteCategoryObjectsAll(wSEC_CAT_UID);
    		admin.DeleteCategoryRulesAll(wSEC_CAT_UID);
    		Guid[] relations = PSDBUtility.ExtractArrayOfSpecificKeysFromDataRows(category.GroupRelations.Select("WSEC_CAT_UID='" + wSEC_CAT_UID.ToString(string.Empty, CultureInfo.InvariantCulture) + "'"), "WSEC_GRP_UID");
    		admin.CreateCategoryGroupRelations(relations, wSEC_CAT_UID);
    		Guid[] relations2 = PSDBUtility.ExtractArrayOfSpecificKeysFromDataRows(category.UserRelations.Select("WSEC_CAT_UID='" + wSEC_CAT_UID.ToString(string.Empty, CultureInfo.InvariantCulture) + "'"), "RES_UID");
    		admin.CreateCategoryUserRelations(relations2, wSEC_CAT_UID);
    	}

    This shows that for each security category passed into the method, one of the first things it does is remove all previous contents of the category. This will be the cause of the behaviour you have noted.  So you may not be able to directly put 70,000 objects into a category via the PSI.

    You might have more luck first putting the 70,000 users into a group (AD or Project Server) and then putting the group into the category.

    Cheers,

       James.


    James Boman - http://www.boman.biz Software Consultant for IPMO - http://www.ipmo.com.au

    Thursday, September 26, 2013 12:15 AM