I have the following query. When there is no matching record in the database, the method returns null. But I want the response to return object with null properties. How to achieve this?
public async Task<UserResponse> GetUserByEmployeeId(string employeeNumber)
{
var userRecord = await _context.User
.AsNoTracking()
.Include(u => u.Manager)
.Where(x => x.PersonNumber == employeeNumber)
.Select(user => UserReponseMapper.ToUserResponse(user))
.FirstOrDefaultAsync();
// The following returns expected value:
// But, looking for a better solution
/*
if(userRecord == null)
{
userRecord = new UserResponse();
}
*/
return userRecord;
}
public static UserResponse ToUserResponse(User user)
{
return new UserResponse
{
EmployeeNumber = user.PersonNumber,
ManagerNumber = user.Manager?.PersonNumber
};
}
Expected result when no matching record
{
EmployeeNumber: null,
ManagerNumber: null
}
Currently getting result as NULL;
CodePudding user response:
If there are no matching records, ToUserResponse
is not called and FirstOrDefaultAsync
returns null. You can use the null-coalescing operator to return the alternative:
public async Task<UserResponse> GetUserByEmployeeId(string employeeNumber)
{
var userRecord = (await _context.User
.AsNoTracking()
.Include(u => u.Manager)
.Where(x => x.PersonNumber == employeeNumber)
.Select(user => UserReponseMapper.ToUserResponse(user))
.FirstOrDefaultAsync())
?? new UserResponse() { EmployeeNumber: null, ManagerNumber: null };
// ...
This operator checks the result of the first parameter against null; if the result is not null, it is returned, otherwise the second parameter is returned. It is basically a short form of the if-statement in your sample.
CodePudding user response:
If you are looking to condense the lines.
userRecord = (userRecord == null) ? new UserResponse() : userRecord;
Or if you want to add it to the original you can add the Elvis operator. "??"
var userRecord = (await _context.User
.AsNoTracking()
.Include(u => u.Manager)
.Where(x => x.PersonNumber == employeeNumber)
.Select(user => UserReponseMapper.ToUserResponse(user))
.FirstOrDefaultAsync())
?? new UserResponse();
// ^ Checks for null
You need to change your construct if user is null as well.
return new UserResponse
{
EmployeeNumber = user?.PersonNumber,
ManagerNumber = user?.Manager?.PersonNumber
};
CodePudding user response:
I was wrong in my comment (and deleted it), but it got me thinking; since you might want to add more logic to the "create this new object when the result is null" you could do something like the "pseudocode" below (it compiles, but it's just testcode)
public async Task<ResultObject> GetResultObjectAsync()
{
return ProcessResult(
(await GetResult())
.Where(x => x?.ID == new Guid())
.FirstOrDefault());
}
// this is your DB
async Task<List<ResultObject>> GetResult()
{
return new List<ResultObject>();
}
// this is the null-coalesce replacement
public static ResultObject ProcessResult(ResultObject? value)
{
if (value == null) return new ResultObject(); // or add more info like setting default values
return value;
}
// this is just a simple POCO for testing
public class ResultObject
{
public Guid ID { get; set; }
}