EF Core 压缩解压列

10
作为示例,假设有一个简单的 POCO 类型,包含一个名为 data 的字符串属性和一个 ID 属性。
使用 EF Core 保存实体之前,最好的方法是调用 COMPRESS(data) 函数来压缩数据,并在加载时调用 DECOMPRESS(data) 函数。相应地,数据库列的类型应该是 VARBINARY。
实现这个功能的自定义 SQL 示例如下:
SELECT Id, DECOMPRESS(@Data) as [Data]
FROM table

选择实体的方式是使用类似于此的语法,插入实体的方式是使用以下格式:
INSERT INTO table
VALUES(@Id, COMPRESS(@Data))

注:

这是SQL Server。

当前字符串长度可以达到几千个字符,因此在数据库方面使用PAGE或ROW压缩的定长NVARCHAR不是一个选择。


1
你可以尝试使用转换,但这样你就必须使用C#代码进行压缩/解压,而不是使用SQL Server方法。 - Preben Huybrechts
我考虑过那个选项,同样地,在存储值之前,我可以简单地压缩它,但是由于SQL Server有一个压缩和解压缩的选项,我想知道是否有一种方法来配置EF Core。 - Raul
投票关闭此问题的人,请问这个问题中到底有什么不清楚的地方? - Raul
你可以在转换中调用 SELECT COMPRESS(@Data),但我不建议这样做。因为这会导致性能问题。其他选项是创建一个视图来查询解压缩的数据和一个存储过程来插入/更新压缩的数据。 - Preben Huybrechts
看一下这个。可能会有帮助 https://stackoverflow.com/a/31727711/5817136 - Iman
1个回答

11

使用转换似乎是最佳方法。因为越早压缩数据,生成的网络I/O就越少。另外压缩会消耗宝贵的SQL服务器CPU周期,并可能影响SQL服务器的性能。

public class YourEntityTypeConfigruation : IEntityTypeConfiguration<YourEntity>
{
    public void Configure(EntityTypeBuilder<YourEntity> builder)
    {
        builder.Property(e => e.Data)
            .HasConversion(
                v => Zip(v),
                v => Unzip(v));
    }
    
    public static void CopyTo(Stream src, Stream dest) {
        byte[] bytes = new byte[4096];

        int cnt;

        while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
            dest.Write(bytes, 0, cnt);
        }
    }

    public static byte[] Zip(string str) {
        var bytes = Encoding.UTF8.GetBytes(str);

        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream()) {
            using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
                //msi.CopyTo(gs);
                CopyTo(msi, gs);
            }

            return mso.ToArray();
        }
    }

    public static string Unzip(byte[] bytes) {
        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream()) {
            using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
                //gs.CopyTo(mso);
                CopyTo(gs, mso);
            }

            return Encoding.UTF8.GetString(mso.ToArray());
        }
    }
}

当您创建视图时,可以使用SQL server方法,例如

CREATE VIEW MyView
AS
SELECT Id, DECOMPRESS(Data) as [Data]
FROM table

并在EF上下文中映射它。

对于插入/更新操作,您需要使用存储过程来压缩数据。这违背了使用实体框架跟踪实体更改的目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接