我正在使用值对象作为标识,并想知道如何最好地处理EF核心中的空值。
例如,如果我有一个具有可选头衔(先生、夫人等(的员工:
public class Employee
: Entity,
IAggregateRoot
{
public EmployeeTitleId TitleId { get; private set; }
public EmployeeFirstName FirstName { get; private set; }
public EmployeeSurname Surname { get; private set; }
...
}
我可以在我的代码中检查任何地方的空值,例如
if (employee.TitleId == null) ...
或者我可以使用默认值,例如
if (employee.TitleId.Equals(EmployeeTitleId.None)) ...
EmployeeTitleId
实现如下:
public class EmployeeTitleId
: Value<EmployeeTitleId>
{
public static readonly EmployeeTitleId None = new EmployeeTitleId();
protected EmployeeTitleId() { }
public EmployeeTitleId(Guid value)
{
if (value == default)
throw new ArgumentNullException(nameof(value), "Employee title id cannot be empty");
Value = value;
}
public Guid Value { get; internal set; }
public static implicit operator Guid(EmployeeTitleId self) => self.Value;
public static implicit operator EmployeeTitleId(string value)
=> new EmployeeTitleId(Guid.Parse(value));
public override string ToString() => Value.ToString();
}
我更喜欢第二种方法,因为它看起来更干净,但我不知道这是否矫枉过正。 它还需要在实体框架方面进行更多设置,例如:
builder.OwnsOne(_ => _.TitleId).Property(_ => _.Value)
.HasColumnName("TitleId").HasConversion(v => v == default ? (Guid?) null : v, v => v ?? EmployeeTitleId.None);
这似乎是一种可行的方法,还是我应该坚持检查 null? 如果是这样,是否有我可以在实体类型配置中使用的约定,以便我不必手动设置每个 HasConversion?
还有另一种方法可以全局过滤结果。您可以在OnModelCreating
中配置此项,如下所示:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// code omitted for brevity
modelBuilder.Entity<Employee>().HasQueryFilter(p => p.TitleId == null);
}