0

据我所知,自 2012 版以来 SQL Server 有一个新功能,FileTable. 它允许我们将文件存储在文件系统中并从 T-SQL 中使用它们。

我正在尝试使用此功能,但我不知道如何正确使用它。

通常,我不知道如何访问存储在文件表中的文件。假设我有 asp.net MVC 应用程序,并且我在网页上的 img 标签中显示了很多图像。我想将这些图像存储在 Filetable 中,并将它们作为文件系统中的文件进行访问。但我不知道这些文件存储在哪里以及如何将它们用作文件。现在我的图像存储在文件夹图像的网络应用程序目录中,我写了这样的东西:

<img src='/images/mypicture.png' />

如果我将图像移动到文件表中,我应该在 src 中写什么?

<img src='path-toimage-in-filetable' />
4

2 回答 2

2

我认为您仍然不需要这个,无论如何我会为其他感兴趣的人发布我的答案。首先,文件表仍然是一个表,因此,如果您想从中访问数据,您需要使用 Select SQL 语句。所以你需要类似的东西:

select name, file_stream from filetable_name 
where 
name = 'file_name',
file_type = 'file_extension'

只需在您的 asp.net 应用程序中执行这样的语句,然后获取结果并使用 file_stream 列来获取存储文件的二进制数据。如果要从 HTML 中检索文件,首先需要在控制器中创建一个操作,该操作将返回检索到的文件:

public ActionResult GetFile(){
..
return File(file.file_stream,file.file_type);
}

在此之后,在您的 HTML 标记中添加如下内容:

<img src="/controller/GetFile" />

希望这会有所帮助!如果您想知道文件表的架构,请参见 此处

于 2018-01-15T22:14:50.663 回答
-1

我假设 FileTable 你实际上是指 FileStream。关于这一点的几点说明:

  1. 如果您的文件实际上是文件,则最好使用此功能
  2. 这些文件平均应大于 1mb - 尽管此规则可能存在例外情况,但如果它们平均小于 1mb,则最好适当地使用 aVARBINARY(MAX)XML数据类型。如果您的图像平均非常小(只有几 KB),请考虑使用VARBINARY(MAX)列。
  3. 访问这些文件将需要一个打开的事务,并且数据库已正确配置FILESTREAM
  4. 您可以通过告诉 SQL Server 您要直接访问文件来绕过正常的 SQL 引擎/数据库文件数据访问方法,从而获得一些显着优势,但这并不意味着直接访问文件系统上的文件并尝试这样做可以打破 SQL 对这些文件的管理(事务一致性、跟踪、锁定等)。
  5. 如果您确实需要 SQL,则很可能通过使用 CDN 并将图像 URL 存储在表中来更好地服务您的用例。您可以使用它FILESTREAM来执行此操作(请参阅下面的代码示例以了解一种实现),但是除非您将图像存储在浏览器可以正确缓存的其他位置(我的示例没有这样做),否则您将为每个请求敲击您的 SQL 服务器) - 如果您将它们存储在其他地方以便在浏览器中呈现,您不妨将它们存储在那里(一旦它们被复制到其他驱动器/磁盘/位置,这些图像就不会具有事务一致性) .

说了这么多,下面是一个如何FILESTREAM使用 ADO.NET 访问数据的示例:

public static string connectionString = ...; // get your connection string from encrypted config

// assumes your FILESTREAM data column is called Img in a table called ImageTable
const string sql = @"
    SELECT            
        Img.PathName(),
        GET_FILESTREAM_TRANSACTION_CONTEXT()
      FROM ImageTagble
      WHERE ImageId = @id";

public string RetreiveImage(int id)
{
    string serverPath;
    byte[] txnToken;
    string base64ImageData = null;
    using (var ts = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
                using (SqlDataReader rdr = cmd.ExecuteReader())
                {
                    rdr.Read();
                    serverPath = rdr.GetSqlString(0).Value;
                    txnToken = rdr.GetSqlBinary(1).Value;
                }
            }
            using (var sfs = new SqlFileStream(serverPath, txnToken, FileAccess.Read))
            {
            // sfs will now work basically like a FileStream.  You can either copy it locally or return it as a base64 encoded string
               using (var ms = new MemoryStream())
               {
                  sfs.CopyTo(ms);
                  base64ImageData = Convert.ToBase64String(ms.ToArray());
               }
            }
        }
        ts.Complete();
        // assume this is PNG image data, replace PNG with JPG etc. as appropraite.  Might store in table if it will vary...
        return "data:img/png;base64," + base64ImageData;
    }
}

显然,如果您有很多图像要像这样处理,这不是一个理想的方法 - 不要尝试将 SQL Server 实例制作成您应该使用 CDN 的......但是,如果您真的有其他充分的理由,您应该尝试在单个请求/事务中获取尽可能多的图像(例如,如果您知道您在页面上显示 50 个图像,则使用单个事务范围获取所有 50 个图像,不要使用 50 个事务范围- 此代码不会处理)。

于 2017-01-17T13:52:27.733 回答