Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics AX forum
Suggested answer

Updating records using odata

Posted on by 690

Hi

I need to update odata records that I looping through using a linq query, but an exception is being thrown when I call SaveChanges. Here is a basic outline of the code - hopefully this will be enough to demonstrate what I am doing wrong

var query = from BatchOrder 
	in context.BatchOrders
	where BatchOrder.Sent == NoYes.No
	select BatchOrder;

foreach (var batchOrder in query)
{
	// do some processing on the batchOrder record here

	// update AX record
	batchOrder.Sent = NoYes.Yes;
}

// send changes to the AX records back to AX
context.SaveChanges(SaveChangesOptions.PostOnlySetProperties);

The exception message is "'SaveChangesOptions.OnlyPostExplicitProperties' must be used with 'DataServiceCollection'", however I cannot find any examples of how to use a DataServiceCollection when looping through records.

Can someone point me in the right direction please?

Thanks,
Joe

  • RE: Updating records using odata

    Hi,

    While trying to Update a Custom Entity. Throwing following Error:

    An error occurred while processing this request.

    "Message":"No HTTP resource was found that matches the request URI 'http://***.dynamics.com/data/CustomerSchemePaymentCRMs(SchemeEntryNo%3D'SCHC008202003208'%2CTransactionId%3D'20200401111212800110168844721905105'%2CLineNum%3D1)'. No route data was found for this request."

    Any Idea How to resolve this issue?

  • Suggested answer
    Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    Hello Everyone , 

    I was able to solve the issue with the help of Martin's blog :- https://community.dynamics.com/365/financeandoperations/b/goshoom/archive/2017/04/20/odata-service-across-companies

    So the final code is as follows:- 

    namespace ODataConsoleApplication
    {
        class Program
        {
            public static string ODataEntityPath = ClientConfiguration.Default.UriString + "data";
            static void Main(string[] args)
            {
                
                Uri oDataUri = new Uri(ODataEntityPath, UriKind.Absolute);
                var context = new Resources(oDataUri);
                context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)
                {
                    var authenticationHeader = OAuthHelper.GetAuthenticationHeader(useWebAppAuthentication: true);
                    e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
                });
                //Below code block from above URL
                context.BuildingRequest += (sender, e) =>
                {
                    var uriBuilder = new UriBuilder(e.RequestUri);
                    // Requires a reference to System.Web
                    var paramValues = HttpUtility.ParseQueryString(uriBuilder.Query);
                    //In order to update we need to add this block of code.
                    paramValues.Add("cross-company", "true");
                    uriBuilder.Query = paramValues.ToString();
                    e.RequestUri = uriBuilder.Uri;
                };
                Console.WriteLine("Executing in Example - Updating Customer 981848");
                SimpleCRUDExamples.UpdateCRUD_Customer(context);
            }
    } }

    Customer Update Code

    namespace ODataConsoleApplication
    {
        class SimpleCRUDExamples
        {
            public static void UpdateCRUD_Customer(Resources d365)
            {
                try
                {
                    var query = from  Customer
                    in d365.Customers
                    where Customer.CustomerAccount == "004073"
                    &&  Customer.DataAreaId =="USRT"
                    select Customer;
                    DataServiceCollection<Customer> customersToUpdate = new DataServiceCollection<Customer>(query);
    
                    foreach (var customer in customersToUpdate)
                    {
                        customer.PaymentMethod = "Check";
                        d365.UpdateObject(customer);
                    }
                    d365.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset);
                }
                catch (DataServiceRequestException e)
                {
                    // Console.WriteLine(string.Format("Customer {0} - Save Failed !"));
                    Console.WriteLine(e.Message);
                }            
    
            }
    
        }
    }
    


     



  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    Hi Justin

    I am also trying to update the customer with the help of your query. But is is throwing this error.

    try
               {
                   var query = from Customer
                               in d365.Customers
                               where Customer.CustomerAccount == "004073"
                               where Customer.DataAreaId =="usrt"
                               select Customer;
                   DataServiceCollection<Customer> customersToDelete = new DataServiceCollection<Customer>(query);
                   foreach (var customer in customersToDelete)
                   {
                       d365.UpdateObject(customer);
                   }
                   d365.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset);
               }
               catch (DataServiceRequestException e)
               {
                   // Console.WriteLine(string.Format("Customer {0} - Save Failed !"));
                   Console.WriteLine(e.Message);
               }        
    Microsoft.OData.Client.DataServiceQueryException
     HResult=0x80131509
     Message=An error occurred while processing this request.
     Source=Microsoft.OData.Client
     StackTrace:
      at Microsoft.OData.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
      at Microsoft.OData.Client.DataServiceQuery`1.Execute()
      at Microsoft.OData.Client.DataServiceCollection`1.InternalLoadCollection(IEnumerable`1 items)
      at Microsoft.OData.Client.DataServiceCollection`1.StartTracking(DataServiceContext context, IEnumerable`1 items, String entitySet, Func`2 entityChanged, Func`2 collectionChanged)
      at Microsoft.OData.Client.DataServiceCollection`1..ctor(DataServiceContext context, IEnumerable`1 items, TrackingMode trackingMode, String entitySetName, Func`2 entityChangedCallback, Func`2 collectionChangedCallback)
      at Microsoft.OData.Client.DataServiceCollection`1..ctor(IEnumerable`1 items)
      at ODataConsoleApplication.SimpleCRUDExamples.UpdateCRUD_Customer(Resources d365) Inner Exception 1:
    DataServiceClientException: NotFound

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    Thanks Justin for your response,

    find solution, By using below code  we can delete multiple records at a time.

    StringBuilder sb = new StringBuilder();
                int count = 1;

                foreach (Customer customer in customers)
                {                
                    sb.Append(String.Format("customerId eq '{0}'", customer.cutomerId));
                    sb.Append(" and ");
                    sb.Append(String.Format("dataAreaId eq '{0}'", company));
                    if (count < customers.Count)
                        sb.Append(" or ");
                    count++;
                }
                var dynamicfilter = sb.ToString();
         
                var customerBatch = from entity in dataServiceContext.Customers.AddQueryOption("$filter", dynamicfilter)
                                 select entity;

               DataServiceCollection<Customer> customersToDelete = new DataServiceCollection<Customer>(customerBatch);
        
                foreach (var customer in customersToDelete)
                {
                    dataServiceContext.DeleteObject(customer);
                }
                dataServiceContext.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset);

  • swetha desai Profile Picture
    swetha desai 152 on at
    RE: Updating records using odata

    Thanks Justin. This worked well for me :)

    I was using the crosscompany=true using the AddQueryFilter option on DataServiceQuery. But changed that to what you suggested, and got rid of the error.

    Regards,

    Swetha K Desai

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    I know this is a few weeks old, but I'll do my best to respond...

    I am not sure how to delete as you are asking, but I assume you need to be deleting the record from "customersToDelete".  Calling dataServiceContext.DeleteObject(customer ); by itself isn't enough.  Make sure the "customersToDelete" is a DataServiceCollection object:

    (This is just an example, I have no idea what you are using for your query to get the customers)

    var query = from Customer

      in context.Customers

      where Customer.FieldToDelete == true

      select Customer;

    DataServiceCollection<Customer> customersToDelete = new DataServiceCollection<Customer>(query);

    The problem is, looping over a DataServiceCollection and trying to delete an element in that same collection may prove problematic.  I haven't tried it, but I could see how it may be a problem.

    Let me know if you were able to figure it out or not.

    Thanks,

    Justin

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    I have not seen that specific error before, but one thing we have found that solved a few of our issues is that you must set the initial resources to pull from all the companies.  That isn't always the case, but try setting the "cross-company" parameter to "true", as shown in bold in the code below when you are first getting the resources.

    private Resources MakeResources()

            {

                string entityRootPath = appContract.resource + "/data";

                Uri oDataUri = new Uri(entityRootPath, UriKind.Absolute);

                var resources = new Resources(oDataUri);

     

                resources.SendingRequest2 += new

                EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)

                {

                    e.RequestMessage.SetHeader(OAuthHeader,

                    authenticationHeader);

                });

     

                resources.BuildingRequest += (sender, e) =>

                {

                    var uriBuilder = new UriBuilder(e.RequestUri);

                    var paramValues = HttpUtility.ParseQueryString(uriBuilder.Query);

                    paramValues.Add("cross-company", "true");

                    uriBuilder.Query = paramValues.ToString();

                    e.RequestUri = uriBuilder.Uri;

                };

     

                return resources;

            }

  • swetha desai Profile Picture
    swetha desai 152 on at
    RE: Updating records using odata

    Hello Justin,

    Using the same code, i am unable to update salesorderheader entity. It gives me the error, no resources found while selecting for update.

    Any suggestions?

    Thanks,

    Swetha K Desai

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Updating records using odata

    Hi justin,

    Do you have any idea to delete multiple records at a time(single call to delete), like above update example.

    foreach (string customerId in customersToDelete)

               {

                   Customer customer = dataServiceContext.CreateTrackedEntityInstance<Customer >();

                   customer = RetreiveCustomer (customerId );              

                   dataServiceContext.DeleteObject(customer );

               }

               dataServiceContext.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset);

    Could you please help me if you have any idea about this.

    Thank you

  • Suggested answer
    Sukrut Parab Profile Picture
    Sukrut Parab 71,637 Moderator on at
    RE: Updating records using odata
    Look at the below code for how to use 'DataServiceCollection'

    https://stoneridgesoftware.com/working-with-the-odata-endpoint-in-dynamics-365-for-operations/


    DataServiceCollection<Customer> customersCollection = new DataServiceCollection<Customer>(context); customersCollection.Add(myCustomer); myCustomer.CustomerAccount = "US-X11111"; myCustomer.Name = "ABC Trees 111"; myCustomer.CustomerGroupId = "10"; myCustomer.SalesCurrencyCode = "USD"; myCustomer.CreditRating = "Excellent"; myCustomer.AddressCountryRegionId = "USA"; #region Create multiple customers Customer myCustomer2 = new Customer(); customersCollection.Add(myCustomer2); myCustomer2.CustomerAccount = "US-X22222"; myCustomer2.Name = "ABC Rains vb"; myCustomer2.CustomerGroupId = "10"; //myCustomer2.SalesCurrencyCode = "USD"; myCustomer2.CreditRating = "Excellent"; myCustomer2.AddressCountryRegionId = "USA"; #endregion


     

Helpful resources

Quick Links

Can you answer this forum question?

You could make someone's day!

Community Newsletter - May 2024

Kudos to our community stars!

Community Spotlight of the Month

Kudos to Mohamed Amine Mahmoudi!

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 283,663 Super User

#2
Martin Dráb Profile Picture

Martin Dráb 224,750 Super User

#3
nmaenpaa Profile Picture

nmaenpaa 101,146

Featured topics

Product updates

Dynamics 365 release plans