【问题标题】:Entity Framework Core 1.1.0 Data type conversionEntity Framework Core 1.1.0 数据类型转换
【发布时间】:2016-12-09 02:08:01
【问题描述】:

我有一个旧数据库,将用户 cmets(以及许多其他文本字段)存储为 blob 数据类型,我无法更改。

我正在编写一个数据访问层,它需要在从数据库中检索数据时始终将数据转换为string,并在保存时将其转换回blob

EF 脚手架工具为这些实体生成了byte[] 数据类型的属性。

public byte[] Comment { get; set; }

我注意到,如果我只是将实体属性类型更改为string,它实际上确实可以正确保存数据,但加载数据会导致转换错误:

无法将“System.Byte[]”类型的对象转换为“System.String”类型。

(有趣的是,版本 1.0.0 没有抛出这个错误,加载和保存工作正常。)

我的问题是...... 有没有办法配置 EF 核心,以便在我从数据库中检索这些数据时自动将其转换为字符串,并在保存回来时自动将其转换回 blob?还是我需要编写一大堆私有的 getter 和 setter 来进行这种操作?

【问题讨论】:

  • byte[] 是与string 完全不同的数据类型。将byte[] 转换为string 取决于编码,... EF 无法为您完成。最佳做法是将其保留为 byte[] 并编写一个 getter 来返回字符串表示形式,例如 public string MyString { get { return Encoding.UTF8.GetString(MyBytes); } }
  • 我认为在github.com/aspnet/EntityFramework/issues/242 实现之前,最好的选择是伙伴属性。

标签: c# entity-framework-core


【解决方案1】:

除了我对您的回答的评论之外,如果您不想添加 getter 和 setter 并希望拥有干净的代码,您还可以使用扩展方法:

public static class Extensions
{
    public static byte[] GetBytes(this string @this, System.Text.Encoding encoding = null)
    {
        return (encoding??Encoding.UTF8).GetBytes(@this);
    }

    public static string GetString(this byte[] @this, System.Text.Encoding encoding = null)
    {
        return (encoding??Encoding.UTF8).GetString(@this);
    }
}

您可以通过这两种方式使用它们:

myentity.Comment = "my comment".GetBytes();
string comment = myentity.Comment.GetString();

注意代码中的default-value,即UTF8,你可以把它改成你想要使用的编码,或者输入另一个编码,比如

byte[] myBytes = "my comment".GetBytes(Encoding.ASCII);

您的胜利:您不必使用 byte[] 为每个属性指定 getter/setter

【讨论】:

  • 感谢您的解决方案。虽然当前的两个答案都将有效地帮助解决这个问题,但我选择它作为接受的答案纯粹是因为它最适合我的特定要求。希望 EF Core 团队能尽快实现这个github.com/aspnet/EntityFramework/issues/242
【解决方案2】:

byte[] 转换为string 总是需要Encoding。由于 EF 不知道使用哪种编码,因此无法进行这种自动转换。

可以做的是将您的 Comment 属性标记为私有并创建一个包装器属性,该属性将值转换为带有您选择的 Encoding 的字符串:

partial class MyEntity
{
    private string m_commentText = null;
    public string CommentText
    {
        get {
            if ((m_commentText == null) && (Comment != null)) {
                m_commentText = Encoding.UTF8.GetString(Comment);      
            }
            return m_commentText;
        }
        set {
            m_commentText = value;
            if (value != null) {
                Comment = Encoding.UTF8.GetBytes(value);
            }
            else {
                Comment = null;
            }
        }
    }
}

此解决方案将文本存储在支持字段中,以避免从byte[]string 的多次转换。如果您需要 Comment 属性保持公开,则需要删除 backer 字段以避免数据不一致:

partial class MyEntity
{
    public string CommentText
    {
        get {
            if (Comment != null) {
                return Encoding.UTF8.GetString(Comment);      
            }
            else {
                return null;
            }
        }
        set {
            if (value != null) {
                Comment = Encoding.UTF8.GetBytes(value);
            }
            else {
                Comment = null;
            }
        }
    }
}

【讨论】:

  • 可以在实体中指定byte[] Comment-property 让它更清晰一些
  • 是的,我会,但那部分是自动生成的。指定自动生成的属性没有多大意义。这就是为什么包含partial
  • 啊,我明白了,所以也许可以添加到您的答案中,生成的类也必须是 partial。或者生成的总是一个部分类?我不知道 EF 脚手架工具会生成什么 ;)
  • @MatthiasBurger:EF 始终将实体生成为部分类以允许您的自定义扩展。
  • @Sefe:感谢非常有用的 cmets 和答案。此解决方案会导致 EF 期望 CommentText 作为数据库字段的问题。即使这是可以修复的,对于我的特定场景,额外的 getter 和 setter 也需要大量的工作来实现。
猜你喜欢
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
相关资源
最近更新 更多