使用 SqlFileStream 在 SQL Server 中序列化和存储大对象

发布于 2025-01-01 16:23:52 字数 2913 浏览 1 评论 0原文

我正在使用 SqlFileStream 将我的(大)对象存储在 SQL Server 上(在 varbinary(max) 列中),但我无法真正得到它做我想做的事。我一直在尝试找到一些专门针对序列化和存储(不仅仅是从磁盘读取文件进行存储)的文章以及如何最有效地做到这一点。是否有一些我尚未找到的“隐藏”最佳实践文章?或者有人有一个很好的例子来说明如何做到这一点?

我的主要来源是 使用 SqlFileStream 与 C# 访问 SQL Server FILESTREAM 数据

编辑:

添加了示例代码,其中对象 DataObject 必须使用以下方式存储在 SQL Server 表中:文件流。我希望可以将我的对象流式传输到数据库中,但我目前不知道如何以最好的方式进行此操作,我需要对对象做什么才能流式传输它,并记住该对象可以>1 GB,其中结构非常复杂。

新编辑: 我已经用包含很少数据<300 kb 的数据结构对其进行了测试,没有任何问题。然后我在想这是否是缓冲区问题或类似问题?

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Transactions;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data;

namespace QEStore
{
    public class DataObject
    {
        private Dictionary<int, string> _values = new Dictionary<int, string>();
        private string _objName;
    }

    public class Store
    {
        private string _connStr = "Data Source=127.0.0.1;Integrated Security=True;Initial Catalog=my_data;";

        public void InsertObject(int id, DataObject data)
        {
            var insStmt =
                @"insert into data (data_id) values (@dataID);
                  select data_value.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() from data where data_id = @dataID;";

            string serverPath;
            byte[] serverTxn;

            using (var ts = new TransactionScope())
            {
                using (var conn = new SqlConnection(this._connStr))
                {
                    conn.Open();
                    using (var cmd = new SqlCommand(insStmt, conn))
                    {
                        cmd.Parameters.Add("@dataID", SqlDbType.Int).Value = id;
                        using (var reader = cmd.ExecuteReader())
                        {
                            reader.Read();
                            serverPath = reader.GetSqlString(0).Value;
                            serverTxn = reader.GetSqlBinary(1).Value;
                            reader.Close();
                        }
                    }
                    using (var dest = new SqlFileStream(serverPath, serverTxn, FileAccess.Write))
                    {
                        // How to write the DataObject to the database using SqlFileStream
                        // dest.Write(...);
                    }
                }
                ts.Complete();
            }
        }
    }
}

我尝试按如下方式序列化对象,但收到 IOException 错误,指出“句柄无效”:

using (var dest = new SqlFileStream(serverPath, serverTxn, FileAccess.Write))
{
    var formatter = new BinaryFormatter();
    formatter.Serialize(dest, data);
    dest.Close();
}

I am playing with theSqlFileStream to store my (large) objects on a SQL Server (in a varbinary(max) column), but i can't really get a it to do as i want to. I have been trying to find some articles specific for serializing and storing (not just reading files from disk to store) and how to do this most efficiently. Is there some "hidden" best practice articles that I just haven't found yet? Or do someone have a nice example of how to do this?

My primary source is Using SqlFileStream with C# to Access SQL Server FILESTREAM Data

Edit:

Added example code, where the object DataObject must be stored in a SQL Server table using filestream. I expect that it would be possible to stream my object, into the database but i currently don't know how to this in the best way, what do i need to do to the object to stream it and have in mind that the object can be >1 GB with very complex structures in it.

New edit:
I have tested it with data structures containing very little data <300 kb and there are no problems. Then i'm thinking if it is a buffer problem or similar?

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Transactions;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data;

namespace QEStore
{
    public class DataObject
    {
        private Dictionary<int, string> _values = new Dictionary<int, string>();
        private string _objName;
    }

    public class Store
    {
        private string _connStr = "Data Source=127.0.0.1;Integrated Security=True;Initial Catalog=my_data;";

        public void InsertObject(int id, DataObject data)
        {
            var insStmt =
                @"insert into data (data_id) values (@dataID);
                  select data_value.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() from data where data_id = @dataID;";

            string serverPath;
            byte[] serverTxn;

            using (var ts = new TransactionScope())
            {
                using (var conn = new SqlConnection(this._connStr))
                {
                    conn.Open();
                    using (var cmd = new SqlCommand(insStmt, conn))
                    {
                        cmd.Parameters.Add("@dataID", SqlDbType.Int).Value = id;
                        using (var reader = cmd.ExecuteReader())
                        {
                            reader.Read();
                            serverPath = reader.GetSqlString(0).Value;
                            serverTxn = reader.GetSqlBinary(1).Value;
                            reader.Close();
                        }
                    }
                    using (var dest = new SqlFileStream(serverPath, serverTxn, FileAccess.Write))
                    {
                        // How to write the DataObject to the database using SqlFileStream
                        // dest.Write(...);
                    }
                }
                ts.Complete();
            }
        }
    }
}

I have tried serializing the object as following, but get an IOException error saying "The handle is invalid":

using (var dest = new SqlFileStream(serverPath, serverTxn, FileAccess.Write))
{
    var formatter = new BinaryFormatter();
    formatter.Serialize(dest, data);
    dest.Close();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

楠木可依 2025-01-08 16:23:52

我发现了问题。问题是内置序列化器无法使用 protobuf-net< 处理大数据对象/a> 相反有效。

I found the problem. The problem was that the build-in serializer could not handle the large data object, using protobuf-net instead worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文