question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Getting started with NRT exposes confusing behaviour.

See original GitHub issue

I’m learning to use EF rather than using direct ADO so I’ve started a new NET6 project with EFCore and am using. I’m working through getting the basic things I need but I’m finding that there are some confusing things for beginners that could be improved on.

I’ve started with a very basic context and added a set property. NRT are enabled and I want the property to be non-null but if I don’t assign to the property in the ctor i’ll get a complier warning in the ctor and as a good developer I want to ensure my code builds without warning or suppressions. So how do I make it work? The usual way to do this would simply be to set it in the ctor Entities = null!;, this is wrong. To know that is wrong you have to know that EF is going to set the property in the parameterless ctor so in the second ctor the property is already initialized. If you’re not aware of this implementation detail the null assignment will break the property.

I asked about this on the c# discord and Reacher there patiently explained to me and provided the accepted patterns to work around it, those being:

  1. to use { get; set; } = new DbSet<Named>() (or now possibly target typed new()). This feels a little strange that I need to setup the collection myself and could get unwieldy for complex or immutable collection types. It’s also not what the docs tell you do do, they leave it as a pure auto property without initialization.
  2. to use { get; init; } = null!. This just looks wrong because i’m creating an init only property and setting it to null in order to explain the the compiler that the property will never be null. All the code I can see tells me it will be null, at runtime it will not be. I didn’t see this pattern in the docs, it’s probably there but I haven’t hit the page that explains it yet.

I’ve worked through the docs and pretty early fallen into a pit (well, a pothole) of failure. There might be something that can be improved on here.

using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.Diagnostics;

using (var context = new DatabaseContext())
{
	context.Database.EnsureCreated();
	Debug.Assert(context.Entities != null);
}

public class DatabaseContext : DbContext
{
	public DatabaseContext()
		: this("datbase.db")
	{
	}
	public DatabaseContext(string databaseFilePath)
	{
		DatabaseFilePath = databaseFilePath ?? throw new ArgumentNullException(databaseFilePath);
		// Entities = null!; // uncomment this assignment for failure
	}

	public string DatabaseFilePath { get; init; }

	public DbSet<Named> Entities { get; set; }

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Entity<Named>().HasKey(nameof(Named.Name));
	}

	protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
	{
		SqliteConnectionStringBuilder connectionBuilder = new SqliteConnectionStringBuilder();
		connectionBuilder.DataSource = DatabaseFilePath;
		connectionBuilder.Mode = SqliteOpenMode.ReadWriteCreate;
		optionsBuilder.UseSqlite(connectionBuilder.ConnectionString);
	}
}

public class Named
{
	public string? Name { get; set; }
}

Include provider and version information

EF Core version: 6.0 Database provider:Microsoft.EntityFrameworkCore.SqlLite Target framework: NET 6.0 Operating system: IDE: vs 2022

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
ajcvickerscommented, Dec 1, 2021

@Wraith2 Personally, I’m a fan of

public DbSet<Named> Entities => Set<Named>();

The DbSet object is cached anyway, so this is functionally the same as initializing all the sets in the constructor. I don’t think we would ever have done the auto-initialization stuff had this syntax been available in 2010.

1reaction
stevendarbycommented, Dec 1, 2021

I know this is probably obvious but sometimes simple things can get obscured: DbSet<T> properties aren’t required and you can always just use Set<T>(). I’m not trying to convince anyone not to use the convenience properties, just wanted to say that among all the options there are around getting them to play nicely with NRT, one option is not to have them at all.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nicotine Replacement Therapy to Help You Quit Tobacco
Nicotine Replacement Therapy (NRT) provides the nicotine without the other harmful chemicals you get when using other forms of tobacco.
Read more >
Nicotine replacement therapy versus control for smoking ...
Background. Nicotine replacement therapy (NRT) aims to temporarily replace much of the nicotine from cigarettes to reduce motivation to smoke and nicotine ...
Read more >
Preloading - wearing a nicotine patch for four weeks before ...
Nicotine preloading means using nicotine replacement therapy (NRT), usually a nicotine patch, while continuing to smoke normally in the 2-4 weeks leading up ......
Read more >
A Randomized Trial of E-Cigarettes versus Nicotine ...
Conclusions. E-cigarettes were more effective for smoking cessation than nicotine-replacement therapy, when both products were accompanied by ...
Read more >
Nicotine replacement therapy
Nicotine replacement therapy (NRT) is a medically approved way to treat people with tobacco use disorder by taking nicotine through means other than...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found