Skip to content

Commit 610f65a

Browse files
committed
removed implicit null check on object
1 parent a87e114 commit 610f65a

File tree

6 files changed

+76
-30
lines changed

6 files changed

+76
-30
lines changed

example/Controllers/UserController.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using AutoMapper;
2+
using AutoMapper.QueryableExtensions;
13
using Microsoft.AspNetCore.Mvc;
24
using Microsoft.EntityFrameworkCore;
35

@@ -6,24 +8,28 @@
68
public class UsersController : ControllerBase
79
{
810
private readonly ApplicationDbContext _db;
9-
public UsersController(ApplicationDbContext db)
11+
private readonly IMapper _mapper;
12+
13+
public UsersController(ApplicationDbContext db, IMapper mapper)
1014
{
1115
_db = db;
16+
_mapper = mapper;
1217
}
1318

1419
// GET: /controller/users
1520
[HttpGet]
16-
[ProducesResponseType(typeof(IEnumerable<User>), StatusCodes.Status200OK)]
17-
[EnableQuery<User>(maxTop: 10)]
18-
public ActionResult<IEnumerable<User>> Get()
21+
[ProducesResponseType(typeof(IEnumerable<UserDto>), StatusCodes.Status200OK)]
22+
[EnableQuery<UserDto>(maxTop: 10)]
23+
public ActionResult<IEnumerable<UserDto>> Get()
1924
{
2025
var users = _db.Users
2126
.Include(x => x.Company)
2227
.Include(x => x.Addresses)
2328
.ThenInclude(x => x.City)
2429
.Include(x => x.Manager)
2530
.ThenInclude(x => x.Manager)
26-
.Where(x => !x.IsDeleted);
31+
.Where(x => !x.IsDeleted)
32+
.ProjectTo<UserDto>(_mapper.ConfigurationProvider);
2733

2834
return Ok(users);
2935
}

example/Dto/UserDto.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Text.Json.Serialization;
2+
3+
public record UserDto
4+
{
5+
public Guid Id { get; set; }
6+
7+
[JsonPropertyName("first_name")]
8+
public string Firstname { get; set; } = string.Empty;
9+
public string Lastname { get; set; } = string.Empty;
10+
public int Age { get; set; }
11+
public bool IsEmailVerified { get; set; }
12+
public double Test { get; set; }
13+
public int? NullableInt { get; set; }
14+
public DateTime DateOfBirthUtc { get; set; }
15+
public DateTime DateOfBirthTz { get; set; }
16+
public User? Manager { get; set; }
17+
public IEnumerable<AddressDto> Addresses { get; set; } = Array.Empty<AddressDto>();
18+
public IEnumerable<string> Tags { get; set; } = Array.Empty<string>();
19+
public CompanyDto? Company { get; set; }
20+
}
21+
22+
public record AddressDto
23+
{
24+
public string AddressLine1 { get; set; } = string.Empty;
25+
public CityDto City { get; set; } = new CityDto();
26+
}
27+
28+
public record CityDto
29+
{
30+
public string Name { get; set; } = string.Empty;
31+
public string Country { get; set; } = string.Empty;
32+
}
33+
34+
public record CompanyDto
35+
{
36+
public string Name { get; set; } = string.Empty;
37+
public string Department { get; set; } = string.Empty;
38+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using AutoMapper;
2+
3+
public class AutoMapperProfile : Profile
4+
{
5+
public AutoMapperProfile()
6+
{
7+
CreateMap<User, UserDto>();
8+
CreateMap<Address, AddressDto>();
9+
CreateMap<City, CityDto>();
10+
CreateMap<Company, CompanyDto>();
11+
}
12+
}

example/Program.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
using System.Reflection;
2+
using AutoMapper;
3+
using AutoMapper.QueryableExtensions;
14
using Bogus;
5+
using Microsoft.AspNetCore.Mvc;
26
using Microsoft.EntityFrameworkCore;
37
using Testcontainers.PostgreSql;
48

@@ -19,6 +23,8 @@
1923
options.UseNpgsql(postgreSqlContainer.GetConnectionString());
2024
});
2125

26+
builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());
27+
2228
var app = builder.Build();
2329

2430
using (var scope = app.Services.CreateScope())
@@ -71,7 +77,7 @@
7177

7278
Console.WriteLine($"Postgres connection string: {postgreSqlContainer.GetConnectionString()}");
7379

