locked
Astoria (save operation) from SL2B2 RRS feed

  • Question

  • Hi, I have the following code sample:

     

    Code Snippet

    Uri uri = new Uri("http://localhost:49968/WebDataService1.svc");

    Entities ctx = new Entities(uri);

    ctx.MergeOption = MergeOption.OverwriteChanges;

    DataServiceQuery<Link2> query = (DataServiceQuery<Link2>)(from l in ctx.Link2

    where l.ID == 1

    select l);

    Link2 l2 = new Link2();

    query.BeginExecute((result) =>

    {

    l2 = query.EndExecute(result).First();

    }, null);

    Description d = new Description();

    d.Name = "fifth one";

    ctx.AddObject("Description", d);

    d.Link2 = l2;

    ctx.AddLink(d, "Link2", l2);

    ctx.BeginSaveChanges(

    delegate(IAsyncResult ar)

    {

    ctx.EndSaveChanges(ar);

    },

    null);

     

     

     

    However, I get an error on the following line:-

     

    ctx.AddLink(d, "Link2", l2);

     

    The error is as follows:

    System.InvalidOperationException occurred
      Message="The context is not currently tracking the entity."
      StackTrace:
           at System.Data.Services.Client.DataServiceContext.EnsureContained(Object resource, String parameterName)
           at System.Data.Services.Client.DataServiceContext.EnsureRelatable(Object source, String sourceProperty, Object target, EntityStates state)
           at System.Data.Services.Client.DataServiceContext.AddLink(Object source, String sourceProperty, Object target)
           at SilverlightApplication2.Page.btnClick2_Click(Object sender, RoutedEventArgs e)
      InnerException:

    The code is in a silverlight application (Silverlight2 Beta 2).

     

    Thanks in advance,

     

    NJP

    Friday, June 13, 2008 3:10 PM

Answers

  •  

    Hi Nitish,

     When you call BeginSaveChanges without any options , if any error occurs during processing the request , no exception is thrown. To see the exception , you will have to loop through the DataServiceResponse and check if any operation failed.

    An easier way to troubleshoot this would be to use SaveCHangesOptions.Batch

     

    Code Snippet

    ctx.BeginSaveChanges(SaveChangesOptions.Batch,

    delegate(IAsyncResult ar)

    {

    ctx.EndSaveChanges(ar);

    },

    null);

    }

     

     

    This will surface the exception from the request and will help you move ahead
    Monday, June 16, 2008 9:23 PM
    Moderator

