AutoMapper / AutoMapper.Extensions.OData

Creates LINQ expressions from ODataQueryOptions and executes the query.
MIT License
140 stars 38 forks source link

Self-referrential hierarchy generating the wrong SQL query for parent #135

Closed Kizzik closed 2 years ago

Kizzik commented 2 years ago

Consider the following entity:

[Table("OB_TBuildingType")]
public class TBuildingType
{
    [Column("Id")]
    [Required, Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Int32 Id { get; set; }

    [Column("Identifier")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Identity { get; set; }

    public String Name { get; set; }

    [ForeignKey("Parent")]
    public Int32? ParentId { get; set; }
    public TBuildingType Parent { get; set; }

    public virtual ICollection<TBuildingType> Children { get; set; }
}

And corresponding DTO:

public class BuildingType
{
    [Key]
    public Guid Identity { get; set; }
    public string Name { get; set; }
    public Int32? ParentId { get; set; }
    public BuildingType Parent { get; set; }
    public ICollection<BuildingType> Children { get; set; }
}

With a mapping of: CreateMap<TBuildingType, BuildingType>();

When I retrieve the entities, I'm able to expand the children just fine, however when I try to expand the parent it always returns null (even when the entity has a valid parent ID). The following SQL is generated for the call when expanding parent:

SELECT [o].[Id], [o0].[Identifier], [o0].[Name], [o0].[ParentId], [o0].[Id], [o].[Identifier], [o].[Name], [o].[ParentId]
FROM [OB_TBuildingType] AS [o]
LEFT JOIN [OB_TBuildingType] AS [o0] ON [o].[Id] = [o0].[ParentId]
ORDER BY [o].[Id]

Where, if I'm reading it correctly, [o] is the child and [o0] is the parent. It appears to have the joined Id/ParentId relationship reversed. If I manually execute the query with those properties reversed ([o0].[Id] = [o].[ParentId]) it shows the result set I would expect to see in SQL.

If I run the same query options directly against the entity it works as I'd expect. If there's something that I've done wrong in the entity setup or mapping please let me know, but it appears to me that this is happening somewhere in GetQueryAsync.

BlaiseD commented 2 years ago

Consider the solution to issue #102.

If your case is different then you'd want to create a sample we can execute and reproduce the problem (zip upload, a new repository, or add to one of the tests).

Kizzik commented 2 years ago

That sorted out the issue, thanks heaps for that! So is that to say without this option enabled, for a recursive relationship we can only go down the chain (entity > children), not back up it?

BlaiseD commented 2 years ago

That sorted out the issue, thanks heaps for that! So is that to say without this option enabled, for a recursive relationship we can only go down the chain (entity > children), not back up it?

Not sure about that - I would have thought it would fail in either direction if it's already in the hierarchy. That logic is in the main AutoMapper repository.