When receiving a Stream
in WCF
and writing it to a database table, what buffer size is used when writing the data to the database table and how can it be changed?
I'm using .NET Framework 4.6 and Microsoft SQL Server.
Server
[ServiceContract(Name = "IUploadFileService")]
public interface IUploadFileService
{
[OperationContract]
void UploadFile(UploadFileMessage uploadFileMessage);
}
[MessageContract]
public class UploadFileMessage
{
[MessageBodyMember]
public Stream FileContents { get; set; }
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class UploadFileService : IUploadFileService
{
public void UploadFile(UploadFileMessage uploadFileMessage)
{
using (MyDbContext context = new MyDbContext())
{
DbConnection conn = context.Database.Connection;
ConnectionState initialState = conn.State;
try
{
if (initialState != ConnectionState.Open)
{
conn.Open();
}
using (DbCommand cmd = conn.CreateCommand())
{
// the FileContents field is a `varbinary(max)` data type
cmd.CommandText = "INSERT INTO [Files] (FileContents) VALUES (@FileContents)";
cmd.CommandTimeout = 0;
DbParameter parameter = cmd.CreateParameter();
parameter.ParameterName = "@FileContents";
parameter.DbType = DbType.Binary;
parameter.Size = -1;
parameter.Value = uploadFileMessage.FileContents; // what buffer size is used to read this Stream and write it to the database?
cmd.Parameters.Add(parameter);
cmd.ExecuteNonQuery();
}
}
finally
{
if (initialState != ConnectionState.Open)
{
conn.Close();
}
}
}
}
}
Server configuration
<?xml version="1.0" encoding="utf-8" ?>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IFileUploadService" closeTimeout="00:01:00" receiveTimeout="24.20:31:23.6470000" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Streamed">
<readerQuotas maxArrayLength="32505856" maxStringContentLength="32505856" />
<security mode="None">
<transport clientCredentialType="None" protectionLevel="None" />
<message clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
Client
private static void UploadFile()
{
EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:4502/FileUploadService");
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None)
{
TransferMode = TransferMode.Streamed,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
SendTimeout = TimeSpan.MaxValue
};
FileUploadServiceClient fileUploadServiceClient = new FileUploadServiceClient(binding, endpointAddress);
using (FileStream fileStream = new FileStream(@"c:\test.bin", FileMode.Open)) // read buffer size is 4096 bytes by default
{
fileUploadServiceClient.UploadFile(fileStream);
}
}
Is it any of these?
FileStream
used to open the file on the clientNetTcpBinding.MaxBufferSize
on the clientmaxBufferSize
in the WCF server configurationDbParameter.Size
, which is int.MaxValue
because it's set to -1
and the maximum number of bytes that can be entered in a varbinary(max)
database fieldNetwork Packet Size
configuration setting in the SQL Server databaseMTU
values on the networkThank you.
Windows Communication Foundation (WCF) transports support two modes for transferring messages:
1.Buffered transfers hold the entire message in a memory buffer until the transfer is complete. A buffered message must be completely delivered before a receiver can read it.
2.Streamed transfers expose the message as a stream. The receiver starts processing the message before it is completely delivered.
I see that you use the second transfer mode, streaming, which can improve the scalability of services by eliminating the need for large memory buffers.
To prevent denial of service attacks, WCF exposes a MaxReceivedMessageSize attribute to limit the size attribute of incoming messages, so it also limits the maximum amount of memory accessed when processing the message. The unit is set in bytes, and the default value is 65,536 bytes.
For more information about Streaming Message Transfer,Please refer to the following link:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/streaming-message-transfer