如何将 C# 8.0 可空引用类型与 Entity Framework Core 模型一起使用?
Posted
技术标签:
【中文标题】如何将 C# 8.0 可空引用类型与 Entity Framework Core 模型一起使用?【英文标题】:How to use C# 8.0 Nullable Reference Types with Entity Framework Core models? 【发布时间】:2020-01-29 23:41:52 【问题描述】:我在 .NET Core 3.0 项目上启用 C# 8.0 Nullable Reference Types。项目使用Entity Framework Core 3.0访问数据库。
下面是一个Title不能为null的数据模型。
public class Vehicle
public int Id get; private set;
public string Title get; private set;
// Entity Framework Core is instructed to bind to the private _drivers field in a configuration builder
private readonly List<Driver> _drivers = new List<Driver>();
public IReadOnlyCollection<Driver> Drivers => _drivers.AsReadOnly();
private Vehicle()
public Vehicle(string title)
this.Title = title;
public void AddDriver(string name)
this._drivers.Add(new Driver(name));
// A foreign column is defined in a configuration builder
public class Driver
public int Id get; private set;
public string Name get; private set;
private Driver()
public Driver(string name)
this.Name = name;
自己的代码应该只使用 public
构造函数,而 private
构造函数只是为了允许 Entity Framework Core 和(可能还有)序列化将值从数据库绑定到这些类/模型。公共构造函数可能具有与模型具有的属性不同的结构、列表和参数类型(例如,它可能还包含第一个必需子项的参数,它可能具有一些可选参数等)。
但是,编译器会在 private
构造函数上生成 CS8618 Non-nullable field is uninitialized. Consider declaring as nullable.
。
我可以通过 #pragma warning disable CS8618
为 private
构造函数禁用 CS8616,但我认为这不是一个好主意。
在这种情况下应该如何使用 C# 8.0 可空引用类型? 还是我的模型是伪造的或违反了最佳实践 - 如何正确执行?
很遗憾,我没有找到相关的文档或指南。
【问题讨论】:
docs.microsoft.com/en-us/ef/core/miscellaneous/… ? 【参考方案1】:没有适当的方法来处理不可为空的导航属性。
-
文档提出了两种方法,但都不是类型安全的。用一个
支持字段并抛出 InvalidOperationException。不清楚如何
它不同于什么都不做并且有一个 NullReferenceException
使用 null 宽恕运算符抑制它
官方文档链接:https://docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types#non-nullable-properties-and-initialization
【讨论】:
【参考方案2】:我同意你的看法——pragma 块很难看。相反,我会将 null 宽恕运算符分配给默认构造函数 inside 的不可为 null 的引用类型,如下所示:
private Vehicle()
Title = null!;
这比使用上述操作符内联初始化属性更简洁,更具表现力,如下所示:
public string Title get; private set; = null!;
后一种解决方案读作“我知道Title
在任何情况下都不为空”,这实际上否定了不可为空引用类型的好处,因为您丢失了所有设计时检查。前者读作“我知道Title
在此特定 场景中不为空”,因此如果您错过分配,编译器警告会继续在其他地方发出。
【讨论】:
您可能希望使用 default 关键字而不是 null。public string Title get; private set; = default!;
。这样,您可以对值类型遵循相同的模式。【参考方案3】:
来自MS Docs for Entity types with constructors
当 EF Core 创建这些类型的实例时,例如为结果 的查询,它会首先调用默认的无参数构造函数 然后将每个属性设置为数据库中的值。然而,如果 EF Core 找到一个带有参数名称的参数化构造函数,并且 匹配映射属性的类型,然后它将改为调用 具有这些属性的值的参数化构造函数和 不会显式设置每个属性。
也许值得创建一个带有这些属性所需参数的私有 ctor,然后看看框架是否会调用它并工作?
除非您完全 100% 确信可以禁用警告,否则禁用警告也不是一个好主意。
【讨论】:
以上是关于如何将 C# 8.0 可空引用类型与 Entity Framework Core 模型一起使用?的主要内容,如果未能解决你的问题,请参考以下文章