How should string
nullability be handled in EF8? Should I use the required
keyword? Also should I choose set;
over init;
? I remember there were some issues with init;
in .NET 6.
public class LegalEntity : BaseAuditableEntity<Guid>
{
// This is required by EF Core when there is another ctor with parameters that we need to pass
[UsedImplicitly]
private LegalEntity()
{
}
// TODO: Add ctor with couple of parameters
// TODO: How are we supposed to handle string nullability in .NET 8 and EF Core?
// TODO: Should we use init instead?
// https://learn.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types
public required string EntityType { get; set; }
public required string Name { get; set; }
public required string ShortName { get; set; }
public required string RegistrationNumber { get; set; }
public DateTime? DateOfIncorporation { get; set; }
public required string StreetAddress { get; set; }
public required string City { get; set; }
public required string State { get; set; }
public required string PostalCode { get; set; }
public required string Country { get; set; }
}
public class LegalEntityEfConfiguration : IEntityTypeConfiguration<LegalEntity>
{
public void Configure(EntityTypeBuilder<LegalEntity> builder)
{
builder.HasKey(x => x.Id);
builder.Property(x => x.Id).ValueGeneratedOnAdd();
builder.Property(x => x.EntityType).IsRequired().HasMaxLength(50);
builder.Property(x => x.Name).IsRequired().HasMaxLength(255);
builder.Property(x => x.ShortName).HasMaxLength(100);
builder.Property(x => x.RegistrationNumber).HasMaxLength(100);
builder.Property(x => x.StreetAddress).HasMaxLength(255);
builder.Property(x => x.City).HasMaxLength(100);
builder.Property(x => x.State).HasMaxLength(100);
builder.Property(x => x.PostalCode).HasMaxLength(20);
builder.Property(x => x.Country).HasMaxLength(100);
}
}
public abstract class BaseAuditableEntity<TId> : BaseEntity<TId>
where TId : struct
{
public DateTimeOffset CreatedAt { get; set; }
public string? CreatedBy { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
public string? UpdatedBy { get; set; }
}
public abstract class BaseEntity<TId>
where TId : struct
{
public TId Id { get; set; }
private readonly List<BaseEvent> _domainEvents = [];
[NotMapped]
public IReadOnlyCollection<BaseEvent> DomainEvents => _domainEvents.AsReadOnly();
public void AddDomainEvent(BaseEvent domainEvent) => _domainEvents.Add(domainEvent);
public void RemoveDomainEvent(BaseEvent domainEvent) => _domainEvents.Remove(domainEvent);
public void ClearDomainEvents() => _domainEvents.Clear();
}
1
You could use required
to set non-nullable properties during initialization.
Here is the sample:
public required string EntityType { get; set; }
public required string Name { get; set; }
public string? RegistrationNumber { get; set; } // Optional property
-
Use
init;
allows you to assign values to read-only properties only during the initialization of the object. We can use this feature to create immutable objects that require a specific set of values during their creation, and those values should remain unchanged during the object’s lifetime.You can call the
init
accessors only during object creation. -
Use
set;
if the property might need to be modified after the object is constructed.
When working with EF Core, which depends on property setters during data loading and updates, it’s better to use set;
for properties that will be updated by the framework.
e.g:
public required string EntityType { get; set; } // Allows updates
Here is the document you can refer to:
Nullable Reference Types in EF Core