【发布时间】:2021-11-12 07:46:01
【问题描述】:
我有一个内部域,它有一个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]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略该属性。
有人知道为什么我的转换器做错了吗?
补充:当我在 lambda 语句中放置断点时,断点永远不会被命中。
我还尝试直接注册 lambda:...HasConversion(domainValue => string.IsNullOrWhiteSpace(domainValue) ? null : domainValue, databaseValue => databaseValue ?? string.Empty);,这与第一次注册的结果相同。
【问题讨论】:
-
这是一个糟糕的想法。空字符串绝对是 NOT null。它有一个非常具体的值,即空字符串。在 SQL 和 .NET 中,这两者完全不同。在 SQL 中,您不能按值搜索空值(您可以对空字符串执行此操作),因此将空字符串转换为 NULL 会中断查询。你必须写
.Where(p=>p.ThatField == null)而不是.Where(=>p.ThatField = "") -
备注字段不是可搜索字段。我需要这样做的原因是为了保持域正确并且架构师希望数据库尽可能小(已经有很多巨大的数据库),因此不应将空字符串持久化到数据库。
-
架构师应该知道这是一个坏主意,节省的成本可以忽略不计。如果您真的关心空间,请使用表压缩。这在所有受支持的 SQL Server 版本和版本中都可用,甚至是 Express 和 LocalDB。您将最终提高性能,因为 IO 将减少。如果您有用于报告的大型表,columstore 聚集索引也会减少存储(并提高性能)
标签: c# entity-framework .net-core