Or, embed this snippet using GenerateWP WordPress Plugin.

Download

Clone

AX CRUD

 [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {

            // populate proxy pool
            ppt.Start();


            // some set up for global variables
            // Yes, I know this is in this class  twice. But it is needed in the constructor for the materialization test in CRM which calls into this class.  
            context.Company = axTestCompany;
            productClass = GetProductClassReference();
            prodClassNameForTest = productClass.Name;


            //create many products and add to a static array for Read. This avoids a SQL bottleneck.  
            for (int i = 0; i <= sizeOfReadArray - 1; i++)
            {
                arrPreInitializedDpForRead.Add(AX_DP_Create_Preinitialized());
            }

            //create many Products and add to a static array for update. This avoids a SQL bottleneck.  
            for (int i = 0; i <= sizeOfUpdateArray - 1; i++)
            {
                arrPreInitializedDpForUpdate.Add(AX_DP_Create_Preinitialized());
            }


        } // end class initialize






        # region Distinct Product Tests
        

        static CallContext context_S = new CRUD.AX_WS_Services.CallContext();
        static EcoResProductServiceClient client_S = new EcoResProductServiceClient(); // this opens and closes the client. Service channels might be better. 
        


        /// <summary>
        /// This approaches uses the big AX port.
        /// </summary>
        [TestMethod]
        public void AX_DP_Create()
        {
            context = new CRUD.AX_WS_Services.CallContext();
            context.Company = axTestCompany;

            // This gives us access to properties in the LoadTest object. Need this to get the user (thread) ID.
            LoadTestUserContext loadTestUserContext =
                this.TestContext.Properties["$LoadTestUserContext"] as LoadTestUserContext;

            if (TestContext.Properties.Contains("$LoadTestUserContext"))
            {
                int uID = loadTestUserContext.UserId;
            }

            // Set up to make sure we do not create duplicates under high load. 
            Guid DMSStaticGUID = GetDMSStaticGUID();
            string strTheGuid = DMSStaticGUID.ToString().Substring(0, 20);
            Interlocked.Increment(ref sequential);
            //string agentId = testContextInstance.Properties["AgentId"].ToString();
            DateTime curDT = DateTime.Now;
            curDT.ToString("mm dd");
            string nameAndProdNum = "Ch" + curDT + strTheGuid + "_" + sequential.ToString(); //+ agentId + "_"



            // --------------------------------------------            

            CRUD.AX_WS_Services.AxdEntity_Product_EcoResDistinctProduct dp =
                new CRUD.AX_WS_Services.AxdEntity_Product_EcoResDistinctProduct();

            dp.DisplayProductNumber = nameAndProdNum;
            dp.SearchName = nameAndProdNum;
            dp.ProductType = CRUD.AX_WS_Services.AxdEnum_EcoResProductType.Service;


            dp.Translation = new CRUD.AX_WS_Services.AxdEntity_Translation[1];
            dp.Translation[0] = new CRUD.AX_WS_Services.AxdEntity_Translation()
            {
                LanguageId = "en-us",
                Name = "DMS Perf"
            };
            dp.Identifier = new CRUD.AX_WS_Services.AxdEntity_Identifier[1];
            dp.Identifier[0] = new CRUD.AX_WS_Services.AxdEntity_Identifier()
            {
                ProductNumber = strTheGuid,
            };

            AxdEntity_DMSProductClassProduct productClassProduct = new AxdEntity_DMSProductClassProduct();
            productClassProduct.DMSProductClass = prodClassNameForTest; //  productClass.Name;
            // productClassProduct.Product = productMaster.DisplayProductNumber;
            dp.DMSProductClassProduct = new CRUD.AX_WS_Services.AxdEntity_DMSProductClassProduct[1] { productClassProduct };

            AxdEcoResProduct doc = new AxdEcoResProduct();
            doc.Product = new AxdEntity_Product_EcoResProduct[1] { dp };

            testContextInstance.BeginTimer("AX_DP_Create");
            CRUD.AX_WS_Services.EntityKey[] keys = client.create(context, doc);
            testContextInstance.EndTimer("AX_DP_Create");

            client.Close();

        }

                


        /// <summary>
        /// Read only of the RecID
        /// </summary>
        [TestMethod]
        public void AX_DP_Read()
        {
            context = new CRUD.AX_WS_Services.CallContext();
            context.Company = axTestCompany;

            // march sequentially through the pre-created entities for read.         
            if (numberTimesReadExecuted >= sizeOfReadArray - 1)
            {
                numberTimesReadExecuted = 0;
            }
            Object dpSingleObj = arrPreInitializedDpForRead[numberTimesReadExecuted];
            Interlocked.Increment(ref numberTimesReadExecuted);


            CRUD.AX_WS_Services.EntityKey[] myKey = (CRUD.AX_WS_Services.EntityKey[])dpSingleObj;


            TestContext.BeginTimer("AX_DP_Read");
            client.read(context, myKey); // we created keyToRead Statically in classInitailize
            TestContext.EndTimer("AX_DP_Read");

            client.Close();
        }





        /// <summary>
        /// To do: Investigate if it is possible to do the update without the read. I think it is by partial updates?  
        /// </summary>
        [TestMethod]
        public void AX_DP_Update_With_Read()
        {

            context = new CRUD.AX_WS_Services.CallContext();
            //client = new EcoResProductServiceClient(); // this opens and closes the client. Service channels might be better. 
            context.Company = axTestCompany;

            AxdEcoResProduct DPtoRead = new AxdEcoResProduct();

            CRUD.AX_WS_Services.CallContext callcontext = new CRUD.AX_WS_Services.CallContext();
            callcontext.Company = axTestCompany;
            callcontext.Language = "en-us";

            // march sequentially through the pre-created entities for read.         
            if (numberTimesUpdateExecuted >= sizeOfReadArray - 1)
            {
                numberTimesUpdateExecuted = 0;
            }
            Object dpSingleObj = arrPreInitializedDpForRead[numberTimesUpdateExecuted];
            Interlocked.Increment(ref numberTimesUpdateExecuted);

            CRUD.AX_WS_Services.EntityKey[] myKey = (CRUD.AX_WS_Services.EntityKey[])dpSingleObj;

            TestContext.BeginTimer("AX_DP_Update");
            DPtoRead = client.read(context, myKey);
            TestContext.EndTimer("AX_DP_Update");


            // now try to update it ---------------

            AxdEcoResProduct DPtoUpdate = DPtoRead;

            DPtoUpdate.Product[0].SearchName = "LoadTestUpdated";

            TestContext.BeginTimer("AX_DP_Update");
            client.update(context, myKey, DPtoUpdate);
            TestContext.EndTimer("AX_DP_Update");

            client.Close();

        }






        /// <summary>
        /// 
        /// </summary>
        [TestMethod]
        public void AX_DP_Delete()
        {
            context = new CRUD.AX_WS_Services.CallContext();
            //client = new EcoResProductServiceClient(); // this opens and closes the client. Service channels might be better. 
            context.Company = axTestCompany;

            // must create a product in order to delete it.  Only way around this is to create a lot of enties, get their ID's, and 
            // add a data source to this test. 
            CRUD.AX_WS_Services.EntityKey[] keyToDelete = AX_DP_Create_Preinitialized();

            Thread.Sleep(1000);

            TestContext.BeginTimer("AX_DP_Delete");
            client.delete(context, keyToDelete);
            TestContext.EndTimer("AX_DP_Delete");

            client.Close();
        }




        public DataSet AX_DP_Query_Count_0001_DataSet(string displayProdNum)
        {
            DataSet ds = AX_DP_Query_Parameterized(1, true, displayProdNum);
            return ds;
        }

        [TestMethod]
        public void AX_DP_Query_Count_0001()
        {
            AX_DP_Query_Parameterized(1, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_0050()
        {
            AX_DP_Query_Parameterized(50, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_0100()
        {
            AX_DP_Query_Parameterized(100, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_0250()
        {
            AX_DP_Query_Parameterized(250, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_0500()
        {
            AX_DP_Query_Parameterized(500, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_1000()
        {
            AX_DP_Query_Parameterized(1000, true);
        }
        [TestMethod]
        public void AX_DP_Query_Count_5000()
        {
            AX_DP_Query_Parameterized(5000, true);
        }


        /// <summary>
        /// Retrieve X number of  records from AX.
        /// Note that this is not a test method. Execute this method by means of the above test methods. 
        /// Areas for further investigation:
        /// What about "static" queries -- already defined in the AOT
        //  http://msdn.microsoft.com/en-us/library/gg847959.aspx/html
        /// </summary>
        public DataSet AX_DP_Query_Parameterized(int querySize, bool dynFieldList, string displayProdNum = null)
        {
            // Some references  
            // http://community.dynamics.com/ax/b/axpulse/archive/2012/11/11/microsoft-dynamics-ax-2012-aif-query-service.aspx#.UfxoKdjn_Qg
            // more about filters, such as by company.
            //http://axcalated.blogspot.com/2015/06/c-ax-aif-webservice-apply-company.html 

            // other interesting things
            // return flattened data set: https://msdn.microsoft.com/EN-US/library/gg841671.aspx
            // Odata query service: http://blogs.msdn.com/b/aif/archive/2011/08/23/odata-query-service.aspx 
            // better way to formate the query: http://www.sohua.xyz/questions-full/1773870/how-to-format-datetime-comparison-value-in-ax-query-service 

            //  Paging paging = null;

            //  Paging paging =  new PositionBasedPaging { StartingPosition = 1, NumberOfRecordsToFetch = 50 }; // only works if an order by is present

            Paging paging = new ValueBasedPaging() { RecordLimit = querySize };

            QueryServiceClient client = new QueryServiceClient();

            // if these are blank, user executing VS will be used. 
            client.ClientCredentials.Windows.ClientCredential.UserName = AX_Proxy_Initialize.userName;
            client.ClientCredentials.Windows.ClientCredential.Password = AX_Proxy_Initialize.userPassword;
            client.ClientCredentials.Windows.ClientCredential.Domain = AX_Proxy_Initialize.userDomain;


            // Meta data. This can be captured from the eventlog of CRM. 
            QueryMetadata queryMetaData = new QueryMetadata();

            // Set the meta data properties of the query.
            queryMetaData.QueryType = QueryType.Join;
            queryMetaData.AllowCheck = true;
            queryMetaData.JoinPolymorphicTables = true;
            queryMetaData.EnableOnlyModified = false;
            queryMetaData.Literals = Literals.Default;
            queryMetaData.QueryType = QueryType.Join;
            queryMetaData.ReturnFlatDataSet = false;
            queryMetaData.ReturnOnlyVisible = false;
            queryMetaData.Searchable = false;

            // Datasource  node. 
            queryMetaData.DataSources = new QueryDataSourceMetadata[1];
            QueryDataSourceMetadata dataSource;

            // Set the properties of the data source (AX table).
            dataSource = new QueryDataSourceMetadata();

            dataSource.Name = "Ecoresproduct"; // This is the name of a field in the table. However it is best if it is this is a primary key, or else zero records will be returned. 
            dataSource.Table = "Ecoresproduct"; // name of the table in AX
            dataSource.Enabled = true;
            dataSource.DynamicFieldList = dynFieldList; //dynFieldList; // Setting DynamicFieldList property to true returns all fields. However if you set it to false without specifiying fields it will timeout AX. 


            //define the current company to search by within AX
            //dataSource.Company = "NML";

            queryMetaData.AllowCrossCompany = true;

            dataSource.TableId = 0;
            dataSource.Enabled = true;
            dataSource.ConcurrencyModel = ConcurrencyModel.Auto;
            dataSource.FetchMode = FetchMode.OneToOne;
            dataSource.JoinMode = JoinMode.InnerJoin;
            dataSource.OrderMode = OrderMode.OrderBy;
            dataSource.ExpansionType = ExpansionType.Original;
            dataSource.FirstFast = false;
            dataSource.FirstOnly = false;
            dataSource.HasRelations = false;
            dataSource.SelectWithRepeatableRead = false;
            dataSource.UnionType = UnionType.None;
            dataSource.Update = false;


            //Add the data source to the query.
            queryMetaData.DataSources[0] = dataSource;

            //// this is how you do a where clause. Should not be used be used for testing. 
            //// notice the if statement. Will not execute unless a recID is passed in. 
            //if (displayProdNum != null)
            //{
            //    var range = new QueryDataRangeMetadata
            //    {
            //        TableName = "Ecoresproduct",
            //        FieldName = "RecId",
            //        Value = displayProdNum,
            //        Enabled = true
            //    };

            //    dataSource.Ranges = new QueryRangeMetadata[] { range };
            //}



            // execute the query. 
            string timerName = ("AX_DP_Query_" + querySize.ToString("D4") + "_dynFld_" + dynFieldList);

            testContextInstance.BeginTimer(timerName);
            DataSet ds = client.ExecuteQuery(queryMetaData, ref paging);

            testContextInstance.EndTimer(timerName);


            client.Close();

            //// verification steps
            //int thecount = ds.Tables[0].Rows.Count;

            //foreach (DataRow row in ds.Tables[0].Rows)
            //{
            //    int theCount = ds.Tables[0].Rows.Count;
            //    string prodNumStr = ds.Tables[0].Rows[0]["DisplayProductNumber"].ToString();
            //}
            ////UnpackResponses.PrintAXRows(ds); // debugging only do not use under load            

            ////  Verification  #2
            //int numOfTables = ds.Tables.Count;
            //int numOfRowsFromAllTables = 0;
            //int numOfColumnsFromAllTables = 0;
            //for (int i = 0; i < ds.Tables.Count; i++)
            //{
            //    numOfRowsFromAllTables += ds.Tables[i].Rows.Count;
            //    numOfColumnsFromAllTables += ds.Tables[i].Columns.Count;
            //}


            return ds;
        }






      


        // End of CRUD methods -------------------------------------------------------------------------



      
      




        #endregion Distinct Product Tests




        // helper methods  ---------------------------




        /// <summary>
        /// This create is for use in the update, query and read methods. 
        /// </summary>
        /// <returns></returns>
        public static CRUD.AX_WS_Services.EntityKey[] AX_DP_Create_Preinitialized() //string prodClassNameForTest = null
        {
            // AX_Proxy_Initialize aXProxy = new AX_Proxy_Initialize();


            Guid DMSStaticGUID = GetDMSStaticGUID();
            string strTheGuid = DMSStaticGUID.ToString().Substring(0, 20);

            //DMSPerfTest.CRUD.AX_WS_Services.CallContext context = new DMSPerfTest.CRUD.AX_WS_Services.CallContext();
            //EcoResProductServiceClient //client = new EcoResProductServiceClient();
            CRUD.AX_WS_Services.AxdEntity_Product_EcoResDistinctProduct dp = new CRUD.AX_WS_Services.AxdEntity_Product_EcoResDistinctProduct();


            dp.DisplayProductNumber = strTheGuid;
            dp.SearchName = strTheGuid;
            dp.ProductType = CRUD.AX_WS_Services.AxdEnum_EcoResProductType.Service;

            dp.Translation = new CRUD.AX_WS_Services.AxdEntity_Translation[1];
            dp.Translation[0] = new CRUD.AX_WS_Services.AxdEntity_Translation()
            {
                LanguageId = "en-us",
                Name = "Nissan Test 2"
            };
            dp.Identifier = new CRUD.AX_WS_Services.AxdEntity_Identifier[1];
            dp.Identifier[0] = new CRUD.AX_WS_Services.AxdEntity_Identifier()
            {
                ProductNumber = strTheGuid,
            };


            AxdEntity_DMSProductClassProduct productClassProduct = new AxdEntity_DMSProductClassProduct();
            productClassProduct.DMSProductClass = productClass.Name; //  ; GetProductClassReference().Name; // could do this name but introduces extra call every request.  
            //productClassProduct.Product = productMaster.DisplayProductNumber;
            dp.DMSProductClassProduct = new CRUD.AX_WS_Services.AxdEntity_DMSProductClassProduct[1] { productClassProduct };

            AxdEcoResProduct doc = new AxdEcoResProduct();
            doc.Product = new AxdEntity_Product_EcoResProduct[1] { dp };

            CRUD.AX_WS_Services.EntityKey[] oneCreatedDPkey = client.create(context, doc);

            return oneCreatedDPkey;

        }



        [TestMethod]
        public void Debug_AX_DP_Create_Many_Products_And_Query_Tester()
        {
            AX_DP_Create_Many_Products_And_Query(50);
        }
        /// <summary>
        /// This create is for use in the update, query and read methods. 
        /// </summary>
        /// <returns></returns>
        public List<string> AX_DP_Create_Many_Products_And_Query(int numToCreate) //string prodClassNameForTest = null
        {

            List<CRUD.AX_WS_Services.EntityKey[]> listOfKeys = new List<CRUD.AX_WS_Services.EntityKey[]>();

            TestContext.BeginTimer("Create50");

            for (int i = 0; i < numToCreate; i++)
            {
                CRUD.AX_WS_Services.EntityKey[] key = AX_DP_Create_Preinitialized();
                listOfKeys.Add(key);
            }

            TestContext.EndTimer("Create50");

            // we now must prepare to query recids from AX because the create method does not return display name. 
            // we need display name (which is unique) to query from the CRM side 

            // set up to call query
            AX_Distinct_Product axdp = new AX_Distinct_Product();

            List<string> displayProdNums = new List<string>();

            TestContext.BeginTimer("Query50");

            foreach (CRUD.AX_WS_Services.EntityKey[] key in listOfKeys)
            {
                string recID = key[0].KeyData[0].Value.ToString();

                DataSet ds = AX_DP_Query_Count_0001_DataSet(recID);


                // there is a better way to do this here with retrieve multiple. Have to think 
                //for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                //{
                string prodNumStr = ds.Tables[0].Rows[0]["DisplayProductNumber"].ToString();


                // works but the above is more clear
                string displayName = "";
                var theData = ds.Tables[0].Rows[0].ItemArray;

                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    displayName = theData[1].ToString();
                    // int theCount = ds.Tables[0].Rows[0].Table.Columns[0].;
                }

                displayProdNums.Add(displayName);



                //}

            }

            TestContext.EndTimer("Query50");


            return displayProdNums;

        }




        /// <summary>
        /// Helper Method to read product class (once) and use it repeatedly in tests. 
        /// </summary>
        /// <returns></returns>
        public static AxdEntity_DMSProductClass GetProductClassReference()
        {
            CRUD.AX_WS_Services.CallContext context = new CRUD.AX_WS_Services.CallContext();

            ProductClassServiceClient productClassService = new ProductClassServiceClient();

            context.Company = axTestCompany;
            productClassService.ClientCredentials.Windows.ClientCredential.Password = AX_Proxy_Initialize.userPassword;
            productClassService.ClientCredentials.Windows.ClientCredential.UserName = AX_Proxy_Initialize.userName;
            productClassService.ClientCredentials.Windows.ClientCredential.Domain = AX_Proxy_Initialize.userDomain;


            CRUD.AX_WS_Services.QueryCriteria criteria = new CRUD.AX_WS_Services.QueryCriteria();
            criteria.CriteriaElement = new CRUD.AX_WS_Services.CriteriaElement[1];
            criteria.CriteriaElement[0] = new CRUD.AX_WS_Services.CriteriaElement();
            criteria.CriteriaElement[0].DataSourceName = "DMSProductClass";
            criteria.CriteriaElement[0].FieldName = "Name";
            criteria.CriteriaElement[0].Operator = CRUD.AX_WS_Services.Operator.Equal;
            criteria.CriteriaElement[0].Value1 = "Kit"; //"New vehicle - color only";

            CRUD.AX_WS_Services.EntityKey[] keys = productClassService.findKeys(context, criteria);

            AxdEntity_DMSProductClass productClass = new AxdEntity_DMSProductClass();
            AxdProductClass doc = productClassService.read(context, keys);

            return doc.DMSProductClass[0];

        }




        static Guid DMSStaticGUID;
        public static Guid GetDMSStaticGUID()
        {
            DMSStaticGUID = Guid.NewGuid();
            return DMSStaticGUID;
        }


        

    } // end class