Skip to content

Commit 0b0e8d1

Browse files
committed
feat(relationships): implement relational attrs
1 parent 07ff717 commit 0b0e8d1

File tree

13 files changed

+61
-84
lines changed

13 files changed

+61
-84
lines changed

src/JsonApiDotNetCore/Builders/DocumentBuilder.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,25 +124,25 @@ private void _addRelationships(DocumentData data, ContextEntity contextEntity, I
124124
{
125125
Links = new Links
126126
{
127-
Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.RelationshipName),
128-
Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.RelationshipName)
127+
Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.InternalRelationshipName),
128+
Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.Id.ToString(), r.InternalRelationshipName)
129129
}
130130
};
131131

132-
if (_relationshipIsIncluded(r.RelationshipName))
132+
if (_relationshipIsIncluded(r.InternalRelationshipName))
133133
{
134134
var navigationEntity = _jsonApiContext.ContextGraph
135-
.GetRelationship(entity, r.RelationshipName);
135+
.GetRelationship(entity, r.InternalRelationshipName);
136136

137137
if(navigationEntity == null)
138138
relationshipData.SingleData = null;
139139
else if (navigationEntity is IEnumerable)
140-
relationshipData.ManyData = _getRelationships((IEnumerable<object>)navigationEntity, r.RelationshipName);
140+
relationshipData.ManyData = _getRelationships((IEnumerable<object>)navigationEntity, r.InternalRelationshipName);
141141
else
142-
relationshipData.SingleData = _getRelationship(navigationEntity, r.RelationshipName);
142+
relationshipData.SingleData = _getRelationship(navigationEntity, r.InternalRelationshipName);
143143
}
144144

145-
data.Relationships.Add(r.RelationshipName.Dasherize(), relationshipData);
145+
data.Relationships.Add(r.InternalRelationshipName.Dasherize(), relationshipData);
146146
});
147147
}
148148

@@ -152,9 +152,9 @@ private List<DocumentData> _getIncludedEntities(ContextEntity contextEntity, IId
152152

153153
contextEntity.Relationships.ForEach(r =>
154154
{
155-
if (!_relationshipIsIncluded(r.RelationshipName)) return;
155+
if (!_relationshipIsIncluded(r.InternalRelationshipName)) return;
156156

157-
var navigationEntity = _jsonApiContext.ContextGraph.GetRelationship(entity, r.RelationshipName);
157+
var navigationEntity = _jsonApiContext.ContextGraph.GetRelationship(entity, r.InternalRelationshipName);
158158

159159
if (navigationEntity is IEnumerable)
160160
foreach (var includedEntity in (IEnumerable)navigationEntity)

src/JsonApiDotNetCore/Controllers/JsonApiController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public virtual async Task<IActionResult> PatchRelationshipsAsync(TId id, string
183183
var relationship = _jsonApiContext.ContextGraph
184184
.GetContextEntity(typeof(T))
185185
.Relationships
186-
.FirstOrDefault(r => r.RelationshipName == relationshipName);
186+
.FirstOrDefault(r => r.InternalRelationshipName == relationshipName);
187187

188188
var relationshipIds = relationships.Select(r=>r.Id);
189189

src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
108108
return oldEntity;
109109
}
110110

111-
public async Task UpdateRelationshipsAsync(object parent, Relationship relationship, IEnumerable<string> relationshipIds)
111+
public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
112112
{
113-
var genericProcessor = GenericProcessorFactory.GetProcessor(relationship.BaseType, _context);
113+
var genericProcessor = GenericProcessorFactory.GetProcessor(relationship.Type, _context);
114114
await genericProcessor.UpdateRelationshipsAsync(parent, relationship, relationshipIds);
115115
}
116116

@@ -131,7 +131,7 @@ public virtual async Task<bool> DeleteAsync(TId id)
131131
public virtual IQueryable<TEntity> Include(IQueryable<TEntity> entities, string relationshipName)
132132
{
133133
var entity = _jsonApiContext.RequestEntity;
134-
if(entity.Relationships.Any(r => r.RelationshipName == relationshipName))
134+
if(entity.Relationships.Any(r => r.InternalRelationshipName == relationshipName))
135135
return entities.Include(relationshipName);
136136

137137
throw new JsonApiException("400", "Invalid relationship",

src/JsonApiDotNetCore/Data/IEntityRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public interface IEntityRepository<TEntity, in TId>
3434

3535
Task<TEntity> UpdateAsync(TId id, TEntity entity);
3636

37-
Task UpdateRelationshipsAsync(object parent, Relationship relationship, IEnumerable<string> relationshipIds);
37+
Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
3838

3939
Task<bool> DeleteAsync(TId id);
4040
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
2-
using JsonApiDotNetCore.Models;
32
using System.Collections.Generic;
3+
using JsonApiDotNetCore.Models;
44

55
namespace JsonApiDotNetCore.Internal
66
{
@@ -9,6 +9,6 @@ public class ContextEntity
99
public string EntityName { get; set; }
1010
public Type EntityType { get; set; }
1111
public List<AttrAttribute> Attributes { get; set; }
12-
public List<Relationship> Relationships { get; set; }
12+
public List<RelationshipAttribute> Relationships { get; set; }
1313
}
1414
}

src/JsonApiDotNetCore/Internal/ContextGraph.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public string GetRelationshipName<TParent>(string relationshipName)
4646
e.EntityType == entityType)
4747
.Relationships
4848
.FirstOrDefault(r =>
49-
r.RelationshipName.ToLower() == relationshipName.ToLower())
50-
?.RelationshipName;
49+
r.InternalRelationshipName.ToLower() == relationshipName.ToLower())
50+
?.InternalRelationshipName;
5151
}
5252
}
5353
}

