simple-odata-client / Simple.OData.Client

MIT License
331 stars 197 forks source link

Empty ODataEntry when using dynamic API query while basic API works fine #171

Open Jerther opened 9 years ago

Jerther commented 9 years ago

Here is a query:

http://localhost:56062/api/Receivings?$expand=Trucker($select=Name),Transporter($select=Name)

this yields the following JSON:

{
  "@odata.context": "http://localhost:56062/api/$metadata#Receivings(Trucker(Name),Transporter(Name))",
  "value": [
    {
      "ReceivingId": "",
      "PlannedDate": "2014-06-18T23:00:00-05:00",
      "ID": 1,
      "Trucker": null,
      "Transporter": null
    },
    {
      "ReceivingId": "",
      "PlannedDate": "2014-06-26T06:20:41.99-05:00",
      "ID": 2,
      "Trucker": null,
      "Transporter": null
    }
  ]
}

I can construct the rquery URL using the basic API:

await mClient.FindEntriesAsync("Receivings?$expand=Trucker($select=Name),Transporter($select=Name)");

And the results are what I expect. All properties are there. However, if I construct the request this way:

await mClient.For(x.Receivings)
    .Expand(x.Trucker, x.Transporter)
    .Select(x.Trucker.Name, x.Transporter.Name)
    .FindEntriesAsync()

I get the same number of results but they're all empty! If I remove the .Select() line, then the results are ok but I miss the Trucker and Transporter properties.

Then, if I do this:

var commandText = await mClient.For(x.Receivings)
    .Expand(x.Trucker, x.Transporter)
    .Select(x.Trucker.Name, x.Transporter.Name)
    .GetCommandTextAsync();
await mClient.FindEntriesAsync(commandText);

Then I get everything, like I would if I constructed my query string manually.

I expect the results of both APIs to be identical for identical query URLs.

object commented 9 years ago

Thanks, that's an interesting one. Will have a look.

object commented 9 years ago

OK, I ran some tests. When it comes to different behavior when you first call GetCommandTextAsync and then FindEntriesAsync, then it's understandable. You first generate a text and then no longer use dynamic in the call to FindEntriesAsync. So the result conversion works completely differently. And I've improved nested dynamic result conversion that may fix your issue. Will be release in version 4.12.

Jerther commented 9 years ago

Looking forward to it, thanks!

Jerther commented 9 years ago

I found something else related to this. Here is a JSON returned to a Simple.OData.Client call:

var charts = await mClient.For(x.ScaleCharts)
    .Expand(x.VolumeUnit, x.Details)
    .FindEntriesAsync()
{
  "@odata.context": "http://localhost:56062/api/$metadata#ScaleCharts",
  "value": [
    {
      "Name": "Table Maine(Bangor)",
      "ScaleChartId": "Maine",
      "Active": false,
      "ID": 6,
      "VolumeUnit": {
        "Description": "PMP",
        "DescriptionForeign": "FBM",
        "MeasuringID": "PMP",
        "Constant": 1002,
        "Availability": "PurchaseOrder, CustomerOrder",
        "ID": 2
      },
      "Details": [
        {
          "Diameter": 4,
          "DiameterMax": 4.4999,
          "DiameterMin": 3.5,
          "Length": 8,
          "Volume": 3,
          "ID": 271
        },
        {
          "Diameter": 5,
          "DiameterMax": 5.4999,
          "DiameterMin": 4.5,
          "Length": 8,
          "Volume": 4,
          "ID": 272
        }
      ]
    },
    {
      "Name": "Charte des mesures",
      "ScaleChartId": "Charte",
      "Active": true,
      "ID": 70,
      "VolumeUnit": {
        "Description": "PL",
        "DescriptionForeign": "LF",
        "MeasuringID": "PL",
        "Constant": 1001,
        "Availability": "PurchaseOrder, CustomerOrder",
        "ID": 1
      },
      "Details": []
    }
  ]
}

Notice the second Details array is empty. If I loop through charts, the second one has no .Details property! I was expecting the property to at least exist, and be set to an empty collection. I'll see with 4.12. Meanwhile I'll check if the property exists first.

object commented 9 years ago

Did you have a chance to check the original issue with the version 4.12?

Jerther commented 8 years ago

The project has evolved since, I'm working on this with 4.13. Seems good so far.

I'm having some difficulties with Select() though. in this example:

.For(x.ScaleCharts)
.Expand(x.DiameterUnit, x.LengthUnit, x.VolumeUnit, x.Details)
.Select(x.DiameterUnit.MeasuringID, x.LengthUnit.MeasuringID, x.VolumeUnit.MeasuringID)

The returned JSon from OData has all ScaleChart properties, and only some for the expanded properties, which is what I expect.

But once deserialized as dynamic objects, I get exclusively what's in Select(), and nothing from the base object (ScaleChart). Do I have to manually select each property whenever I add Select() ? This could become quite cumbersome for large objects...