我有我的内部域,它有一个string
属性注释。在我的数据库中,我想将空string
存储为NULL
,当我从数据库加载NULL
时,我希望这是一个空string
。
我想我会创建一个ValueConverter
并注册它,就是这样。
public class StringEmptyToNullConverter : ValueConverter<string, string>
{
public StringEmptyToNullConverter() : base(ToDatabaseValue, ToDomainValue) {}
private static readonly Expression<Func<string, string>> ToDatabaseValue =
domainValue => string.IsNullOrWhiteSpace(domainValue) ? null : domainValue;
private static readonly Expression<Func<string, string>> ToDomainValue = databaseValue =>
databaseValue ?? string.Empty;
}
在我的上下文配置中,我将其注册为builder.Property(x => x.Remark).HasConversion(new StringEmptyToNullConverter());
,它仍然在数据库中存储一个空string
或给我一个NULL
值。基本上,这会被忽略。
或者我将其注册为builder.Property(x => x.Opmerking).HasConversion<StringEmptyToNullConverter>();
,这会引发错误:
备注"的类型为"字符串",当前数据库提供程序不支持该属性。更改属性 CLR 类型,或使用"[NotMapped]"属性或使用"OnModelCreateating"中的"EntityTypeBuilder.Ignore"忽略该属性。
有谁知道为什么我在转换器中做错了什么?
另外:当我在 lambda 语句中放置断点时,永远不会命中断点。
我还尝试了非常谨慎地注册 lambda:...HasConversion(domainValue => string.IsNullOrWhiteSpace(domainValue) ? null : domainValue, databaseValue => databaseValue ?? string.Empty);
这与第一次注册的结果相同。
有两个问题阻止此操作。 鉴于:
modelBuilder.Entity<Customer>()
.Property(c => c.Name)
.HasConversion(
ev => ev==""?null:ev,
dv => dv==null?"":dv
);
首先,查询的值转换不会将谓词转换为is null
,它只是生成= null
,在标准SQL中,该在标准SQL中永远不会匹配任何行,因为null = null
计算结果为unknown
,例如
像这样的查询:
var q2 = from cust in db.Customers
where cust.Name == ""
select cust;
翻译为
SELECT [c].[Id], [c].[Name]
FROM [Customers] AS [c]
WHERE [c].[Name] = NULL
其次,值覆盖者无法将数据库中的 null 转换为 .NET 中的 ":
此外,值转换器通常不允许转换 null 到其他一些值。这是因为相同的值转换器可以是 用于可为空和不可为空的类型,这非常有用 对于 PK/FK 组合,其中 FK 通常可为空且 PK 为 不。我们将讨论是否添加对转换的支持 空值。
https://github.com/dotnet/efcore/issues/13850
这目前根本行不通。 因此,不想混合空字符串和 null(您不想),如果您希望实体和数据库之间的一致性,您唯一的选择是在两个位置都使用 null。