src/JsonApiDotNetCore/Internal/ContextGraphBuilder.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public class ContextGraphBuilder<T> where T : DbContext
1515
public ContextGraph<T> Build()
1616
{
1717
_getFirstLevelEntities();
18-
_loadRelationships();
1918

2019
var graph = new ContextGraph<T>
2120
{
@@ -42,7 +41,8 @@ private void _getFirstLevelEntities()
4241
entities.Add(new ContextEntity {
4342
EntityName = property.Name,
4443
EntityType = entityType,
45-
Attributes = _getAttributes(entityType)
44+
Attributes = _getAttributes(entityType),
45+
Relationships = _getRelationships(entityType)
4646
});
4747
}
4848
}
@@ -66,38 +66,29 @@ private List<AttrAttribute> _getAttributes(Type entityType)
6666
return attributes;
6767
}
6868

69-
private void _loadRelationships()
70-
{
71-
_entities.ForEach(entity => {
72-
73-
var relationships = new List<Relationship>();
74-
var properties = entity.EntityType.GetProperties();
75-
76-
foreach(var entityProperty in properties)
77-
{
78-
var propertyType = entityProperty.PropertyType;
79-
80-
if(_isValidEntity(propertyType)
81-
|| (propertyType.GetTypeInfo().IsGenericType && _isValidEntity(propertyType.GetGenericArguments()[0])))
82-
relationships.Add(_getRelationshipFromPropertyInfo(entityProperty));
83-
}
84-
85-
entity.Relationships = relationships;
86-
});
87-
}
88-
89-
private bool _isValidEntity(Type type)
69+
private List<RelationshipAttribute> _getRelationships(Type entityType)
9070
{
91-
var validEntityRelationshipTypes = _entities.Select(e => e.EntityType);
92-
return validEntityRelationshipTypes.Contains(type);
71+
var attributes = new List<RelationshipAttribute>();
72+
73+
var properties = entityType.GetProperties();
74+
75+
foreach(var prop in properties)
76+
{
77+
var attribute = (RelationshipAttribute)prop.GetCustomAttribute(typeof(RelationshipAttribute));
78+
if(attribute == null) continue;
79+
attribute.InternalRelationshipName = prop.Name;
80+
attribute.Type = _getRelationshipType(attribute, prop);
81+
attributes.Add(attribute);
82+
}
83+
return attributes;
9384
}
9485

95-
private Relationship _getRelationshipFromPropertyInfo(PropertyInfo propertyInfo)
86+
private Type _getRelationshipType(RelationshipAttribute relation, PropertyInfo prop)
9687
{
97-
return new Relationship {
98-
Type = propertyInfo.PropertyType,
99-
RelationshipName = propertyInfo.Name
100-
};
88+
if(relation.IsHasMany)
89+
return prop.PropertyType.GetGenericArguments()[0];
90+
else
91+
return prop.PropertyType;
10192
}
10293
}
10394
}

src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public GenericProcessor(DbContext context)
1717
_context = context;
1818
}
1919

20-
public async Task UpdateRelationshipsAsync(object parent, Relationship relationship, IEnumerable<string> relationshipIds)
20+
public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
2121
{
22-
var relationshipType = relationship.BaseType;
22+
var relationshipType = relationship.Type;
2323

2424
// TODO: replace with relationship.IsMany
2525
if(relationship.Type.GetInterfaces().Contains(typeof(IEnumerable)))
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using System.Collections.Generic;
22
using System.Threading.Tasks;
3+
using JsonApiDotNetCore.Models;
34

45
namespace JsonApiDotNetCore.Internal
56
{
67
public interface IGenericProcessor
78
{
8-
Task UpdateRelationshipsAsync(object parent, Relationship relationship, IEnumerable<string> relationshipIds);
9+
Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
910
}
1011
}

src/JsonApiDotNetCore/Internal/Relationship.cs

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)