我们需要使用SQL登录名(在多租户环境中每个数据库通常使用一个SQL登录名)登录SQL Server,但是我们需要在C#中使用sqlFileStream类使用文件流功能。
目前的方法,但实施起来非常复杂:
在应用程序代码中,为文件流所需的每个相关sql命令动态添加EXECUTE AS [Service Account]
。(由于应用程序通过SQL身份验证进行连接,因此文件流需要Windows用户获取文件和事务上下文的逻辑路径)
例如
sqlCommand3.CommandText = @"
execute as login ='Domain\xxxxxxx';
Select
FileData.PathName() As Path,
GET_FILESTREAM_TRANSACTION_CONTEXT() As TransactionContext
From PictureTable
Where PkId = (Select Max(PkId) From PictureTable)";
在数据库级别,我们需要将Active Directory组(其中包含所有服务帐户)添加为SQL登录名,并且还需要在每个数据库中添加为用户
我们还需要在实例级别将每个服务帐户创建为SQL登录。
我们需要模拟每个服务帐户登录名给每个数据库用户(每个数据库一个用户)
例如GRANT IMPERSONATE on LOGIN::[Domain\xxxxxxx] to APPUSER;
using (TransactionScope transactionScope = new TransactionScope())
{
SqlConnection sqlConnection1 = new SqlConnection("Data Source=xxxxx-xxxxx;Initial Catalog=xxxxx;User ID=xxxx;Password=xxxx");
SqlCommand sqlCommand1 = sqlConnection1.CreateCommand();
sqlCommand1.CommandText = @"execute as login ='XXXXXX\XXXXXX';Insert Into PictureTable(Description,FileData) values('" + Guid.NewGuid().ToString() + "',Cast('' As varbinary(Max))); Select FileData.PathName() As Path From PictureTable Where PkId =@@Identity";
sqlConnection1.Open();
string filePath1 = (string)sqlCommand1.ExecuteScalar();
SqlConnection sqlConnection2 = new SqlConnection("Data Source=xxxxx-xxxxx;Initial Catalog=xxxxx;User ID=xxxx;Password=xxxx");
SqlCommand sqlCommand2 = sqlConnection2.CreateCommand();
sqlCommand2.CommandText = @"execute as login ='XXXXXX\XXXXXX';Select GET_FILESTREAM_TRANSACTION_CONTEXT() As TransactionContext";
sqlConnection2.Open();
byte[] transactionContext1 = (byte[])sqlCommand2.ExecuteScalar();
SqlFileStream sqlFileStream1 = new SqlFileStream(filePath1, transactionContext1, FileAccess.Write);
byte[] fileData = Guid.NewGuid().ToByteArray();
sqlFileStream1.Write(fileData, 0, fileData.Length);
sqlFileStream1.Close();
transactionScope.Complete();
}