首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在实体框架核心模型中使用C# 8.0可空引用类型?

如何在实体框架核心模型中使用C# 8.0可空引用类型?
EN

Stack Overflow用户
提问于 2019-09-30 16:36:24
回答 3查看 10.7K关注 0票数 39

我在一个C# Core3.0项目上启用了.NET 8.0可空引用类型。该项目使用实体框架核心3.0访问数据库。

以下是标题不应为null的数据模型。

代码语言:javascript
代码运行次数:0
运行
复制
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可空引用类型?或者我的模型是假的还是违反了最佳实践--如何正确地做到这一点?

不幸的是,我没有找到相关的文件或指导。

EN

回答 3

Stack Overflow用户

发布于 2019-10-02 09:51:18

没有正确的方法来处理不可空的导航属性。

  1. 文档提出了两种方法,它们都不是类型安全的。使用支持字段并抛出InvalidOperationException。目前还不清楚它与什么都不做和拥有一个NullReferenceException有什么不同。
  2. 用空宽恕操作符来抑制它

正式文档链接:https://learn.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types#non-nullable-properties-and-initialization

票数 14
EN

Stack Overflow用户

发布于 2021-04-15 20:26:59

我同意你的观点--实用主义是丑陋的。相反,我会将null宽恕操作符分配给默认构造函数中的非空引用类型,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
private Vehicle() 
{
    Title = null!;
}

这比使用上述运算符内联初始化属性要干净得多,而且更有表现力,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
public string Title { get; private set; } = null!;

后一种解决方案是“我知道Title不是空的,不管是什么情况”,这实际上否定了非空引用类型的好处,因为您失去了所有的设计时间检查。前者读为“我知道Title在这个特定的场景中不是空的”,因此,如果您错过了赋值,编译器警告将继续在其他地方发出。

票数 8
EN

Stack Overflow用户

发布于 2019-10-02 10:35:56

来自带有构造函数的实体类型的MS文档

当EF Core创建这些类型的实例(例如查询结果)时,它将首先调用默认的无参数构造函数,然后将每个属性设置为数据库中的值。但是,如果EF Core找到一个参数化构造函数,其参数名称和类型与映射属性的参数名称和类型相匹配,那么它将使用这些属性的值调用参数化构造函数,并且不会显式地设置每个属性。

也许值得创建一个具有这些属性所需参数的私有ctor,然后看看Framework是否会调用它并工作?

此外,禁用警告不是一个好主意,除非你完全100%的自信,它是可以禁用它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58171942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档