Skip to content

Suppress warnings on uninitialized DbSet properties#26795

Merged
roji merged 4 commits intodotnet:mainfrom
roji:UninitializedDbSetSuppressor
Nov 26, 2021
Merged

Suppress warnings on uninitialized DbSet properties#26795
roji merged 4 commits intodotnet:mainfrom
roji:UninitializedDbSetSuppressor

Conversation

@roji
Copy link
Copy Markdown
Member

@roji roji commented Nov 22, 2021

Closes #21608

@roji roji requested a review from a team November 22, 2021 21:40
@roji roji force-pushed the UninitializedDbSetSuppressor branch from 8550edf to bcffe52 Compare November 22, 2021 21:53
@roji roji force-pushed the UninitializedDbSetSuppressor branch from bcffe52 to a0b2f87 Compare November 22, 2021 21:54
@roji
Copy link
Copy Markdown
Member Author

roji commented Nov 22, 2021

/cc @Youssef1313

private static readonly SuppressionDescriptor _suppressUninitializedDbSetRule = new(
id: "SPR1001",
suppressedDiagnosticId: "CS8618",
justification: "DbSet properties on DbContext subclasses are automatically populated by the DbContext constructor");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this being non-localized intentionally?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that nothing else in EF Core is localized at this point.

It's true we manage exception strings via resx, but those sometimes get reused (or asserted upon in tests). I'd rather extract these strings out based on need rather than proactively, though can do that if the team prefers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roji We have so far taken the approach that everything (possible) is localization ready. I'd prefer we keep doing that, but we can discuss with the team.

Comment on lines +73 to +87
static bool InheritsFrom(ITypeSymbol typeSymbol, ITypeSymbol baseTypeSymbol)
{
var baseType = typeSymbol.BaseType;
while (baseType is not null)
{
if (baseType.Equals(baseTypeSymbol, SymbolEqualityComparer.Default))
{
return true;
}

baseType = baseType.BaseType;
}

return false;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional to look at the full hierarchy, not only the parent?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - the user's DbContext type can be lower down the hierarchy, rather than directly extend DbContext. A good example is ASP.NET Identity, where user context types can extend IdentityDbContext, which itself extends DbContext. The moment DbContext is somewhere in the base type list, we know its constructor will get invoked, and therefore the DbSets will get populated.

@roji roji force-pushed the UninitializedDbSetSuppressor branch from 9def9d5 to da6b358 Compare November 23, 2021 09:11
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@roji roji force-pushed the UninitializedDbSetSuppressor branch from 5acc0e3 to c5f0ae7 Compare November 25, 2021 14:13
@roji
Copy link
Copy Markdown
Member Author

roji commented Nov 25, 2021

@ajcvickers you may want to give my localization commit a quick look.

Copy link
Copy Markdown
Contributor

@ajcvickers ajcvickers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

Copy link
Copy Markdown

@Bretttt Bretttt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roji Curious why this wasn't applied to get-only auto-properties. Feels like
public DbSet<Blog> Blogs { get; } is a very common thing - I've never had a reason to expose a setter on a DB set (it's not even instantiable other than via Set<T>()), and before get-only I would aways define them as private set.

@roji
Copy link
Copy Markdown
Member Author

roji commented Dec 1, 2025

@Bretttt because EF Itself doesn't automatically inject read-only DbSet properties with DbSet instances - it can't, since there's no setter. In other words, for writable DbSet properties, the warning is wrong since EF takes care of initialization behind the scenes; but for non-writable ones it does not, and so the warning is correct: you must initialize those properties yourself. Try it out yourself to see this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Write a DiagnosticSuppressor for CS8618 for DbSet properties

4 participants