Skip to content

fix(#425): fetching HasManyThrough returns no includes #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 14, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Examples/JsonApiDotNetCoreExample/Models/Tag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace JsonApiDotNetCoreExample.Models
{
public class Tag : Identifiable
{
[Attr("name")]
public string Name { get; set; }
}
}
29 changes: 28 additions & 1 deletion src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using JsonApiDotNetCore.Extensions;
using JsonApiDotNetCore.Internal;
Expand Down Expand Up @@ -320,7 +321,9 @@ public virtual IQueryable<TEntity> Include(IQueryable<TEntity> entities, string
entity = _jsonApiContext.ContextGraph.GetContextEntity(relationship.Type);
}

return entities.Include(internalRelationshipPath);
IQueryable<TEntity> included = entities.Include(internalRelationshipPath);
AttachHasManyThrough(relationshipChain, included);
return included;
}

/// <inheritdoc />
Expand Down Expand Up @@ -367,5 +370,29 @@ public async Task<IReadOnlyList<TEntity>> ToListAsync(IQueryable<TEntity> entiti
? await entities.ToListAsync()
: entities.ToList();
}

private void AttachHasManyThrough(string[] relationshipChain, IQueryable<TEntity> included)
{
var hasManyThroughRelationships = _jsonApiContext.RequestEntity.Relationships.OfType<HasManyThroughAttribute>();
foreach (var hasManyThroughRelation in _jsonApiContext.RequestEntity.Relationships.OfType<HasManyThroughAttribute>())
{
if (relationshipChain.Contains(hasManyThroughRelation.PublicRelationshipName))
{
Type rightInstancesListType = typeof(List<>).MakeGenericType(hasManyThroughRelation.Type);
PropertyInfo rightPropertyOnLeft = _jsonApiContext.RequestEntity.EntityType.GetProperty(hasManyThroughRelation.InternalRelationshipName);
foreach (var leftInstance in included)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is going to enumerate and materialize the query result set which is not something we should do yet. i'm thinking the work of mapping these values back should be moved to the serializer. looking closer it looks like the problem exists in the DocumentBuilder and the use of an older api that can't traverse the HasManyThrough relationship.

{
var rightInstancesList = (IList)Activator.CreateInstance(rightInstancesListType);
var throughInstances = (IList)hasManyThroughRelation.ThroughProperty.GetValue(leftInstance);
foreach (var ti in throughInstances)
{
var rightInstance = hasManyThroughRelation.RightProperty.GetValue(ti);
rightInstancesList.Add(rightInstance);
}
rightPropertyOnLeft.SetValue(leftInstance, rightInstancesList);
}
}
}
}
}
}
Empty file modified src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
100755 → 100644
Empty file.
104 changes: 104 additions & 0 deletions src/JsonApiDotNetCore/_site/api/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!DOCTYPE html>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these need to be removed. doc artifacts are only supposed to be created when /p:DocFx=true and shouldn't be checked in. were these built automatically or were you building the docs intentionally?

<!--[if IE]><![endif]-->
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>PLACEHOLDER </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="PLACEHOLDER ">
<meta name="generator" content="docfx 2.33.0.0">

<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="../toc.html">
<meta property="docfx:tocrel" content="../toc.html">



</head>
<body data-spy="scroll" data-target="#affix">
<div id="wrapper">
<header>

<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>

<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>

<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div role="main" class="container body-content hide-when-search">
<div class="article row grid">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="">
<h1 id="placeholder">PLACEHOLDER</h1>

<p>TODO: Add .NET projects to the <em>src</em> folder and run <code>docfx</code> to generate <strong>REAL</strong> <em>API Documentation</em>!</p>
</article>
</div>

<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/fix/hasmanythrough-empty-includes/src/JsonApiDotNetCore/api/index.md/#L1" class="contribution-link">Improve this Doc</a>
</li>
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>

<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>

<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>

<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
110 changes: 110 additions & 0 deletions src/JsonApiDotNetCore/_site/articles/intro.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Add your introductions here! </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Add your introductions here! ">
<meta name="generator" content="docfx 2.33.0.0">

<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="../toc.html">
<meta property="docfx:tocrel" content="toc.html">



</head>
<body data-spy="scroll" data-target="#affix">
<div id="wrapper">
<header>

<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>

<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>

<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div role="main" class="container body-content hide-when-search">

<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="">
<h1 id="add-your-introductions-here">Add your introductions here!</h1>

</article>
</div>

<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/fix/hasmanythrough-empty-includes/src/JsonApiDotNetCore/articles/intro.md/#L1" class="contribution-link">Improve this Doc</a>
</li>
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>

<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>

<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>

<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
20 changes: 20 additions & 0 deletions src/JsonApiDotNetCore/_site/articles/toc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

<div id="sidetoggle">
<div>
<div class="sidefilter">
<form class="toc-filter">
<span class="glyphicon glyphicon-filter filter-icon"></span>
<input type="text" id="toc_filter_input" placeholder="Enter here to filter..." onkeypress="if(event.keyCode==13) {return false;}">
</form>
</div>
<div class="sidetoc">
<div class="toc" id="toc">

<ul class="nav level1">
<li>
<a href="intro.html" name="" title="Introduction">Introduction</a>
</li>
</ul> </div>
</div>
</div>
</div>
Binary file added src/JsonApiDotNetCore/_site/favicon.ico
Binary file not shown.
Binary file not shown.
Loading