All replies

  • Hi ,

     

     You need to attach the Link object to the context.

    Code Snippet

    ctx.AttachTo("EntitySetName", l2);

     

     

    Where EntitySetName is the name of the set to which l2 belongs to

     

    Friday, June 13, 2008 3:51 PM
    Moderator
  • Thanks for your reply Phani;

     

    Here is what I have tried: -

     

    Code Snippet

    private void btnClick_Click(object sender, RoutedEventArgs e)

    {

    Entities ctx = new Entities(new Uri("http://localhost:49968/WebDataService1.svc"));

    var qry = from l in ctx.Link2

    where l.ID == 1

    select l;

    // Cast the query to a DataServiceQuery

    DataServiceQuery<Link2> Link2Query = (DataServiceQuery<Link2>)qry;

    // Start the execution

    Link2Query.BeginExecute(new AsyncCallback(OnLoadComplete),

    Link2Query);

    }

    void OnLoadComplete(IAsyncResult result)

    {

    // Get a reference to the Query

    DataServiceQuery<Link2> Link2Query =

    (DataServiceQuery<Link2>)result.AsyncState;

    // Get ther esults and add them to the collection

    List<Link2> _lnks = Link2Query.EndExecute(result).ToList();

    Uri uri = new Uri("http://localhost:49968/WebDataService1.svc");

    Entities ctx = new Entities(uri);

    ctx.MergeOption = MergeOption.OverwriteChanges;

    DataServiceQuery<Link2> query = (DataServiceQuery<Link2>)(from l in ctx.Link2

    where l.ID == 1

    select l);

     

    ctx.AttachTo("Link2", _lnks.First());

    Description d = new Description();

    d.Name = "fifth one";

    ctx.AddObject("Description", d);

    d.Link2 = _lnks.First();

    ctx.AddLink(d, "Link2", _lnks.First());

    ctx.BeginSaveChanges(

    delegate(IAsyncResult ar)

    {

    ctx.EndSaveChanges(ar);

    },

    null);

    }

     

     

     

    I do not get any error; but nothing saves unfortunately.

     

    Thanks in Advance

    NJP

    Monday, June 16, 2008 8:19 PM
  •  

    Hi Nitish,

     When you call BeginSaveChanges without any options , if any error occurs during processing the request , no exception is thrown. To see the exception , you will have to loop through the DataServiceResponse and check if any operation failed.

    An easier way to troubleshoot this would be to use SaveCHangesOptions.Batch

     

    Code Snippet

    ctx.BeginSaveChanges(SaveChangesOptions.Batch,

    delegate(IAsyncResult ar)

    {

    ctx.EndSaveChanges(ar);

    },

    null);

    }

     

     

    This will surface the exception from the request and will help you move ahead
    Monday, June 16, 2008 9:23 PM
    Moderator
  • Thanks Phani. I used the SaveChangesOptions.Batch and it worked.

     

    Tuesday, June 17, 2008 1:54 PM
  • I got a problem that is close to what you were talking about. I like to see if you have the answer. I am testing the 'Add' function of the SL2B2 client against a data service for AdventureWorks database. I already retrieved an employee and his purchase order header. Next I want to insert a new purchase order header object. So, created code like this:

     

    Code Snippet

    ...// retrieve emp and his PurchaseOrderHeader.

    // the Employee class has a collection property

    // of PurchaseOrderHeader. The property is also called

    // PurchaseOrderHeader

    PurchaseOrderHeader newOrder = new PurchaseOrderHeader();

    newOrder.Employee = emp;

    ... // set properties of newOrder

     

    _ctx.AttachTo("PurchaseOrderHeader", newOrder.Employee);

    _ctx.AddToPurchaseOrderHeader(newOrder);

    _ctx.AddLink(order, "Employee", newOrder.Employee);

    _ctx.BeginSaveChanges(SaveChangesOptions.Batch,

    delegate(IAsyncResult ar)

    {

      _ctx.EndSaveChanges(ar);

    }

     

     

    Out of this code, I am not sure what the purpose of AttachTo is. Without it, nothing happens. I added it after reading your discussion. But in the way as it shown, It throws exception of "The context is already tracking the entity."

     

    Thanks!

     

     

    Thursday, June 26, 2008 8:10 PM
  • Hi John,

    AttachTO method is used when you have an entity that exists in the store and you would want the DataServiceContext to track the entity . You would use AddObject or AddTO* method when you create a new entity and want the Context to track the entity.


     You would do this explicitly if you create a new instance of the object and set the ID property ( primary Key value ) to a key that exists in the Store(DB). This is done for you implicitly by the DataServiceCOntext when you retrieve a set of entities using CreateQuery,Execute,LoadProperty operations.

    In the above example , you have existing employee objects and new PurchaseOrderHeader objects.

    You would attach the employee instance and add the new PurchaseOrderHeader entity

    The could would look like this

    Code Snippet

    PurchaseOrderHeader newOrder = new PurchaseOrderHeader();

    ... // set properties of newOrder

     

    // add the new Order to the context to track
    _ctx.AddToPurchaseOrderHeader(newOrder);

    emp.PurchaseOrderHeader.Add(newOrder);

     

    // link new PurchaseOrder to the Existing employee

    _ctx.AddLink(emp, "PurchaseOrderHeader ", newOrder);

     

    _ctx.BeginSaveChanges(SaveChangesOptions.Batch,

    delegate(IAsyncResult ar)

    {

      _ctx.EndSaveChanges(ar);

    }

     

     

    Thursday, June 26, 2008 10:16 PM
    Moderator
  • Phani,


     

    Thanks for the reply. It helped me to understand it better. I removed the AttachTo call and modified the AddLink call. If I need to call AddLink for the relation between the employee and the order, what about the relations between the order and ship method, and between the order and vendor? I tried code like this:

     

    Code Snippet

    _ctx.AddLink(emp, "PurchaseOrderHeader ", newOrder);

    _ctx.AddLink(vender, "PurchaseOrderHeader ", newOrder);

    _ctx.AddLink(shipMethod, "PurchaseOrderHeader ", newOrder);

     


    With one call to AddLink or three calls to AddLink, I still don’t see the new order get persisted to database. It seems existed in memory, though. I can tell because my other part of code tried to load the order detail for the newly added order. The context complained about it. It said: “The context can not load the related collection or reference for objects in the added state”. So, it’s in ‘added state’. What do I miss to push it all the way to database?

    John
    Friday, June 27, 2008 1:17 AM
  • Hi John,

     Can you collect a Fiddler trace when calling Begin and End SaveChanges method ?

    That should tell you if the entity is even going on the wire.

    And also , Save with SaveChangesOptions.Batch.

     

    -Phani

     

    Friday, June 27, 2008 1:30 AM
    Moderator
  •  

    Hi Phani,

    There is one post back between the begin and end SaveChanges. Below is the full content. I am using the batch mode for the call. Looks like the server is returning a error.

     

    John

     

    Code Snippet

     

    POST /AdventureWorks.svc/$batch HTTP/1.1
    If-Modified-Since: 11/15/1995 12:00:00 AM
    Accept-Language: en-us
    Referer: http://localhost.:3818/SilverlightControlsTestPage.aspx
    Accept: application/atom+xml,application/xml
    Accept-Charset: UTF-8
    Content-Type: multipart/mixed; boundary=batch_c8660a87-b5d3-40c3-ac52-bdeff069231e
    UA-CPU: x86
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.5.30428)
    Host: localhost.:3818
    Content-Length: 5062
    Connection: Keep-Alive
    Pragma: no-cache

    --batch_c8660a87-b5d3-40c3-ac52-bdeff069231e
    Content-Type: multipart/mixed; boundary=changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5

    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/PurchaseOrderHeader
    Content-ID: 401
    Content-Type: application/atom+xml;type=entry
    Content-Length: 755

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <content type="application/xml">
        <m:properties>
          <d:Freight>3.9500</d:Freight>
          <d:ModifiedDate>0001-01-01T00:00:00</d:ModifiedDate>
          <d:OrderDate>0001-01-01T00:00:00</d:OrderDate>
          <d:PurchaseOrderID>5000</d:PurchaseOrderID>
          <d:RevisionNumber>0</d:RevisionNumber>
          <d:ShipDate m:null="true" />
          <d:Status>0</d:Status>
          <d:SubTotal>0</d:SubTotal>
          <d:TaxAmt>0</d:TaxAmt>
          <d:TotalDue>0</d:TotalDue>
        </m:properties>
      </content>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/Employee(1)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$401</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/Vendor(1)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$401</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/ShipMethod(1)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$401</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/PurchaseOrderHeader
    Content-ID: 405
    Content-Type: application/atom+xml;type=entry
    Content-Length: 756

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <content type="application/xml">
        <m:properties>
          <d:Freight>29.9500</d:Freight>
          <d:ModifiedDate>0001-01-01T00:00:00</d:ModifiedDate>
          <d:OrderDate>0001-01-01T00:00:00</d:OrderDate>
          <d:PurchaseOrderID>5001</d:PurchaseOrderID>
          <d:RevisionNumber>0</d:RevisionNumber>
          <d:ShipDate m:null="true" />
          <d:Status>0</d:Status>
          <d:SubTotal>0</d:SubTotal>
          <d:TaxAmt>0</d:TaxAmt>
          <d:TotalDue>0</d:TotalDue>
        </m:properties>
      </content>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/Employee(1)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$405</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/Vendor(1)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$405</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5
    Operation: POST http://localhost.:3818/AdventureWorks.svc/ShipMethod(3)/PurchaseOrderHeader
    Content-Type: application/atom+xml;type=entry
    Content-Length: 269

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <id>$405</id>
    </entry>
    --changeset_38b0fadb-05b9-4868-8c98-5b8f4e1b31b5--
    --batch_c8660a87-b5d3-40c3-ac52-bdeff069231e--

    HTTP/1.1 200 OK
    Server: ASP.NET Development Server/9.0.0.0
    Date: Fri, 27 Jun 2008 01:47:15 GMT
    X-AspNet-Version: 2.0.50727
    Cache-Control: no-cache
    Content-Type: multipart/mixed; boundary=batchresponse_6970e766-8a3d-4b7a-b343-2995c5a94d88
    Content-Length: 520
    Connection: Close

    --batchresponse_6970e766-8a3d-4b7a-b343-2995c5a94d88
    Content-Type: multipart/mixed; boundary=changesetresponse_d4e5d6e3-b9d2-443a-b64d-397f59575a46
    Cache-Control: no-cache

    --changesetresponse_d4e5d6e3-b9d2-443a-b64d-397f59575a46
    Operation : POST /AdventureWorks.svc/ShipMethod(3)/PurchaseOrderHeader
    Content-Type: text/plain
    Cache-Control: no-cache
    Status-Code: 500

    Internal Server Error
    --changesetresponse_d4e5d6e3-b9d2-443a-b64d-397f59575a46--
    --batchresponse_6970e766-8a3d-4b7a-b343-2995c5a94d88--

     

     

     

    Friday, June 27, 2008 2:02 AM
  •  

    Hi ,

    Please Turn on Dev Error mode on the server by setting

    Code Snippet
    config.UseVerboseErrors = true;

     

     

    in the InitializeService function of the dataservice.

    Then you can see the stack trace on the server.

     

    Reference : http://blogs.msdn.com/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx

    Friday, June 27, 2008 3:21 AM
    Moderator
  • Hi Phani,

    I used that config setting. It immediately unveiled the problem. It was the date time fields out of range and a few other constraint violations. After fixing them, the insertion works.

     

    This is a great help. Thanks a lot!

     

    Friday, June 27, 2008 2:28 PM