74-
app.MapGet("/minimal/users", (ApplicationDbContext db, [AsParameters] Query query) =>
80+
app.MapGet("/minimal/users", (ApplicationDbContext db, [FromServices] IMapper mapper, [AsParameters] Query query) =>
7581
{
7682
var result = db.Users
7783
.Include(x => x.Company)
@@ -80,14 +86,15 @@
8086
.Include(x => x.Manager)
8187
.ThenInclude(x => x.Manager)
8288
.Where(x => !x.IsDeleted)
89+
.ProjectTo<UserDto>(mapper.ConfigurationProvider)
8390
.Apply(query);
8491

8592
if (result.IsFailed)
8693
{
8794
return Results.BadRequest(new { message = result.Errors });
8895
}
8996

90-
var response = new PagedResponse<User>(result.Value.Query.ToList(), result.Value.Count);
97+
var response = new PagedResponse<UserDto>(result.Value.Query.ToList(), result.Value.Count);
9198

9299
return Results.Ok(response);
93100
});

example/example.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
1011
<PackageReference Include="Bogus" Version="35.6.3" />
1112
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
1213
<PackageReference Include="Testcontainers" Version="4.5.0" />

src/GoatQuery/src/Evaluator/FilterEvaluator.cs

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,26 @@ private static Result<Expression> EvaluatePropertyPathExpression(
5555
var propertyPathResult = BuildPropertyPath(propertyPath, baseExpression, context.PropertyMappingTree);
5656
if (propertyPathResult.IsFailed) return Result.Fail(propertyPathResult.Errors);
5757

58-
var (finalProperty, nullChecks) = propertyPathResult.Value;
58+
var finalProperty = propertyPathResult.Value;
5959

6060
if (exp.Right is NullLiteral)
6161
{
6262
var nullComparison = CreateNullComparison(exp, finalProperty);
63-
return CombineWithNullChecks(nullComparison, nullChecks);
63+
return nullComparison;
6464
}
6565

6666
var comparisonResult = EvaluateValueComparison(exp, finalProperty);
6767
if (comparisonResult.IsFailed) return comparisonResult;
6868

69-
return CombineWithNullChecks(comparisonResult.Value, nullChecks);
69+
return comparisonResult.Value;
7070
}
7171

72-
private static Result<(MemberExpression Property, List<Expression> NullChecks)> BuildPropertyPath(
72+
private static Result<MemberExpression> BuildPropertyPath(
7373
PropertyPath propertyPath,
7474
Expression startExpression,
7575
PropertyMappingTree propertyMappingTree)
7676
{
7777
var current = startExpression;
78-
var nullChecks = new List<Expression>();
7978
var currentMappingTree = propertyMappingTree;
8079

8180
foreach (var (segment, isLast) in propertyPath.Segments.Select((s, i) => (s, i == propertyPath.Segments.Count - 1)))
@@ -85,12 +84,6 @@ private static Result<Expression> EvaluatePropertyPathExpression(
8584

8685
current = Expression.Property(current, propertyNode.ActualPropertyName);
8786

88-
// Add null check for intermediate reference types only (not the final property)
89-
if (!isLast && IsNullableReferenceType(current.Type))
90-
{
91-
nullChecks.Add(Expression.NotEqual(current, Expression.Constant(null, current.Type)));
92-
}
93-
9487
// Navigate to nested mapping for next segment
9588
if (!isLast)
9689
{
@@ -101,7 +94,7 @@ private static Result<Expression> EvaluatePropertyPathExpression(
10194
}
10295
}
10396

104-
return Result.Ok(((MemberExpression)current, nullChecks));
97+
return Result.Ok((MemberExpression)current);
10598
}
10699

107100
private static Result<MemberExpression> ResolvePropertyPathForCollection(
@@ -185,17 +178,6 @@ private static Expression CreateDateComparison(Expression dateProperty, Constant
185178
};
186179
}
187180

188-
private static Result<Expression> CombineWithNullChecks(Expression comparison, List<Expression> nullChecks)
189-
{
190-
if (!nullChecks.Any())
191-
{
192-
return comparison;
193-
}
194-
195-
var allNullChecks = nullChecks.Aggregate(Expression.AndAlso);
196-
197-
return Expression.AndAlso(allNullChecks, comparison);
198-
}
199181

200182
private static Result<Expression> EvaluateValueComparison(InfixExpression exp, MemberExpression property)
201183
{

0 commit comments

Comments
 (0)