diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 088a2bf092..0beb0516c1 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -107,7 +107,7 @@ public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
                 Id = entity.StringId
             };
 
-            if (_jsonApiContext.IsRelationshipData)
+            if (_jsonApiContext.IsRelationshipPath)
                 return data;
 
             data.Attributes = new Dictionary<string, object>();
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index b6bcda29b3..032fef13c4 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -84,11 +84,29 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
 
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
+            AttachHasManyPointers();
             _dbSet.Add(entity);
+
             await _context.SaveChangesAsync();
             return entity;
         }
 
+        /// <summary>
+        /// This is used to allow creation of HasMany relationships when the
+        /// dependent side of the relationship already exists.
+        /// </summary>
+        private void AttachHasManyPointers()
+        {
+            var relationships = _jsonApiContext.HasManyRelationshipPointers.Get();
+            foreach(var relationship in relationships)
+            {
+                foreach(var pointer in relationship.Value)
+                {
+                    _context.Entry(pointer).State = EntityState.Unchanged;
+                }
+            }
+        }
+
         public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
         {
             var oldEntity = await GetAsync(id);
diff --git a/src/JsonApiDotNetCore/Data/IEntityRepository.cs b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
index 4c35d6ea3f..e8bb68ef90 100644
--- a/src/JsonApiDotNetCore/Data/IEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
@@ -1,7 +1,3 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Data
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index 2606342e29..3cb5ccc359 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,20 +1,12 @@
-using Microsoft.EntityFrameworkCore;
 using System;
+using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Extensions
 {
     public static class DbContextExtensions
     {
-        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class
-        {
-            var contextProperties = context.GetType().GetProperties();
-            foreach(var property in contextProperties)
-            {
-                if (property.PropertyType == typeof(DbSet<T>))
-                    return (DbSet<T>)property.GetValue(context);
-            }
-
-            throw new ArgumentException($"DbSet of type {typeof(T).FullName} not found on the DbContext", nameof(T));
-        }
+        [Obsolete("This is no longer required since the introduction of context.Set<T>", error: false)]
+        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class 
+            => context.Set<T>();
     }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index ccc4619966..8cc7c0dffe 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -31,5 +31,28 @@ public static Type GetElementType(this IEnumerable enumerable)
 
             return elementType;
         }
+
+        /// <summary>
+        /// Creates a List{TInterface} where TInterface is the generic for type specified by t
+        /// </summary>
+        public static IEnumerable GetEmptyCollection(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var listType = typeof(List<>).MakeGenericType(t);
+            var list = (IEnumerable)Activator.CreateInstance(listType);
+            return list;
+        }
+
+        /// <summary>
+        /// Creates a new instance of type t, casting it to the specified TInterface 
+        /// </summary>
+        public static TInterface New<TInterface>(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var instance = (TInterface)Activator.CreateInstance(t);
+            return instance;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/TypeHelper.cs b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
index 5135473cdb..0a3e01d0d1 100644
--- a/src/JsonApiDotNetCore/Internal/TypeHelper.cs
+++ b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
@@ -7,6 +7,14 @@ namespace JsonApiDotNetCore.Internal
 {
     public static class TypeHelper
     {
+        public static IList ConvertCollection(IEnumerable<object> collection, Type targetType)
+        {
+            var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(targetType)) as IList;
+            foreach(var item in collection)
+                list.Add(ConvertType(item, targetType));
+            return list;
+        }
+
         public static object ConvertType(object value, Type type)
         {
             if (value == null)
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index eb649ed5dc..4f52a23002 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.4</VersionPrefix>
+    <VersionPrefix>2.2.5</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index 4519dc8cb6..c2d7594400 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -12,7 +12,7 @@ public override void SetValue(object entity, object newValue)
                 .GetType()
                 .GetProperty(InternalRelationshipName);
             
-            propertyInfo.SetValue(entity, newValue);        
+            propertyInfo.SetValue(entity, newValue);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index 03fdb200fc..77422027a7 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -39,9 +39,14 @@ public HasOneAttribute(string publicName, Link documentLinks = Link.All, bool ca
             ? $"{InternalRelationshipName}Id"
             : _explicitIdentifiablePropertyName;
 
+        /// <summary>
+        /// Sets the value of the property identified by this attribute
+        /// </summary>
+        /// <param name="entity">The target object</param>
+        /// <param name="newValue">The new property value</param>
         public override void SetValue(object entity, object newValue)
         {
-            var propertyName = (newValue.GetType() == Type)
+            var propertyName = (newValue?.GetType() == Type)
                 ? InternalRelationshipName
                 : IdentifiablePropertyName;
 
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 2781ecfb53..3e66bdc8aa 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -19,6 +19,28 @@ protected RelationshipAttribute(string publicName, Link documentLinks, bool canI
         public Link DocumentLinks { get; } = Link.All;
         public bool CanInclude { get; }
 
+        public bool TryGetHasOne(out HasOneAttribute result)
+        {
+            if (IsHasOne)
+            {
+                result = (HasOneAttribute)this;
+                return true;
+            }
+            result = null;
+            return false;
+        }
+
+        public bool TryGetHasMany(out HasManyAttribute result)
+        {
+            if (IsHasMany)
+            {
+                result = (HasManyAttribute)this;
+                return true;
+            }
+            result = null;
+            return false;
+        }
+
         public abstract void SetValue(object entity, object newValue);
 
         public override string ToString()
diff --git a/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
new file mode 100644
index 0000000000..721274e3d6
--- /dev/null
+++ b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Request
+{
+    /// <summary>
+    /// Stores information to set relationships for the request resource. 
+    /// These relationships must already exist and should not be re-created.
+    /// 
+    /// The expected use case is POST-ing or PATCH-ing 
+    /// an entity with HasMany relaitonships:
+    /// <code>
+    /// {
+    ///    "data": {
+    ///      "type": "photos",
+    ///      "attributes": {
+    ///        "title": "Ember Hamster",
+    ///        "src": "http://example.com/images/productivity.png"
+    ///      },
+    ///      "relationships": {
+    ///        "tags": {
+    ///          "data": [
+    ///            { "type": "tags", "id": "2" },
+    ///            { "type": "tags", "id": "3" }
+    ///          ]
+    ///        }
+    ///      }
+    ///    }
+    ///  }
+    /// </code>
+    /// </summary>
+    public class HasManyRelationshipPointers
+    {
+        private Dictionary<Type, IList> _hasManyRelationships = new Dictionary<Type, IList>();
+
+        /// <summary>
+        /// Add the relationship to the list of relationships that should be 
+        /// set in the repository layer.
+        /// </summary>
+        public void Add(Type dependentType, IList entities)
+            => _hasManyRelationships[dependentType] = entities;
+
+        /// <summary>
+        /// Get all the models that should be associated
+        /// </summary>
+        public Dictionary<Type, IList> Get() => _hasManyRelationships;
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 6fb7af55e1..45d77c0f77 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
@@ -15,14 +16,20 @@ namespace JsonApiDotNetCore.Serialization
     public class JsonApiDeSerializer : IJsonApiDeSerializer
     {
         private readonly IJsonApiContext _jsonApiContext;
-        private readonly IGenericProcessorFactory _genericProcessorFactory;
 
+        [Obsolete(
+            "The deserializer no longer depends on the IGenericProcessorFactory",
+            error: false)]
         public JsonApiDeSerializer(
             IJsonApiContext jsonApiContext,
             IGenericProcessorFactory genericProcessorFactory)
         {
             _jsonApiContext = jsonApiContext;
-            _genericProcessorFactory = genericProcessorFactory;
+        }
+
+        public JsonApiDeSerializer(IJsonApiContext jsonApiContext)
+        {
+            _jsonApiContext = jsonApiContext;
         }
 
         public object Deserialize(string requestBody)
@@ -200,20 +207,25 @@ private object SetHasOneRelationship(object entity,
 
                 var rio = (ResourceIdentifierObject)relationshipData.ExposedData;
 
-                if (rio == null) return entity;
-
-                var newValue = rio.Id;
-
                 var foreignKey = attr.IdentifiablePropertyName;
                 var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
-                if (entityProperty == null)
+                if (entityProperty == null && rio != null)
                     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
 
-                var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
+                if (entityProperty != null)
+                {
+                    // e.g. PATCH /articles
+                    // {... { "relationships":{ "Owner": { "data" :null } } } }
+                    if (rio == null && Nullable.GetUnderlyingType(entityProperty.PropertyType) == null)
+                        throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null.");
 
-                _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
+                    var newValue = rio?.Id ?? null;
+                    var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
 
-                entityProperty.SetValue(entity, convertedValue);
+                    _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
+
+                    entityProperty.SetValue(entity, convertedValue);
+                }
             }
 
             return entity;
@@ -225,11 +237,6 @@ private object SetHasManyRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
-
-            if (entityProperty == null)
-                throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain an relationsip named {attr.InternalRelationshipName}");
-
             var relationshipName = attr.PublicRelationshipName;
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
@@ -238,11 +245,18 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
+                var relationshipShells = relationshipData.ManyData.Select(r =>
+                {
+                    var instance = attr.Type.New<IIdentifiable>();
+                    instance.StringId = r.Id;
+                    return instance;
+                });
+
+                var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
 
-                var ids = relationshipData.ManyData.Select(r => r.Id);
+                attr.SetValue(entity, convertedCollection);
 
-                genericProcessor.SetRelationships(entity, attr, ids);
+                _jsonApiContext.HasManyRelationshipPointers.Add(attr.Type, convertedCollection);
             }
 
             return entity;
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index bc7a2adb52..642ee00a57 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -80,10 +80,7 @@ private async Task<T> GetWithRelationshipsAsync(TId id)
         }
 
         public virtual async Task<object> GetRelationshipsAsync(TId id, string relationshipName)
-        {
-            _jsonApiContext.IsRelationshipData = true;
-            return await GetRelationshipAsync(id, relationshipName);
-        }
+            => await GetRelationshipAsync(id, relationshipName);
 
         public virtual async Task<object> GetRelationshipAsync(TId id, string relationshipName)
         {
@@ -136,7 +133,7 @@ public virtual async Task UpdateRelationshipsAsync(TId id, string relationshipNa
                 .Relationships
                 .FirstOrDefault(r => r.InternalRelationshipName == relationshipName);
 
-            var relationshipIds = relationships.Select(r => r.Id?.ToString());
+            var relationshipIds = relationships.Select(r => r?.Id?.ToString());
 
             await _entities.UpdateRelationshipsAsync(entity, relationship, relationshipIds);
         }
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index a73f0eb53a..52036f21af 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -6,29 +6,126 @@
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 
 namespace JsonApiDotNetCore.Services
 {
-    public interface IJsonApiContext
+    public interface IJsonApiApplication
     {
         JsonApiOptions Options { get; set; }
-        IJsonApiContext ApplyContext<T>(object controller);
         IContextGraph ContextGraph { get; set; }
-        ContextEntity RequestEntity { get; set; }
-        string BasePath { get; set; }
-        QuerySet QuerySet { get; set; }
-        bool IsRelationshipData { get; set; }
+    }
+
+    public interface IQueryRequest
+    {
         List<string> IncludedRelationships { get; set; }
-        bool IsRelationshipPath { get; }
+        QuerySet QuerySet { get; set; }
         PageManager PageManager { get; set; }
-        IMetaBuilder MetaBuilder { get; set; }
-        IGenericProcessorFactory GenericProcessorFactory { get; set; }
+    }
+
+    public interface IUpdateRequest
+    {
+        /// <summary>
+        /// The attributes that were included in a PATCH request. 
+        /// Only the attributes in this dictionary should be updated.
+        /// </summary>
         Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
+
+        /// <summary>
+        /// Any relationships that were included in a PATCH request. 
+        /// Only the relationships in this dictionary should be updated.
+        /// </summary>
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
+    }
+
+    public interface IJsonApiRequest : IJsonApiApplication, IUpdateRequest, IQueryRequest
+    {
+        /// <summary>
+        /// The request namespace. This may be an absolute or relative path
+        /// depending upon the configuration.
+        /// </summary>
+        /// <example>
+        /// Absolute: https://example.com/api/v1
+        /// 
+        /// Relative: /api/v1
+        /// </example>
+        string BasePath { get; set; }
+
+        /// <summary>
+        /// Stores information to set relationships for the request resource. 
+        /// These relationships must already exist and should not be re-created.
+        /// By default, it is the responsibility of the repository to use the 
+        /// relationship pointers to persist the relationship.
+        /// 
+        /// The expected use case is POST-ing or PATCH-ing an entity with HasMany 
+        /// relaitonships:
+        /// <code>
+        /// {
+        ///    "data": {
+        ///      "type": "photos",
+        ///      "attributes": {
+        ///        "title": "Ember Hamster",
+        ///        "src": "http://example.com/images/productivity.png"
+        ///      },
+        ///      "relationships": {
+        ///        "tags": {
+        ///          "data": [
+        ///            { "type": "tags", "id": "2" },
+        ///            { "type": "tags", "id": "3" }
+        ///          ]
+        ///        }
+        ///      }
+        ///    }
+        ///  }
+        /// </code>
+        /// </summary>
+        HasManyRelationshipPointers HasManyRelationshipPointers { get; }
+
+        /// <summary>
+        /// If the request is a bulk json:api v1.1 operations request.
+        /// This is determined by the `
+        /// <see cref="JsonApiDotNetCore.Serialization.JsonApiDeSerializer" />` class.
+        /// 
+        /// See [json-api/1254](https://github.com/json-api/json-api/pull/1254) for details.
+        /// </summary>
+        bool IsBulkOperationRequest { get; set; }
+
+        /// <summary>
+        /// The `<see cref="ContextEntity" />`for the target route.
+        /// </summary>
+        /// 
+        /// <example>
+        /// For a `GET /articles` request, `RequestEntity` will be set
+        /// to the `Article` resource representation on the `JsonApiContext`.
+        /// </example>
+        ContextEntity RequestEntity { get; set; }
+
+        /// <summary>
+        /// The concrete type of the controller that was activated by the MVC routing middleware
+        /// </summary>
         Type ControllerType { get; set; }
+
+        /// <summary>
+        /// The json:api meta data at the document level
+        /// </summary>
         Dictionary<string, object> DocumentMeta { get; set; }
-        bool IsBulkOperationRequest { get; set; }
 
+        /// <summary>
+        /// If the request is on the `{id}/relationships/{relationshipName}` route
+        /// </summary>
+        bool IsRelationshipPath { get; }
+
+        [Obsolete("Use `IsRelationshipPath` instead.")]
+        bool IsRelationshipData { get; set; }
+    }
+
+    public interface IJsonApiContext : IJsonApiRequest
+    {
+        IJsonApiContext ApplyContext<T>(object controller);
+        IMetaBuilder MetaBuilder { get; set; }
+        IGenericProcessorFactory GenericProcessorFactory { get; set; }
+
+        [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")]
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 2665217fef..0643d494d6 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -6,6 +6,7 @@
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 using Microsoft.AspNetCore.Http;
 
 namespace JsonApiDotNetCore.Services
@@ -51,6 +52,7 @@ public JsonApiContext(
         public Type ControllerType { get; set; }
         public Dictionary<string, object> DocumentMeta { get; set; }
         public bool IsBulkOperationRequest { get; set; }
+        public HasManyRelationshipPointers HasManyRelationshipPointers { get; } = new HasManyRelationshipPointers();
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
index 1dffa6ce87..067483a1b3 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
@@ -127,5 +127,100 @@ public async Task Can_Update_ToOne_Relationship_ThroughLink()
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(todoItemsOwner);
         }
+
+        [Fact]
+        public async Task Can_Delete_Relationship_By_Patching_Resource()
+        {
+            // arrange
+            var person = _personFaker.Generate();
+            var todoItem = _todoItemFaker.Generate();
+            todoItem.Owner = person;
+
+            _context.People.Add(person);
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    relationships = new
+                    {
+                        owner = new
+                        {
+                            data = (object)null
+                        }
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}";
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert
+            var todoItemResult = _context.TodoItems
+                .AsNoTracking()
+                .Include(t => t.Owner)
+                .Single(t => t.Id == todoItem.Id);
+
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Null(todoItemResult.Owner);
+        }
+
+        [Fact]
+        public async Task Can_Delete_Relationship_By_Patching_Relationship()
+        {
+            // arrange
+            var person = _personFaker.Generate();
+            var todoItem = _todoItemFaker.Generate();
+            todoItem.Owner = person;
+
+            _context.People.Add(person);
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = (object)null
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}/relationships/owner";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert
+            var todoItemResult = _context.TodoItems
+                .AsNoTracking()
+                .Include(t => t.Owner)
+                .Single(t => t.Id == todoItem.Id);
+
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Null(todoItemResult.Owner);
+        }
     }
 }
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index dbca1bebb4..fc816765eb 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -1,268 +1,267 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using JsonApiDotNetCore.Builders;
-using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Services;
-using Moq;
-using Xunit;
-
-namespace UnitTests
-{
-    public class DocumentBuilder_Tests
-    {
-        private readonly Mock<IJsonApiContext> _jsonApiContextMock;
-        private readonly PageManager _pageManager;
-        private readonly JsonApiOptions _options;
-        private readonly Mock<IRequestMeta> _requestMetaMock;
-
-        public DocumentBuilder_Tests()
-        {
-            _jsonApiContextMock = new Mock<IJsonApiContext>();
-            _requestMetaMock = new Mock<IRequestMeta>();
-
-            _options = new JsonApiOptions();
-
-            _options.BuildContextGraph(builder =>
-            {
-                builder.AddResource<Model>("models");
-                builder.AddResource<RelatedModel>("related-models");
-            });
-
-            _jsonApiContextMock
-                .Setup(m => m.Options)
-                .Returns(_options);
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            _jsonApiContextMock
-                .Setup(m => m.MetaBuilder)
-                .Returns(new MetaBuilder());
-
-            _pageManager = new PageManager();
-            _jsonApiContextMock
-                .Setup(m => m.PageManager)
-                .Returns(_pageManager);
-
-            _jsonApiContextMock
-                .Setup(m => m.BasePath)
-                .Returns("localhost");
-
-            _jsonApiContextMock
-                .Setup(m => m.RequestEntity)
-                .Returns(_options.ContextGraph.GetContextEntity(typeof(Model)));
-        }
-
-        [Fact]
-        public void Includes_Paging_Links_By_Default()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.NotNull(document.Links);
-            Assert.NotNull(document.Links.Last);
-        }
-
-        [Fact]
-        public void Page_Links_Can_Be_Disabled_Globally()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            _options.BuildContextGraph(builder => builder.DocumentLinks = Link.None);
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.Null(document.Links);
-        }
-
-        [Fact]
-        public void Related_Links_Can_Be_Disabled()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.Null(document.Data.Relationships["related-model"].Links);
-        }
-
-        [Fact]
-        public void Related_Data_Included_In_Relationships_By_Default()
-        {
-            // arrange
-            const string relatedTypeName = "related-models";
-            const string relationshipName = "related-model";
-            const int relatedId = 1;
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model
-            {
-                RelatedModel = new RelatedModel
-                {
-                    Id = relatedId
-                }
-            };
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            var relationshipData = document.Data.Relationships[relationshipName];
-            Assert.NotNull(relationshipData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
-            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+using System.Collections;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Services;
+using Moq;
+using Xunit;
+
+namespace UnitTests
+{
+    public class DocumentBuilder_Tests
+    {
+        private readonly Mock<IJsonApiContext> _jsonApiContextMock;
+        private readonly PageManager _pageManager;
+        private readonly JsonApiOptions _options;
+        private readonly Mock<IRequestMeta> _requestMetaMock;
+
+        public DocumentBuilder_Tests()
+        {
+            _jsonApiContextMock = new Mock<IJsonApiContext>();
+            _requestMetaMock = new Mock<IRequestMeta>();
+
+            _options = new JsonApiOptions();
+
+            _options.BuildContextGraph(builder =>
+            {
+                builder.AddResource<Model>("models");
+                builder.AddResource<RelatedModel>("related-models");
+            });
+
+            _jsonApiContextMock
+                .Setup(m => m.Options)
+                .Returns(_options);
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            _jsonApiContextMock
+                .Setup(m => m.MetaBuilder)
+                .Returns(new MetaBuilder());
+
+            _pageManager = new PageManager();
+            _jsonApiContextMock
+                .Setup(m => m.PageManager)
+                .Returns(_pageManager);
+
+            _jsonApiContextMock
+                .Setup(m => m.BasePath)
+                .Returns("localhost");
+
+            _jsonApiContextMock
+                .Setup(m => m.RequestEntity)
+                .Returns(_options.ContextGraph.GetContextEntity(typeof(Model)));
+        }
+
+        [Fact]
+        public void Includes_Paging_Links_By_Default()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.NotNull(document.Links);
+            Assert.NotNull(document.Links.Last);
         }
 
-        [Fact]
-        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
-        {
-            // arrange
-            const string relatedTypeName = "related-models";
-            const string relationshipName = "related-model";
-            const int relatedId = 1;
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model
+        [Fact]
+        public void Page_Links_Can_Be_Disabled_Globally()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            _options.BuildContextGraph(builder => builder.DocumentLinks = Link.None);
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.Null(document.Links);
+        }
+
+        [Fact]
+        public void Related_Links_Can_Be_Disabled()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.Null(document.Data.Relationships["related-model"].Links);
+        }
+
+        [Fact]
+        public void Related_Data_Included_In_Relationships_By_Default()
+        {
+            // arrange
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
             {
-                RelatedModelId = relatedId
-            };
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            var relationshipData = document.Data.Relationships[relationshipName];
-            Assert.NotNull(relationshipData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
-            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
-        }
-
-        [Fact]
-        public void Build_Can_Build_Arrays()
-        {
-            var entities = new[] { new Model() };
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-
-            var documents = documentBuilder.Build(entities);
-
-            Assert.Equal(1, documents.Data.Count);
-        }
-
-        [Fact]
-        public void Build_Can_Build_CustomIEnumerables()
-        {
-            var entities = new Models(new[] { new Model() });
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-
-            var documents = documentBuilder.Build(entities);
-
-            Assert.Equal(1, documents.Data.Count);
-        }
-
-
-        [Theory]
-        [InlineData(null, null, true)]
-        [InlineData(false, null, true)]
-        [InlineData(true, null, false)]
-        [InlineData(null, "foo", true)]
-        [InlineData(false, "foo", true)]
-        [InlineData(true, "foo", true)]
-        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
-            string attributeValue,
-            bool resultContainsAttribute)
-        {
-            var documentBuilderBehaviourMock = new Mock<IDocumentBuilderOptionsProvider>();
-            if (omitNullValuedAttributes.HasValue)
-            {
-                documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
-                    .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
-            }
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
-            var document = documentBuilder.Build(new Model() { StringProperty = attributeValue });
-
-            Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
-        }
-
-        private class Model : Identifiable
-        {
-            [HasOne("related-model", Link.None)]
-            public RelatedModel RelatedModel { get; set; }
-            public int RelatedModelId { get; set; }
-            [Attr("StringProperty")]
-            public string StringProperty { get; set; }
-
-        }
-
-        private class RelatedModel : Identifiable
-        {
-            [HasMany("models")]
-            public List<Model> Models { get; set; }
-        }
-
-        private class Models : IEnumerable<Model>
-        {
-            private readonly IEnumerable<Model> models;
-
-            public Models(IEnumerable<Model> models)
-            {
-                this.models = models;
-            }
-
-            public IEnumerator<Model> GetEnumerator()
-            {
-                return models.GetEnumerator();
-            }
-
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return models.GetEnumerator();
-            }
-        }
-    }
-}
+                RelatedModel = new RelatedModel
+                {
+                    Id = relatedId
+                }
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+        }
+
+        [Fact]
+        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
+        {
+            // arrange
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
+            {
+                RelatedModelId = relatedId
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+        }
+
+        [Fact]
+        public void Build_Can_Build_Arrays()
+        {
+            var entities = new[] { new Model() };
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
+        [Fact]
+        public void Build_Can_Build_CustomIEnumerables()
+        {
+            var entities = new Models(new[] { new Model() });
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
+
+        [Theory]
+        [InlineData(null, null, true)]
+        [InlineData(false, null, true)]
+        [InlineData(true, null, false)]
+        [InlineData(null, "foo", true)]
+        [InlineData(false, "foo", true)]
+        [InlineData(true, "foo", true)]
+        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
+            string attributeValue,
+            bool resultContainsAttribute)
+        {
+            var documentBuilderBehaviourMock = new Mock<IDocumentBuilderOptionsProvider>();
+            if (omitNullValuedAttributes.HasValue)
+            {
+                documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
+                    .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
+            }
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
+            var document = documentBuilder.Build(new Model() { StringProperty = attributeValue });
+
+            Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
+        }
+
+        private class Model : Identifiable
+        {
+            [HasOne("related-model", Link.None)]
+            public RelatedModel RelatedModel { get; set; }
+            public int RelatedModelId { get; set; }
+            [Attr("StringProperty")]
+            public string StringProperty { get; set; }
+
+        }
+
+        private class RelatedModel : Identifiable
+        {
+            [HasMany("models")]
+            public List<Model> Models { get; set; }
+        }
+
+        private class Models : IEnumerable<Model>
+        {
+            private readonly IEnumerable<Model> models;
+
+            public Models(IEnumerable<Model> models)
+            {
+                this.models = models;
+            }
+
+            public IEnumerator<Model> GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+        }
+    }
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs b/test/UnitTests/Builders/MetaBuilderTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
rename to test/UnitTests/Builders/MetaBuilderTests.cs
index 5cd0b765de..0b784ef5b7 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
+++ b/test/UnitTests/Builders/MetaBuilderTests.cs
@@ -1,8 +1,8 @@
-using Xunit;
-using JsonApiDotNetCore.Builders;
 using System.Collections.Generic;
+using JsonApiDotNetCore.Builders;
+using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Builders
+namespace UnitTests.Builders
 {
     public class MetaBuilderTests
     {
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
similarity index 88%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
rename to test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
index f6772fa22b..1b00c5aaa1 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
@@ -10,12 +10,11 @@
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.DependencyInjection;
-using UnitTests;
 using Xunit;
+using Microsoft.EntityFrameworkCore;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Extensions
+namespace UnitTests.Extensions
 {
     public class IServiceCollectionExtensionsTests
     {
@@ -26,10 +25,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
             var services = new ServiceCollection();
             var jsonApiOptions = new JsonApiOptions();
 
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseMemoryCache(new MemoryCache(new MemoryCacheOptions()));
-            }, ServiceLifetime.Transient);
+            services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("UnitTestDb"), ServiceLifetime.Transient);
 
             // act
             services.AddJsonApiInternals<AppDbContext>(jsonApiOptions);
diff --git a/test/UnitTests/Extensions/TypeExtensions_Tests.cs b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
new file mode 100644
index 0000000000..f59fa37be0
--- /dev/null
+++ b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Models;
+using Xunit;
+
+namespace UnitTests.Extensions
+{
+    public class TypeExtensions_Tests
+    {
+        [Fact]
+        public void GetCollection_Creates_List_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var collection = type.GetEmptyCollection();
+
+            // assert
+            Assert.NotNull(collection);
+            Assert.Empty(collection);
+            Assert.IsType<List<Model>>(collection);
+        }
+
+        [Fact]
+        public void New_Creates_An_Instance_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var instance = type.New<IIdentifiable>();
+
+            // assert
+            Assert.NotNull(instance);
+            Assert.IsType<Model>(instance);
+        }
+
+        private class Model : IIdentifiable
+        {
+            public string StringId { get; set; }
+        }
+    }
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs b/test/UnitTests/Models/AttributesEqualsTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
rename to test/UnitTests/Models/AttributesEqualsTests.cs
index 107dd1d593..0b989169ef 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
+++ b/test/UnitTests/Models/AttributesEqualsTests.cs
@@ -1,7 +1,7 @@
 using JsonApiDotNetCore.Models;
 using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Models
+namespace UnitTests.Models
 {
     public class AttributesEqualsTests
     {
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 1e20c0359e..ec34d87d24 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -2,8 +2,8 @@
 using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using Moq;
@@ -11,10 +11,13 @@
 using Newtonsoft.Json.Serialization;
 using Xunit;
 
-namespace UnitTests.Serialization {
-    public class JsonApiDeSerializerTests {
+namespace UnitTests.Serialization
+{
+    public class JsonApiDeSerializerTests
+    {
         [Fact]
-        public void Can_Deserialize_Complex_Types() {
+        public void Can_Deserialize_Complex_Types()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -29,20 +32,18 @@ public void Can_Deserialize_Complex_Types() {
             jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new { compoundName = "testName" }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        { "complex-member", new { compoundName = "testName" } }
+                    }
                 }
             };
 
@@ -55,7 +56,8 @@ public void Can_Deserialize_Complex_Types() {
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_List_Types() {
+        public void Can_Deserialize_Complex_List_Types()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResourceWithList>("test-resource");
@@ -69,22 +71,18 @@ public void Can_Deserialize_Complex_List_Types() {
             jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-members",
-                new [] {
-                new { compoundName = "testName" }
-                }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        { "complex-members", new [] { new { compoundName = "testName" } } }
+                    }
                 }
             };
 
@@ -98,7 +96,8 @@ public void Can_Deserialize_Complex_List_Types() {
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
+        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -113,20 +112,20 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
             jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver(); // <--
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new Dictionary<string, string> { { "compound-name", "testName" } }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        {
+                            "complex-member", new Dictionary<string, string> { { "compound-name", "testName" } }
+                        }
+                    }
                 }
             };
 
@@ -139,7 +138,8 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
         }
 
         [Fact]
-        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
+        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -156,22 +156,21 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
             jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new Dictionary<string, string> { { "compound-name", "testName" }
-                }
-                },
-                { "immutable", "value" }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        {
+                            "complex-member", new Dictionary<string, string> { { "compound-name", "testName" } }
+                        },
+                        { "immutable", "value" }
+                    }
                 }
             };
 
@@ -189,7 +188,8 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -204,17 +204,16 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "independents",
-                Id = "1",
-                Attributes = new Dictionary<string, object> { { "property", property }
-                }
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> { { "property", property } }
                 }
             };
 
@@ -229,7 +228,8 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body() {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -244,20 +244,18 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Rel
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "independents",
-                Id = "1",
-                Attributes = new Dictionary<string, object> { { "property", property }
-                },
-                // a common case for this is deserialization in unit tests
-                Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
-                }
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> { { "property", property } },
+                    // a common case for this is deserialization in unit tests
+                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } } }
                 }
             };
 
