Skip to content

Fix/#113 #115

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 4 commits into from
May 27, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 3 additions & 5 deletions docs/EntityRepositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,14 @@ A sample implementation that performs data authorization might look like:
public class MyAuthorizedEntityRepository : DefaultEntityRepository<MyEntity>
{
private readonly ILogger _logger;
private readonly AppDbContext _context;
private readonly IAuthenticationService _authenticationService;

public MyAuthorizedEntityRepository(AppDbContext context,
public MyAuthorizedEntityRepository(
ILoggerFactory loggerFactory,
IJsonApiContext jsonApiContext,
IAuthenticationService authenticationService)
: base(context, loggerFactory, jsonApiContext)
{
_context = context;
: base(loggerFactory, jsonApiContext)
{
_logger = loggerFactory.CreateLogger<MyEntityRepository>();
_authenticationService = authenticationService;
}
Expand Down
21 changes: 21 additions & 0 deletions src/JsonApiDotNetCore/Data/DbContextResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using JsonApiDotNetCore.Extensions;
using Microsoft.EntityFrameworkCore;

namespace JsonApiDotNetCore.Data
{
public class DbContextResolver : IDbContextResolver
{
private readonly DbContext _context;

public DbContextResolver(DbContext context)
{
_context = context;
}

public DbContext GetContext() => _context;

public DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
=> _context.GetDbSet<TEntity>();
}
}
21 changes: 21 additions & 0 deletions src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -17,12 +18,19 @@ public class DefaultEntityRepository<TEntity>
IEntityRepository<TEntity>
where TEntity : class, IIdentifiable<int>
{
[Obsolete("DbContext is no longer directly injected into the ctor. Use JsonApiContext.GetDbContextResolver() instead")]
public DefaultEntityRepository(
DbContext context,
ILoggerFactory loggerFactory,
IJsonApiContext jsonApiContext)
: base(context, loggerFactory, jsonApiContext)
{ }

public DefaultEntityRepository(
ILoggerFactory loggerFactory,
IJsonApiContext jsonApiContext)
: base(loggerFactory, jsonApiContext)
{ }
}

public class DefaultEntityRepository<TEntity, TId>
Expand All @@ -35,6 +43,7 @@ public class DefaultEntityRepository<TEntity, TId>
private readonly IJsonApiContext _jsonApiContext;
private readonly IGenericProcessorFactory _genericProcessorFactory;

[Obsolete("DbContext is no longer directly injected into the ctor. Use JsonApiContext.GetDbContextResolver() instead")]
public DefaultEntityRepository(
DbContext context,
ILoggerFactory loggerFactory,
Expand All @@ -47,6 +56,18 @@ public DefaultEntityRepository(
_genericProcessorFactory = _jsonApiContext.GenericProcessorFactory;
}

public DefaultEntityRepository(
ILoggerFactory loggerFactory,
IJsonApiContext jsonApiContext)
{
var contextResolver = jsonApiContext.GetDbContextResolver();
_context = contextResolver.GetContext();
_dbSet = contextResolver.GetDbSet<TEntity>();
_jsonApiContext = jsonApiContext;
_logger = loggerFactory.CreateLogger<DefaultEntityRepository<TEntity, TId>>();
_genericProcessorFactory = _jsonApiContext.GenericProcessorFactory;
}

public virtual IQueryable<TEntity> Get()
{
if(_jsonApiContext.QuerySet?.Fields != null && _jsonApiContext.QuerySet.Fields.Any())
Expand Down
11 changes: 11 additions & 0 deletions src/JsonApiDotNetCore/Data/IDbContextResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.EntityFrameworkCore;

namespace JsonApiDotNetCore.Data
{
public interface IDbContextResolver
{
DbContext GetContext();
DbSet<TEntity> GetDbSet<TEntity>()
where TEntity : class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public static void AddJsonApiInternals(
services.AddSingleton<DbContextOptions>(new DbContextOptionsBuilder().Options);
}

services.AddScoped<IDbContextResolver, DbContextResolver>();
services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
Expand Down
6 changes: 6 additions & 0 deletions src/JsonApiDotNetCore/Models/AttrAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ public AttrAttribute(string publicName)
PublicAttributeName = publicName;
}

public AttrAttribute(string publicName, string internalName)
{
PublicAttributeName = publicName;
InternalAttributeName = internalName;
}

public string PublicAttributeName { get; set; }
public string InternalAttributeName { get; set; }

Expand Down
2 changes: 2 additions & 0 deletions src/JsonApiDotNetCore/Services/IJsonApiContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using JsonApiDotNetCore.Builders;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Data;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Internal.Generics;
using JsonApiDotNetCore.Internal.Query;
Expand All @@ -24,5 +25,6 @@ public interface IJsonApiContext
IGenericProcessorFactory GenericProcessorFactory { get; set; }
Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
IDbContextResolver GetDbContextResolver();
}
}
8 changes: 8 additions & 0 deletions src/JsonApiDotNetCore/Services/JsonApiContext.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JsonApiDotNetCore.Builders;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Data;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Internal.Generics;
using JsonApiDotNetCore.Internal.Query;
Expand All @@ -13,13 +15,17 @@ namespace JsonApiDotNetCore.Services
public class JsonApiContext : IJsonApiContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IDbContextResolver _contextResolver;

public JsonApiContext(
IDbContextResolver contextResolver,
IContextGraph contextGraph,
IHttpContextAccessor httpContextAccessor,
JsonApiOptions options,
IMetaBuilder metaBuilder,
IGenericProcessorFactory genericProcessorFactory)
{
_contextResolver = contextResolver;
ContextGraph = contextGraph;
_httpContextAccessor = httpContextAccessor;
Options = options;
Expand Down Expand Up @@ -61,6 +67,8 @@ public IJsonApiContext ApplyContext<T>()
return this;
}

public IDbContextResolver GetDbContextResolver() => _contextResolver;

private PageManager GetPageManager()
{
if (Options.DefaultPageSize == 0 && (QuerySet == null || QuerySet.PageQuery.PageSize == 0))
Expand Down
101 changes: 101 additions & 0 deletions test/UnitTests/Data/DefaultEntityRepository_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Internal;
using Microsoft.AspNetCore.Mvc;
using Xunit;
using Moq;
using Microsoft.EntityFrameworkCore;
using JsonApiDotNetCoreExample.Models;
using JsonApiDotNetCore.Extensions;
using JsonApiDotNetCore.Data;
using JsonApiDotNetCore.Models;
using Microsoft.Extensions.Logging;
using JsonApiDotNetCore.Services;
using System.Threading.Tasks;

namespace UnitTests.Data
{
public class DefaultEntityRepository_Tests : JsonApiControllerMixin
{
private readonly Mock<IJsonApiContext> _jsonApiContextMock;
private readonly Mock<ILoggerFactory> _loggFactoryMock;
private readonly Mock<DbSet<TodoItem>> _dbSetMock;
private readonly Mock<DbContext> _contextMock;
private readonly Mock<IDbContextResolver> _contextResolverMock;
private readonly TodoItem _todoItem;
private Dictionary<AttrAttribute, object> _attrsToUpdate = new Dictionary<AttrAttribute, object>();
private Dictionary<RelationshipAttribute, object> _relationshipsToUpdate = new Dictionary<RelationshipAttribute, object>();

public DefaultEntityRepository_Tests()
{
_todoItem = new TodoItem
{
Id = 1,
Description = Guid.NewGuid().ToString(),
Ordinal = 10
};
_jsonApiContextMock = new Mock<IJsonApiContext>();
_loggFactoryMock = new Mock<ILoggerFactory>();
_dbSetMock = DbSetMock.Create<TodoItem>(new[] { _todoItem });
_contextMock = new Mock<DbContext>();
_contextResolverMock = new Mock<IDbContextResolver>();
}

[Fact]
public async Task UpdateAsync_Updates_Attributes_In_AttributesToUpdate()
{
// arrange
var todoItemUpdates = new TodoItem
{
Id = _todoItem.Id,
Description = Guid.NewGuid().ToString()
};

_attrsToUpdate = new Dictionary<AttrAttribute, object>
{
{
new AttrAttribute("description", "Description"),
todoItemUpdates.Description
}
};

var repository = GetRepository();

// act
var updatedItem = await repository.UpdateAsync(_todoItem.Id, todoItemUpdates);

// assert
Assert.NotNull(updatedItem);
Assert.Equal(_todoItem.Ordinal, updatedItem.Ordinal);
Assert.Equal(todoItemUpdates.Description, updatedItem.Description);
}

private DefaultEntityRepository<TodoItem> GetRepository()
{
_contextResolverMock
.Setup(m => m.GetContext())
.Returns(_contextMock.Object);

_contextResolverMock
.Setup(m => m.GetDbSet<TodoItem>())
.Returns(_dbSetMock.Object);

_jsonApiContextMock
.Setup(m => m.AttributesToUpdate)
.Returns(_attrsToUpdate);

_jsonApiContextMock
.Setup(m => m.RelationshipsToUpdate)
.Returns(_relationshipsToUpdate);

_jsonApiContextMock
.Setup(m => m.GetDbContextResolver())
.Returns(_contextResolverMock.Object);

return new DefaultEntityRepository<TodoItem>(
_loggFactoryMock.Object,
_jsonApiContextMock.Object);
}
}
}
Loading