我创建了一个服务,以一对一的关系从数据库中检索用户,所以我有这个
ApplicationUser
类
public class ApplicationUser
{
public required int Id { get; set; }
public required string Username { get; set; }
public required string ProfilePicture { get; set; }
public DateTime Created { get; set; } = DateTime.Now;
public UserProfile? Profile { get; set; }
}
这就是服务功能
public async Task<ApplicationUser?> GetByUserIdAsync(int userId, bool includeProfile = false)
{
IQueryable<ApplicationUser> query = _dbContext.Users;
if (includeProfile)
{
query.Include(u => u.Profile);
}
return await query.FirstOrDefaultAsync(u => u.Id == userId);
}
如您所见,我添加了一个参数
includeProfile
,这样当我还需要用户配置文件时,我可以告诉函数包含它。
问题在于返回类型。由于
ApplicationUser.Profile
可为空,因此当我在代码中访问该属性时,即使我将 true
传递给 includeProfile
,我也会收到警告,指出 Profile
可能为空。
所以我的问题是:如何做到当
includeProfile
为 true 时,ApplicationUser.Profile
不为空?
通常不鼓励使用布尔参数,因为方法调用的可读性较差。考虑一下这两个调用:
var user1 = GetByUserIdAsync(5, true);
var user2 = GetByUserIdAsync(5, false);
作为一名开发人员,阅读这两行代码,如果不研究
GetByUserIdAsync
的实现方式,就不可能区分它们的作用。
相反,我建议您为每个操作添加一个方法和一个数据类型,以更清楚地说明差异(我不知道您的系统的详细信息,因此您可能有更好的名称):
// Data types
public class ApplicationUser
{
public required int Id { get; set; }
public required string Username { get; set; }
public required string ProfilePicture { get; set; }
public DateTime Created { get; set; } = DateTime.Now;
}
public class UserDetails : ApplicationUser
{
public UserProfile Profile { get; set; }
}
// Methods
public async Task<ApplicationUser?> GetByUserIdAsync(int userId)
{
return await _dbContext.Users
.FirstOrDefaultAsync(u => u.Id == userId);
}
public async Task<UserDetails?> GetDetailsByUserIdAsync(int userId)
{
return await _dbContext.Users
.Include(u => u.Profile)
.FirstOrDefaultAsync(u => u.Id == userId);
}
现在,从类的名称以及方法的名称中可以更清楚地了解它们所包含的内容。同时,您消除了 if 语句,降低了复杂性(当然,这并不是一个复杂的方法)。