@@ -288,24 +286,21 @@ public void Sets_The_DocumentMeta_Property_In_JsonApiContext()
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            
+
             var content = new Document
-            {   
-                Meta = new Dictionary<string, object>() { {"foo", "bar"}},
+            {
+                Meta = new Dictionary<string, object>() { { "foo", "bar" } },
                 Data = new DocumentData
                 {
                     Type = "independents",
                     Id = "1",
-                    Attributes = new Dictionary<string, object> { { "property", property }
-                    },
+                    Attributes = new Dictionary<string, object> { { "property", property } },
                     // a common case for this is deserialization in unit tests
-                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
-                    }
+                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } } }
                 }
             };
 
@@ -318,32 +313,100 @@ public void Sets_The_DocumentMeta_Property_In_JsonApiContext()
             jsonApiContextMock.VerifySet(mock => mock.DocumentMeta = content.Meta);
         }
 
-
-        private class TestResource : Identifiable {
+        private class TestResource : Identifiable
+        {
             [Attr("complex-member")]
             public ComplexType ComplexMember { get; set; }
 
-            [Attr("immutable", isImmutable : true)]
+            [Attr("immutable", isImmutable: true)]
             public string Immutable { get; set; }
         }
 
-        private class TestResourceWithList : Identifiable {
+        private class TestResourceWithList : Identifiable
+        {
             [Attr("complex-members")]
             public List<ComplexType> ComplexMembers { get; set; }
         }
 
-        private class ComplexType {
+        private class ComplexType
+        {
             public string CompoundName { get; set; }
         }
 
-        private class Independent : Identifiable {
+        private class Independent : Identifiable
+        {
             [Attr("property")] public string Property { get; set; }
             [HasOne("dependent")] public Dependent Dependent { get; set; }
         }
 
-        private class Dependent : Identifiable {
+        private class Dependent : Identifiable
+        {
             [HasOne("independent")] public Independent Independent { get; set; }
             public int IndependentId { get; set; }
         }
+
+        [Fact]
+        public void Can_Deserialize_Object_With_HasManyRelationship()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<OneToManyIndependent>("independents");
+            contextGraphBuilder.AddResource<OneToManyDependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+            jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
+
+            var contentString =
+            @"{
+                ""data"": {
+                    ""type"": ""independents"",
+                    ""id"": ""1"",
+                    ""attributes"": { },
+                    ""relationships"": {
+                        ""dependents"": {
+                            ""data"": [
+                                {
+                                    ""type"": ""dependents"",
+                                    ""id"": ""2""
+                                }
+                            ]
+                        }
+                    }
+                }
+            }";
+
+            // act
+            var result = deserializer.Deserialize<OneToManyIndependent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(1, result.Id);
+            Assert.NotNull(result.Dependents);
+            Assert.NotEmpty(result.Dependents);
+            Assert.Equal(1, result.Dependents.Count);
+
+            var dependent = result.Dependents[0];
+            Assert.Equal(2, dependent.Id);
+        }
+
+        private class OneToManyDependent : Identifiable
+        {
+            [HasOne("independent")] public OneToManyIndependent Independent { get; set; }
+            public int IndependentId { get; set; }
+        }
+
+        private class OneToManyIndependent : Identifiable
+        {
+            [HasMany("dependents")] public List<OneToManyDependent> Dependents { get; set; }
+        }
     }
 }
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index 14a0d30e33..a6ed346e7d 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -12,5 +12,6 @@
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" />
   </ItemGroup>
 </Project>