2

I have my database context class as below

public class DataContext : DbContext
{
    public DataContext(DbContextOptions options) : base(options) 
    {
    }
    
    public DbSet<Customer> Customers;
    public DbSet<Order> Orders;
}

it warns saying

non-nullable property 'Orders' must contain a non-null value when exiting the constructor. Consider declaring the property as nullable

I have two options in hand to resolve but not sure which is good.

Option 1) make the property as nullable

public DbSet<Order>? Orders;

Option 2) set the property to empty set in constructor

public DataContext(DbContextOptions options) : base(options) 
    {
        this.Orders =  this.Set<Order>();
    }

Which one is the best option to resolve this warning and which also support test cases. ?

EagerToLearn
  • 89
  • 12
  • 1
    Does this answer your question? [How can I hint the C# 8.0 nullable reference system that a property is initalized using reflection](https://stackoverflow.com/questions/57342964/how-can-i-hint-the-c-sharp-8-0-nullable-reference-system-that-a-property-is-init) – gunr2171 Apr 04 '22 at 18:22
  • Take note that `Customers` and `Orders` need to be properties (with `{ get; set; }`), as shown in the linked answer. If it's not a property, it won't be initialized by EF. – madreflection Apr 04 '22 at 18:28

2 Answers2

6

Because a DbSet<T> is (for all practical purposes) guaranteed to be populated by EF once you create a context, you can set it to null! without changing the actual type:

    public DbSet<Customer> Customers {get;set;} = null!;
    public DbSet<Order> Orders {get;set;} = null!;

This will satisfy the non-nullable requirements without also upsetting EF.

null! is essentially a way of telling the compiler "I know you think this is going to be null, but I know better and know it won't be null by the time I need it - so don't warn me about it."

PhonicUK
  • 13,486
  • 4
  • 43
  • 62
3

Starting with C#11 (.NET 7) one can use the required modifier to mark that a property needs to be set by an object initializer. Since we don't manually instance the DbContext, we can therefore use it in this case:

public required DbSet<Customer> Customers {get;set;}
public required DbSet<Order> Orders {get;set;}

Edit: another option according to Microsoft is:

public DbSet<Customer> Customers => Set<Customer>();
public DbSet<Order> Orders => Set<Orders>()
Stephan
  • 2,028
  • 16
  • 19
  • But when you do it on a DbContext, it emits an error: error CS9035: Required member 'xxx' must be set in the object initializer or attribute constructor. – laorient Apr 30 '23 at 17:00
  • I guess you didn't forget about the constructor (delegating to `base`)? But there's anyway the second method which you could try. – Stephan May 01 '23 at 00:52