Skip to content

Commit

Permalink
Merge pull request #1176 from json-api-dotnet/replace-ef-26779-switch
Browse files Browse the repository at this point in the history
Remove dependency on EF Core "Issue26779" AppContext switch
  • Loading branch information
maurei committed Sep 6, 2022
2 parents 206ca38 + 6825c83 commit eed2ab1
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 6 deletions.
6 changes: 0 additions & 6 deletions src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,6 @@ public sealed class JsonApiOptions : IJsonApiOptions
}
};

static JsonApiOptions()
{
// Bug workaround for https://github.com/dotnet/efcore/issues/27436
AppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue26779", true);
}

public JsonApiOptions()
{
_lazySerializerReadOptions =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,34 @@ private void MarkRelationshipAsLoaded(TResource leftResource, RelationshipAttrib
EntityEntry<TResource> leftEntry = _dbContext.Entry(leftResource);
CollectionEntry rightCollectionEntry = leftEntry.Collection(relationship.Property.Name);
rightCollectionEntry.IsLoaded = true;

if (rightCollectionEntry.Metadata is ISkipNavigation skipNavigation)
{
MarkManyToManyRelationshipAsLoaded(leftEntry, skipNavigation);
}
}

private void MarkManyToManyRelationshipAsLoaded(EntityEntry<TResource> leftEntry, ISkipNavigation skipNavigation)
{
string[] primaryKeyNames = skipNavigation.ForeignKey.PrincipalKey.Properties.Select(property => property.Name).ToArray();
object?[] primaryKeyValues = GetCurrentKeyValues(leftEntry, primaryKeyNames);

string[] foreignKeyNames = skipNavigation.ForeignKey.Properties.Select(property => property.Name).ToArray();

foreach (EntityEntry joinEntry in _dbContext.ChangeTracker.Entries().Where(entry => entry.Metadata == skipNavigation.JoinEntityType).ToList())
{
object?[] foreignKeyValues = GetCurrentKeyValues(joinEntry, foreignKeyNames);

if (primaryKeyValues.SequenceEqual(foreignKeyValues))
{
joinEntry.State = EntityState.Unchanged;
}
}
}

private static object?[] GetCurrentKeyValues(EntityEntry entry, IEnumerable<string> keyNames)
{
return keyNames.Select(keyName => entry.Property(keyName).CurrentValue).ToArray();
}

protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, TResource leftResource, object? valueToAssign,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ public sealed class Car : Identifiable<string?>

[HasOne]
public Dealership? Dealership { get; set; }

[HasMany]
public ISet<Dealership> PreviousDealerships { get; set; } = new HashSet<Dealership>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ protected override void OnModelCreating(ModelBuilder builder)
builder.Entity<Dealership>()
.HasMany(dealership => dealership.Inventory)
.WithOne(car => car.Dealership!);

builder.Entity<Car>()
.HasMany(car => car.PreviousDealerships)
.WithMany(dealership => dealership.SoldCars);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,52 @@ public async Task Can_delete_resource()
carInDatabase.Should().BeNull();
});
}

[Fact]
public async Task Can_remove_from_ManyToMany_relationship()
{
// Arrange
Dealership existingDealership = _fakers.Dealership.Generate();
existingDealership.SoldCars = _fakers.Car.Generate(2).ToHashSet();

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
await dbContext.ClearTableAsync<Car>();
dbContext.Dealerships.Add(existingDealership);
await dbContext.SaveChangesAsync();
});

var requestBody = new
{
data = new[]
{
new
{
type = "cars",
id = existingDealership.SoldCars.ElementAt(1).StringId
}
}
};

string route = $"/dealerships/{existingDealership.StringId}/relationships/soldCars";

// Act
(HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecuteDeleteAsync<string>(route, requestBody);

// Assert
httpResponse.ShouldHaveStatusCode(HttpStatusCode.NoContent);

responseDocument.Should().BeEmpty();

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
Dealership dealershipInDatabase = await dbContext.Dealerships.Include(dealership => dealership.SoldCars).FirstWithIdAsync(existingDealership.Id);
dealershipInDatabase.SoldCars.ShouldHaveCount(1);
dealershipInDatabase.SoldCars.Single().Id.Should().Be(existingDealership.SoldCars.ElementAt(0).Id);
List<Car> carsInDatabase = await dbContext.Cars.ToListAsync();
carsInDatabase.ShouldHaveCount(2);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ public sealed class Dealership : Identifiable<int>

[HasMany]
public ISet<Car> Inventory { get; set; } = new HashSet<Car>();

[HasMany]
public ISet<Car> SoldCars { get; set; } = new HashSet<Car>();
}

0 comments on commit eed2ab1

Please sign in to comment.