locked
DataServiceContext SaveChanges problem RRS feed

  • Question

  • Hi,

    I have .NET 3.5 SP1 beta installed and have problem with DataServiceContext.SaveChanged method which did not appear with ADO .Net 3.5 Extensions. Here is my code:

     

                Testcontext = new Test(new Uri("http://localhost/Test.svc");

     

     Parent model = new Parent();

               

                parent.Id = Guid.NewGuid().ToString();

                parent.Name = "Parent";

                context.AddObject("Parent", parent);

     

                Child1 role = new Child1();

                role.Id = Guid.NewGuid().ToString();

                role.Name = " Child1";

                context.AddObject("Child1", role);

               

                Child2 module = new Child2();

                child2.Id = Guid.NewGuid().ToString();

                child2.Name = " Child2";

                context.AddObject("Child2", child2);

     

                ChildRelation relation = new ChildRelation();

                relation.Id = Guid.NewGuid().ToString();

                relation.Name = "relation";

                context.AddObject("ChildRelation", relation);

     

                parent.Child1.Add(role);

                context.AddLink(parent, "Child1", role);

     

                parent.Child2.Add(child2);

                context.AddLink(parent, "Child2", child2);

     

                role.ChildRelation.Add(relation);

                context.AddLink(role, "ChildRelation", relation);

     

                relation.Child2 = child2;

                context.AddLink(relation, "Child2", child2);

     

                DataServiceResponse response = context.SaveChanges(SaveChangesOptions.Batch);

    Execution of this code returns an exception:  

    System.Net.WebException was unhandled

      Message="Internal Server Error\r\n"

      Source="System.Data.Services.Client"

      StackTrace:

           at System.Data.Services.Client.DataServiceContext.HandleResponse(HttpStatusCode statusCode, Func`1 getResponseStream, Boolean throwOnFailure)

           at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.HandleBatchResponse(BatchStream batch)

           at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.HandleBatchResponse(HttpWebResponse response)

           at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.BatchRequest()

           at System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOptions options)

           at ConsoleApplication3.Program.Main(String[] args) in C:\Users\bojan.PEXIMBG\Documents\Visual Studio 2008\Projects\ConsoleApplication3\ConsoleApplication3\Program.cs:line 51

           at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

           at System.Threading.ThreadHelper.ThreadStart()

    When I change code and call  SaveChanges without parameters and parse DataServiceResponse, some of requests are saved successfully and some of them (relation object and its links)  have timeout exired erros.

    Can anyone help me?

    Saturday, June 7, 2008 8:12 AM

Answers

  • Thanks for reporting this issue. We already had the same bug reported from another customers few weeks back. We are working on fixing this, and hopefully we will release a fix sometime soon.

     

    As you said, the only workaround at this moment is to keep the navigation property name and entity type name same. If you do that, does the entire batch request pass?

     

    Thanks once again for reporting this.

    Pratik

     

    Wednesday, August 20, 2008 5:19 PM
    Moderator

All replies

  • We did a few tests related to DataServiceContext.SaveChanged method. If the service is hosted on ASP.NET Development Server and the database is on the same machine and the client is executed on the same machine then data will be saved correctly. But in any other configuration there will be saving problem. We monitored the network traffic and we noticed that in case when a client and the service are on the different machines (which is standard case J ), that all TCP/IP packaged from client machine to service machine have  TCP CHECKSUM error or some other error. We also tried with service hosted on IIS and database and client on the same machine as IIS, but it doesn’t work as well. In all cases retrieve operation works just fine.

    Any suggestions?

     

    Monday, June 16, 2008 8:40 AM
  • Hi ,

     Can you get a fiddler trace when calling SaveChanges in Batching and Non-Batching mode ?

     

    You can get fiddler from here : http://www.fiddlertool.com/dl/Fiddler2Setup.exe

          1)      Run fiddler and reproduce the issue with SaveChangesOptions.Batch  and SaveChangesOptions.None

    2)      In the right-hand pane with the title “Web Sessions”, Select all the Sessions .
    An easy way to do this is to click on any session in the right-hand pane  and press CTRL+A

    3)      Save the Session History by going to
    File -> Save -> Sessions -> In Archive Zip

     

    Once you have the FIddler archive file ready , let me know and I can arrange for a file share for you guys to upload the trace files.

     

    Monday, June 16, 2008 9:27 PM
    Moderator
  • Hi Phani,

    I have the trace you required for the SaveChangesOptions.None mode. In case of SaveChangesOptions.Batch we got an exception (see bellow). Let me know how can I transfer the trace to you.

    Regards,
    Milos


    Retrieve started...
    Request: 0
    ADP milos
    Test node
    Child2
    Child11
    Child12
    Child21
    Jos Jedan
    Generic 1
    Generic 2
    Save started...
    Request: 1

    Unhandled Exception: System.Net.WebException: Internal Server Error

       at System.Data.Services.Client.DataServiceContext.HandleResponse(HttpStatusC
    de statusCode, Func`1 getResponseStream, Boolean throwOnFailure)
       at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.H
    ndleBatchResponse(BatchStream batch)
       at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.H
    ndleBatchResponse(HttpWebResponse response)
       at System.Data.Services.Client.DataServiceContext.SaveChangesetAsyncResult.B
    tchRequest()
       at System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOpt
    ons options)
       at TestClient.Program.Main(String[] args) in E:\milos.milovanovic\pexim\Expe
    iments\Astoria\TestClient\TestClient\Program.cs:line 40
    Press any key to continue . . .


    Tuesday, June 17, 2008 7:19 AM
  •  

    Hi Milos,

     Please email the Trace File to me at : PhaniRaj AT Microsoft DOT com

    Tuesday, June 17, 2008 4:23 PM
    Moderator
  • We have released the RTM version of the product with a number of bug fixes in our SaveChanges processing.  Please give it a spin with: http://msdn.microsoft.com/en-us/vstudio/cc533448.aspx

    Friday, August 15, 2008 4:42 PM
  • This bug IS NOT solved yet. I wrote a little bit more formal description of the bug:

    Bug: DataServiceContext.DeleteLink doesn’t work when navigation property name is different from referred entity type

    Description:

    Link between object cannot be deleted if navigation property name is different from referred entity type name. Example is shown below.

    Example Model:

    Example model has two entity types TypeA and TypeB and there is association between them. Name of the navigation property on the side TypeA is Children and on the side TypeB is Parent as presented in the image.

    Code sample which should delete link between parent and all its children:

    TypeA oa = ctx.CreateQuery<TypeA>("TypeA")

            .Where<TypeA>(nt => nt.Name == parentName)

                  .First<TypeA>();

     

                if (oa == null)

                {

                    return;

                }

               

                ctx.LoadProperty(oa, "Children");

     

                foreach (TypeB ob in oa.Children)

                {

                    try

                    {

                        ctx.DeleteLink(oa, "Children", ob);

                        ctx.SaveChanges(SaveChangesOptions.Batch);

                    }

                    catch (Exception exc)

                    {

                        Console.WriteLine(exc.Message + " " +

                                          exc.InnerException.Message);

                    }

                }

    Result: Exception will be thrown. Fiddler will show following request to service:

     

    DELETE http://testastoria/ExperimentalService/TestService.svc/TypeA(49)/$links/TypeB(90)

     

    This is obviously wrong. You can see that $links is written in place of navigation property name. It seems that some of you internal variables is not resolved.

     

     

    Tuesday, August 19, 2008 2:04 PM
  • Thanks for reporting this issue. We already had the same bug reported from another customers few weeks back. We are working on fixing this, and hopefully we will release a fix sometime soon.

     

    As you said, the only workaround at this moment is to keep the navigation property name and entity type name same. If you do that, does the entire batch request pass?

     

    Thanks once again for reporting this.

    Pratik

     

    Wednesday, August 20, 2008 5:19 PM
    Moderator
  •  

    > As you said, the only workaround at this moment is to keep the navigation property name and entity type name same.

    > If you do that, does the entire batch request pass?

     

    Yes. If navigation property name and entity type name are the same then batch request passes correctly.

    Friday, August 22, 2008 11:20 AM
  •  

    WARNING: Do not upgrade to SP1 if you are doing Silverlight/ADO.NET Data services work. You will be broken and MS will not help you recover. You will be out of luck. There is NO roll back path, MS pulled the freaking bits.!!!
    Wednesday, August 27, 2008 3:36 PM
  • Ben,

    I know how you feel; I was in the same situation two weeks ago, but I had to upgrade. Situation is not so bad. Here are some things I noticed that are changed and tips for workaround:

    1.       DataServiceContext.CreateQuery method is changed. It is not possible to pass any Astoria query. For example you cannot do something like this anymore:

           DataServiceContext ctx = …;

           DataServiceQuery q = ctx.CreateQuery<X>(“X?$filter=Name eq ‘XXX’$top=1”);

     

                 Workaround for this is (if you call this method directly (in a non generic way)):

                 DataServiceQuery q = Ctx.CreateQuery<X>(“X”).Where<X>(x => x.Name == “XXX”).First();

                    I agree that this programming model is much better and code is much cleaner, so MS should force it. On the other side it will produce only one Astoria query, so it is efficient as if you write your own uri (you can see it in fiddler).

                    If you had to create generic CreateQuery method for some type in runtime, then you should use DataServiceContext.Execute (it is still not changedJ, but in future SP2 they can change it also J so be preparedJ). Problem with this method is that it requires the whole uri. You can transform upper CreateQuery in the following way:

                 DataServiceQuery q = ctx.Execute<T>(new Uri(ctx.BaseUri + “X?$filter=Name eq ‘XXX’$top=1”));

    2.       DataServiceContext.LoadProperty  can throw an exception if there is no children. This happened a couple of times to me. I cannot determine in which cases exactly so put try/catch around it and test exceptions more carefully. Luckily we used LoadProperties in a localized way so we didn’t have to much work with this issue.

     

    3.       Astoria function contains is removed?!?!?!? I really don’t see why. Instead of that function there is function substringof. Besides difference in name, substringof also have arguments in opposite order. With contains function when you wrote contains(s1, s2), semantics was “if s1 contains s2”. With substringof, when you write substringof(s1,s2), semaitics is
    “if s1 is substring of s2”. (Like the arguments changed the order). From my point of view substringof is less intuitive then contains, but situation is as is
    J

     

    Good luck with refactoring.

    Thursday, August 28, 2008 7:24 AM
  • Hi Milos,

     

    1.       DataServiceContext.CreateQuery method is changed. 

    Yes, this method has changed to accept only EntitySetNames.

    The way to go about doing arbitrary queries against the service using the client would be to use the Execute<T> method as you have shown.

     

    2.       DataServiceContext.LoadProperty  can throw an exception if there is no children.

    I would like to know more about this.

    LoadProperty shouldn't throw if there are no entities in the relation specified.

    Can you please send me any details you have about this ?

    You have my email id.

     

    3.       Astoria function "contains" is removed

     

        Yes, this function has been renamed . Please see this thread for the thinking behind renaming this function

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3761930&SiteID=1

    Thursday, August 28, 2008 6:30 PM
    Moderator