我有以下查询。当数据库中没有匹配的记录时,该方法返回null。但我希望响应返回具有空属性的对象。如何做到这一点?
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
};
}
没有匹配记录时的预期结果
{
EmployeeNumber: null,
ManagerNumber: null
}
目前得到的结果为 NULL;
回答1
如果没有匹配的记录,则不调用 ToUserResponse
并且 FirstOrDefaultAsync
返回 null。您可以使用 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator 来返回替代方案:
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 };
// ...
该运算符检查第一个参数的结果是否为空;如果结果不为null,则返回,否则返回第二个参数。它基本上是示例中 if 语句的简短形式。
回答2
如果你想压缩线条。
userRecord = (userRecord == null) ? new UserResponse() : userRecord;
或者,如果您想将其添加到原件中,您可以添加 Elvis 运算符。 “??”
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
如果 user 也为空,您需要更改您的构造。
return new UserResponse
{
EmployeeNumber = user?.PersonNumber,
ManagerNumber = user?.Manager?.PersonNumber
};
回答3
我的评论错了(并删除了它),但它让我思考;因为您可能想向“当结果为空时创建这个新对象”添加更多逻辑,所以您可以执行以下“伪代码”之类的操作(它可以编译,但它只是测试代码)
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; }
}