【问题标题】:.Net Core 3 Entity Framework with Firebird database and charset none.Net Core 3 实体框架与 Firebird 数据库和字符集无
【发布时间】:2020-07-16 16:55:30
【问题描述】:

我有一个旧版 Firebird (2.5.9) 数据库,它是在没有字符集的情况下创建的,因为它是在生产中,所以所有数据都是使用 WIN1252 插入的。我正在迁移到 .Net Core,并使用 FirebirdSql.Data.FirebirdClient 作为提供者(在 .Net Framework 和 .Net Core 中)。

在 .Net Framework 和 EF 6 中,我只需在连接字符串中设置字符集 WIN1252。

在 .Net Core 3.1 中,连接字符串的字符集仅在读取时使用,因为我必须首先在代码中设置列类型,如下所示:

entity.Property(e => e.description).HasMaxLength(255).HasColumnType("VARCHAR(255) CHARACTER SET WIN1252");

使其以相同的编码保存字符串。

我现在面临的问题与所有查询参数似乎都使用 UTF8 的事实有关,这是 .Net Core 中新的默认编码,并且一些特殊字符当然是不同的。

因此,例如,假设我在字段 description 中有一条带有重音字符的记录,例如“èèè”。

以下查询检索失败:

string filter = "èèè";
Product p = context.Products.Where(x => x.description == filter).FirstOrDefault();

这个查询被翻译成:

SELECT "a"."product_id", ... , "a"."description"
FROM "products" AS "a"
WHERE "a"."description" = CAST(@__filter_0 AS VARCHAR(8191))

这种转换也发生在 .Net Framework 中,但像这样的查询在那里可以正常工作。

另外,如果有多个参数我会得到错误

Implementation limit exceeded. block size exceeds implementation restriction

这正是question 中描述的内容,即使那是在 EF5 和 .Net Framework 中。基本上,您似乎很容易达到 64k 的行大小限制,因为 VARCHAR(8191) 在字节方面将权重转换为 UTF8。

我确信一种解决方案是升级到使用 UTF8 编码的新数据库并正确编码所有数据,但目前我希望尽可能避免这种情况。另外我认为这不会解决块大小错误。

有没有办法让它像在 .Net Framework 中一样工作?

【问题讨论】:

  • Firebird 问题DNET-934将字符串值转换为 VARCHAR(8191) 导致“超出实施限制” 似乎与您所描述的有关。不确定这是否有助于提供我遇到的似乎切线相关的东西。
  • @ahsteele 是的,它与块大小限制有关。不幸的是,当我使用提供程序选项禁用强制转换时,需要调查许多新的“数据类型未知”错误
  • “连接字符串的字符集仅在阅读时使用”,这与我对 Firebird 有线协议的理解不符。我建议您在firebird-net-provider Google Group 上提问。
  • Firebird (2.5.9) database that was created with no charset - 你能编辑系统表并在其中追溯引入字符集吗?它可能还需要刷新更改,例如备份-恢复周期或制作使用propr charset连接的简单应用程序,然后在所有表上发出UPDATE T SET X=X, Y=Y, Z=Z(脚本可以使用这些系统表自动生成)
  • @MarkRotteveel 我在那里发帖,我会在这里分享我的发现。谢谢。

标签: c# .net-core entity-framework-core firebird firebird2.5


【解决方案1】:

我刚刚在firebird-net-provider Google Group 收到 Jiří Činčura 的答复

.Net Framework 和 .Net Core 行为不同背后的原因实际上是由于 .Net Core (UTF8) 的默认编码。

我的数据库将 column 字符集设置为无。所以发生的情况是,即使你这样设置列类型:

.HasColumnType("VARCHAR(255) CHARACTER SET WIN1252");

提供者总是使用数据库中的列字符集 比较值时。 这意味着如果您首先在代码中设置列类型,您只需修复字符串保存,但当提供者需要比较值时,他会检查数据库中的列配置。

因此解决方案是正确定义/修复列/数据库上的字符集并检查/复制数据。

就个人而言,我没有在所有列上强制使用 WIN1252 字符集,而是继续将整个数据库转换为 UTF8,这样,即使我将列字符集保持为无,字符串也已经保存在相同的 .Net Core 默认值中编码,它也是未来的证明。

行大小限制问题在某种程度上是无关的,它只是在您开始使用 UTF8 时会发生的事情。幸运的是,您可以在上下文配置中设置此选项

new FbDbContextOptionsBuilder(optionsBuilder).WithExplicitParameterTypes(false);

以减少那些 varchar 强制转换。

其他信息

为了转换数据库,我使用了 fbclone,因为它可以克隆一个数据库,使用相同的结构将数据从一个数据库泵送到另一个数据库,同时处理不同的字符集。

此外,您可能需要检查您的索引,因为在 Firebird 2.x 中,最大大小是页面大小 (source) 的四分之一,并且 UTF8 中的字符串在内部存储为 4 个字节/字符,所以如果您来自像我这样的WIN1252(1字节/字符)你可以轻松达到这个限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多