odata.net
odata.net copied to clipboard
How to do nested $expand?
I am trying to query an entity using nested expand to get the related entities.
e.g queryContainer.Persons.Expand("Address($expand=Location)").ExecuteAsync();
These are cardinality one relationships.
I get the results as expected from the Odata service but the Odata client gives error:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: The Id cannot be computed, since the navigation source 'Location' cannot be resolved to a known entity set from model. Microsoft.OData.ODataException: The Id cannot be computed, since the navigation source 'Asset' cannot be resolved to a known entity set from model. at Microsoft.OData.Evaluation.ODataConventionalIdMetadataBuilder.ComputeAndCacheId() at Microsoft.OData.Evaluation.ODataConventionalIdMetadataBuilder.get_ComputedId() at Microsoft.OData.Evaluation.ODataConventionalIdMetadataBuilder.GetId() at Microsoft.OData.ODataResourceBase.get_Id() at Microsoft.OData.Client.Materialization.MaterializerEntry.UpdateEntityDescriptor() at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()
I know the Location is in the model because if I try this query, odata client works:
e.g queryContainer.Address.Expand("Location").ExecuteAsync();
It works when this.MergeOption = MergeOption.NoTracking; This is okay for me as my application is Readonly and I don't need tracking on.
I have looked at this issue
Model
public class Book
{
public int Id { get; set; }
public string Isbn { get; set; }
public string Title { get; set; }
public ICollection<Author> Authors { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Award> Awards { get; set; }
}
public class Award
{
public int Id { get; set; }
public string Name { get; set; }
}
OData Client Code
string uri = "";
Uri serviceUri = new Uri(uri);
Container dsc = new Container(serviceUri);
var books = await dsc.Books.Expand("Authors($expand=Awards)").ExecuteAsync();
foreach (Book book in books)
{
Console.WriteLine($"Book: {book.Title}");
foreach (Author author in book.Authors)
{
Console.WriteLine($"\tAuthor: {author.Name}");
foreach (Award award in author.Awards)
{
Console.WriteLine($"\t\t Award: {award.Name}");
}
}
}
I do not need to set the MergeOption.NoTracking
Below is my output. FYI am using an In-Memory data store.
t
@danleydmello Are you using DataServiceCollection?
@KenitoInc , In my case, the references are cardinality one , not sure if it matters
public class ActionPlan
{
public Guid UniversalID { get; set; }
public MapFailureMode FailureMode { get; set; }
}
public class MapFailureMode
{
public Guid UniversalID { get; set; }
public Asset Asset { get; set; }
}
public class Asset
{
public Guid UniversalID { get; set; }
public string AssetNumber { get; set; }
public string Title { get; set; }
}
QueryContainer Definition, I followed microsoft documentation [https://docs.microsoft.com/en-us/odata/client/using-blazor-wasm-with-odata-client]:
public class QueryContainer : DataServiceContext
{
private readonly string _authHeader;
public QueryContainer(Uri baseUri, string authHeader, IEdmModel edmModel) :base(baseUri)
{
_authHeader = authHeader;
Format.LoadServiceModel = () => edmModel;
HttpRequestTransportMode = HttpRequestTransportMode.HttpClient;
Format.UseJson();
MergeOption = MergeOption.NoTracking;
ActionPlans = base.CreateQuery<ActionPlan>("MNT/MaintenanceActionPlans");
SendingRequest2 += QueryContainer_SendingRequest2;
}
private void QueryContainer_SendingRequest2(object? sender, SendingRequest2EventArgs e)
{
e.RequestMessage.SetHeader("Authorization", _authHeader);
}
public DataServiceQuery<ActionPlan> ActionPlans { get; }
}
Any news on this issue?
I really don't like adding MergeOption.NoTracking;