我在一个C# Core3.0项目上启用了.NET 8.0可空引用类型。该项目使用实体框架核心3.0访问数据库。
以下是标题不应为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
构造函数的存在只是为了允许实体框架核心和(可能的)序列化将值从数据库绑定到这些类/模型。公共构造函数可能具有与模型所具有的属性不同的结构、列表和参数类型(例如,它还可能包含第一个所需子元素的参数,它可能有一些参数可选等等)。
但是,编译器在CS8618 Non-nullable field is uninitialized. Consider declaring as nullable.
构造函数上生成private
。
我可以通过CS8616为private
构造函数禁用#pragma warning disable CS8618
,但我认为这不是一个好主意。
如何在此场景中使用C# 8.0可空引用类型?或者我的模型是假的还是违反了最佳实践--如何正确地做到这一点?
不幸的是,我没有找到相关的文件或指导。
发布于 2019-10-02 01:51:18
没有正确的方法来处理不可空的导航属性。
发布于 2021-04-15 12:26:59
我同意你的观点--实用主义是丑陋的。相反,我会将null宽恕操作符分配给默认构造函数中的非空引用类型,如下所示:
private Vehicle()
{
Title = null!;
}
这比使用上述运算符内联初始化属性要干净得多,而且更有表现力,如下所示:
public string Title { get; private set; } = null!;
后一种解决方案是“我知道Title
不是空的,不管是什么情况”,这实际上否定了非空引用类型的好处,因为您失去了所有的设计时间检查。前者读为“我知道Title
在这个特定的场景中不是空的”,因此,如果您错过了赋值,编译器警告将继续在其他地方发出。
发布于 2019-10-02 02:35:56
当EF Core创建这些类型的实例(例如查询结果)时,它将首先调用默认的无参数构造函数,然后将每个属性设置为数据库中的值。但是,如果EF Core找到一个参数化构造函数,其参数名称和类型与映射属性的参数名称和类型相匹配,那么它将使用这些属性的值调用参数化构造函数,并且不会显式地设置每个属性。
也许值得创建一个具有这些属性所需参数的私有ctor,然后看看Framework是否会调用它并工作?
此外,禁用警告不是一个好主意,除非你完全100%的自信,它是可以禁用它。
https://stackoverflow.com/questions/58171942
复制相似问题