将非必需字符串属性从null水合为空字符串



如果我有一个模型类

public class Foo
{
    public string Property1 { get; set; } = string.Empty;
    ... other properties omitted for brevity
}

由于它不是必需的属性,因此它将以null形式保存到数据库中。但现在,当我检索实体时,该属性为null。我在这个实体上有很多不需要的字符串属性,我不想对这些属性进行大量的null检查,我只希望它们在数据库中为null时被重新水化为空字符串。我不介意它们以null的形式存储在数据库中,但当从数据库中检索实体时,如果它在数据库中为null,我希望将其映射回空字符串。

我想这一定是一个相当常见的场景,我想知道我是否错过了一些简单的方法来使用配置设置或其他东西。我对EF的使用相当陌生。

在我的OnModelCreating中,我有:

.HasMaxLength(50)
.HasDefaultValue(string.Empty)

但它仍然被存储为null,并被重新水合为null。同样,我不介意它被存储为null,但如果它在数据库中为null,我希望它被水合为空字符串。

我试着这样修改模型类:

private string property1 = string.empty;
public string Property1
{
    get { return property1; }
    set { property1 = value ?? string.Empty; }
} 

认为EF必须使用setter,但这仍然导致了null属性。到目前为止,我唯一能解决这个问题的方法是制作这样的属性:

private string property1 = string.empty;
public string Property1
{
    get { return property1 ?? string.empty; }
    set { property1 = value ?? string.Empty; }
} 

我真的不想让我所有的财产都变成那样。

有人能建议一种更干净的方法来做这件事吗?或者,如果我做错了什么、不寻常了或者想错了,有人能纠正我吗。我是不是错过了一些更简单的方法来实现这一点?

我不想使属性成为必需的,因为空字符串也不能满足这种情况。

问题的原始实体框架版本是EF7,这是第一个后来更名为ef核心1的ef核心版本。所描述的行为与当前EF核心版本(2.1.1)有很大不同

让我提一下两个关键点:

1

由于它不是必需的属性,因此它将以null形式保存到数据库中。但现在,当我检索实体时,该属性为null。

目前情况并非如此。

举个简单的例子:

public class Item
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Code { get; set; } = string.Empty;
}

当添加仅设置了NameItem时,将执行以下SQL:

exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Items] ([Code], [Name])
VALUES (@p0, @p1);
SELECT [ID]
FROM [Items]
WHERE @@ROWCOUNT = 1 AND [ID] = scope_identity();
',N'@p0 nvarchar(4000),@p1 nvarchar(50)',@p0=N'',@p1=N'Item1'

空字符串是插入语句的一部分。此外,当从数据库中检索项目时,其Code是一个空字符串。

2

在我的OnModelCreating中,我有:

.HasMaxLength(50)
.HasDefaultValue(string.Empty)

但它仍然被存储为null,并被重新水合为null。

现在情况也不一样了。参加相同的课程,但现在有:

    public string Code { get; set; }  // removed "= string.Empty;"

以及Code:的映射

modelBuilder.Entity<Item>().Property(p => p.Code).HasMaxLength(50).HasDefaultValue(string.Empty);

那么这就是结果表:

CREATE TABLE [Items] (
    [ID] int NOT NULL IDENTITY,
    [Name] nvarchar(50) NOT NULL,
    [Code] nvarchar(50) NULL DEFAULT N'', -- Default constraint
    CONSTRAINT [PK_Items] PRIMARY KEY ([ID])
);

正如您所看到的,映射指令被转换为数据库默认值。

当添加仅设置了NameItem时,将执行以下SQL:

exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Items] ([Name])
VALUES (@p0);
SELECT [ID], [Code]
FROM [Items]
WHERE @@ROWCOUNT = 1 AND [ID] = scope_identity();
',N'@p0 nvarchar(50)',@p0=N'Item1'

因此EF插入项目并读回生成的默认值,以便使被跟踪的实体与数据库保持同步。同样,稍后从数据库中读取的项目在Code中有一个空字符串。

这些发现证实了EF7是EF核心的一个非常不成熟的版本(尽管我没有证实它真的表现出所描述的行为)。从那以后,发生了更多、更深刻的突破性变化。我希望我们很快就会忘记这些早期的EF核心版本。从2.0版本开始,EF核心终于发展成为可生产的ORM。

最新更新