Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.EntityFrameworkCore;

namespace Ardalis.Specification.EntityFrameworkCore
{
public class AsTrackingEvaluator : IEvaluator
{
private AsTrackingEvaluator() { }
public static AsTrackingEvaluator Instance { get; } = new AsTrackingEvaluator();

public bool IsCriteriaEvaluator { get; } = true;

public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specification) where T : class
{
if (specification.AsTracking)
{
query = query.AsTracking();
}

return query;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ public SpecificationEvaluator(bool cacheEnabled = false)
OrderEvaluator.Instance,
PaginationEvaluator.Instance,
AsNoTrackingEvaluator.Instance,
AsNoTrackingWithIdentityResolutionEvaluator.Instance,
AsTrackingEvaluator.Instance,
IgnoreQueryFiltersEvaluator.Instance,
#if !NETSTANDARD2_0
AsSplitQueryEvaluator.Instance,
AsNoTrackingWithIdentityResolutionEvaluator.Instance
#endif
AsSplitQueryEvaluator.Instance
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,35 @@ public static ICacheSpecificationBuilder<T> EnableCache<T>(
return cacheBuilder;
}

/// <summary>
/// If the entity instances are modified, this will be detected
/// by the change tracker.
/// </summary>
/// <param name="specificationBuilder"></param>
public static ISpecificationBuilder<T> AsTracking<T>(
this ISpecificationBuilder<T> specificationBuilder) where T : class
=> AsTracking(specificationBuilder, true);

/// <summary>
/// If the entity instances are modified, this will be detected
/// by the change tracker.
/// </summary>
/// <param name="specificationBuilder"></param>
/// <param name="condition">If false, the setting will be discarded.</param>
public static ISpecificationBuilder<T> AsTracking<T>(
this ISpecificationBuilder<T> specificationBuilder,
bool condition) where T : class
{
if (condition)
{
specificationBuilder.Specification.AsNoTracking = false;
specificationBuilder.Specification.AsNoTrackingWithIdentityResolution = false;
specificationBuilder.Specification.AsTracking = true;
}

return specificationBuilder;
}

/// <summary>
/// If the entity instances are modified, this will not be detected
/// by the change tracker.
Expand All @@ -391,6 +420,8 @@ public static ISpecificationBuilder<T> AsNoTracking<T>(
{
if (condition)
{
specificationBuilder.Specification.AsTracking = false;
specificationBuilder.Specification.AsNoTrackingWithIdentityResolution = false;
specificationBuilder.Specification.AsNoTracking = true;
}

Expand Down Expand Up @@ -463,6 +494,8 @@ public static ISpecificationBuilder<T> AsNoTrackingWithIdentityResolution<T>(
{
if (condition)
{
specificationBuilder.Specification.AsTracking = false;
specificationBuilder.Specification.AsNoTracking = false;
specificationBuilder.Specification.AsNoTrackingWithIdentityResolution = true;
}

Expand Down
6 changes: 6 additions & 0 deletions Specification/src/Ardalis.Specification/ISpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ public interface ISpecification<T>
/// </summary>
string? CacheKey { get; }

/// <summary>
/// Returns whether or not the change tracker will track any of the entities
/// that are returned.
/// </summary>
bool AsTracking { get; }

/// <summary>
/// Returns whether or not the change tracker will track any of the entities
/// that are returned. When true, if the entity instances are modified, this will not be detected
Expand Down
3 changes: 3 additions & 0 deletions Specification/src/Ardalis.Specification/Specification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ public virtual bool IsSatisfiedBy(T entity)
/// <inheritdoc/>
public bool CacheEnabled { get; internal set; }

/// <inheritdoc/>
public bool AsTracking { get; internal set; } = false;

/// <inheritdoc/>
public bool AsNoTracking { get; internal set; } = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,13 @@ public void FlagsAsNoTracking_GivenSpecWithAsNoTracking()

spec.AsNoTracking.Should().Be(true);
}

[Fact]
public void FlagsAsNoTracking_GivenSpecWithAsTrackingAndEndWithAsNoTracking()
{
var spec = new CompanyByIdWithAsTrackingAsUntrackedSpec(1);

spec.AsNoTracking.Should().Be(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,13 @@ public void FlagsAsNoTracking_GivenSpecWithAsNoTrackingWithIdentityResolution()

spec.AsNoTrackingWithIdentityResolution.Should().Be(true);
}

[Fact]
public void FlagsAsNoTracking_GivenSpecWithAsTrackingAndEndWithAsNoTrackingWithIdentityResolution()
{
var spec = new CompanyByIdWithAsTrackingAsUntrackedWithIdentityResolutionSpec(1);

spec.AsNoTrackingWithIdentityResolution.Should().Be(true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Ardalis.Specification.UnitTests.Fixture.Specs;
using FluentAssertions;
using Xunit;

namespace Ardalis.Specification.UnitTests.BuilderTests
{
public class SpecificationBuilderExtensions_AsTracking
{
[Fact]
public void DoesNothing_GivenSpecWithoutAsTracking()
{
var spec = new StoreEmptySpec();

spec.AsTracking.Should().Be(false);
}

[Fact]
public void DoesNothing_GivenAsTrackingWithFalseCondition()
{
var spec = new CompanyByIdWithFalseConditions(1);

spec.AsTracking.Should().Be(false);
}

[Fact]
public void FlagsAsTracking_GivenSpecWithAsTracking()
{
var spec = new CompanyByIdAsTrackedSpec(1);

spec.AsTracking.Should().Be(true);
}

[Fact]
public void FlagsAsTracking_GivenSpecWithAsNoTrackingAndEndWithAsTracking()
{
var spec = new CompanyByIdWithAsNoTrackingAsTrackedSpec(1);

spec.AsTracking.Should().Be(true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ardalis.Specification.UnitTests.Fixture.Entities;

namespace Ardalis.Specification.UnitTests.Fixture.Specs
{
public class CompanyByIdAsTrackedSpec : Specification<Company>, ISingleResultSpecification<Company>
{
public CompanyByIdAsTrackedSpec(int id)
{
Query.Where(company => company.Id == id).AsTracking();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ardalis.Specification.UnitTests.Fixture.Entities;

namespace Ardalis.Specification.UnitTests.Fixture.Specs
{
public class CompanyByIdWithAsNoTrackingAsTrackedSpec : Specification<Company>, ISingleResultSpecification<Company>
{
public CompanyByIdWithAsNoTrackingAsTrackedSpec(int id)
{
Query.Where(company => company.Id == id).AsNoTracking().AsNoTrackingWithIdentityResolution().AsTracking();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ardalis.Specification.UnitTests.Fixture.Entities;

namespace Ardalis.Specification.UnitTests.Fixture.Specs
{
public class CompanyByIdWithAsTrackingAsUntrackedSpec : Specification<Company>, ISingleResultSpecification<Company>
{
public CompanyByIdWithAsTrackingAsUntrackedSpec(int id)
{
Query.Where(company => company.Id == id).AsTracking().AsNoTracking();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Ardalis.Specification.UnitTests.Fixture.Entities;

namespace Ardalis.Specification.UnitTests.Fixture.Specs
{
public class CompanyByIdWithAsTrackingAsUntrackedWithIdentityResolutionSpec : Specification<Company>,
ISingleResultSpecification<Company>
{
public CompanyByIdWithAsTrackingAsUntrackedWithIdentityResolutionSpec(int id)
{
Query.Where(company => company.Id == id).AsTracking().AsNoTrackingWithIdentityResolution();
}
}
}