SQL文件流认证最佳实践

时间:2010-12-15 15:58:43

标签: sql filestream

我能够在本地使用SQL Filestream,但是当我尝试将文件上传到使用SQL身份验证的远程SQL服务器时,我得到了一个Access Denied异常。显然,SQL Filestream仅适用于Windows身份验证(Integrated Security = true),而不适用于我们目前拥有的SQL身份验证。

在生产环境中没有人真正使用Windows身份验证,因此我只想知道如何克服此限制。什么是最佳做法?

    public static void AddItem(RepositoryFile repository, byte[] data)
{
    using (var scope = new TransactionScope())
    {
        using (var db = new MyEntities()) // DBContext
        {
            db.RepositoryTable.AddObject(repository);
            db.SaveChanges();
        }

        using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
        using (var cmd = new SqlCommand(string.Format("SELECT Data.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM dbo.RepositoryTable WHERE ID='{0}'", repository.ID), con)) // "Data" is the column name which has the FILESTREAM. Data.PathName() gives me the local path to the file.
        {
            cmd.Connection.Open();
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var path = reader.GetString(0);
                    var transactionContext = reader.GetSqlBytes(1).Buffer;
                    var fileStream = new SqlFileStream(path, transactionContext, FileAccess.Write);

                    fileStream.Write(contents, 0, contents.Length); // I get the error at this line.
                    fileStream.Close();
                }
            }
        }

        scope.Complete();
    }
}

2 个答案:

答案 0 :(得分:4)

使用FILESTREAM时确实必须使用集成身份验证:

FILESTREAM Storage in SQL Server 2008

您需要确保生成应用程序的Windows帐户已添加为SQL Server中的登录帐户,并且已被授予与应用程序当前使用的SQL身份验证帐户相同的权限。

您还必须确保该帐户具有写入FILESTREAM容器的文件系统权限。

答案 1 :(得分:3)

我使用SqlFileStream示例获得了类似的“拒绝访问”消息。这让我们难过了好几天。

一位同事提出了一种非常有效的替代方法。不使用SqlFileStream,而是使用带有带字节值的参数的INSERT命令将文件字节直接写入SQL服务器。对于我们的名为'FileData'的表,列'Id'(一个guid)和'Bytes',我会使用这样的东西:

Byte[] bytes = // assign your data here

using (SqlConnection conn = new SqlConnection(connectionString)) {
    SqlCommand insertCmd = new SqlCommand("INSERT INTO FileData (Id, Bytes) VALUES (@Id, @Bytes)", conn);

    insertCmd.CommandType = System.Data.CommandType.Text;
    insertCmd.Parameters.AddWithValue("@Id", Guid.NewGuid());
    insertCmd.Parameters.AddWithValue("@Bytes", bytes);
    insertCmd.Transaction = conn.BeginTransaction();

    try {
        insertCmd.ExecuteNonQuery();
        insertCmd.Commit();
    }
    catch (Exception e) {
        insertCmd.Transaction.Rollback();
    }
}

请注意,未使用SqlFileStream类。