public async Task UpdateBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, SnDataContext dataContext) { var streamLength = value.Stream?.Length ?? 0; var isExternal = false; if (!(blobProvider is IBuiltInBlobProvider)) { // BlobProviderData parameter is irrelevant because it will be overridden in the Allocate method var ctx = new BlobStorageContext(blobProvider) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; await blobProvider.AllocateAsync(ctx, dataContext.CancellationToken).ConfigureAwait(false); isExternal = true; value.BlobProviderName = ctx.Provider.GetType().FullName; value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } else { value.BlobProviderName = null; value.BlobProviderData = null; } if (blobProvider is IBuiltInBlobProvider) { // MS-SQL does not support stream size over [Int32.MaxValue]. if (streamLength > int.MaxValue) { throw new NotSupportedException(); } } var isRepositoryStream = value.Stream is RepositoryStream; var hasStream = isRepositoryStream || value.Stream is MemoryStream; if (!isExternal && !hasStream) { // do not do any database operation if the stream is not modified return; } if (!(dataContext is MsSqlDataContext sqlCtx)) { throw new PlatformNotSupportedException(); } var sql = blobProvider is IBuiltInBlobProvider ? UpdateBinaryPropertyScript : UpdateBinaryPropertyNewFilerowScript; var fileId = (int)await sqlCtx.ExecuteScalarAsync(sql, cmd => { cmd.Parameters.AddRange(new[] { sqlCtx.CreateParameter("@BinaryPropertyId", DbType.Int32, value.Id), sqlCtx.CreateParameter("@ContentType", DbType.String, 450, value.ContentType), sqlCtx.CreateParameter("@FileNameWithoutExtension", DbType.String, 450, value.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)value.FileName.FileNameWithoutExtension), sqlCtx.CreateParameter("@Extension", DbType.String, 50, ValidateExtension(value.FileName.Extension)), sqlCtx.CreateParameter("@Size", DbType.Int64, value.Size), sqlCtx.CreateParameter("@Checksum", DbType.AnsiString, 200, value.Checksum != null ? (object)value.Checksum : DBNull.Value), sqlCtx.CreateParameter("@BlobProvider", DbType.String, 450, value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value), sqlCtx.CreateParameter("@BlobProviderData", DbType.String, int.MaxValue, value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value), }); }).ConfigureAwait(false); if (fileId > 0 && fileId != value.FileId) { value.FileId = fileId; } if (blobProvider is IBuiltInBlobProvider) { // Stream exists and is loaded -> write it var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, BlobProviderData = new BuiltinBlobProviderData() }; await BuiltInBlobProvider.UpdateStreamAsync(ctx, value.Stream, sqlCtx).ConfigureAwait(false); } else { var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; if (streamLength == 0) { await blobProvider.ClearAsync(ctx, dataContext.CancellationToken).ConfigureAwait(false); } else { using (var stream = blobProvider.GetStreamForWrite(ctx)) value.Stream?.CopyTo(stream); } } }
public STT.Task UpdateBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, SnDataContext dataContext) { var streamLength = value.Stream?.Length ?? 0; var isExternal = false; if (streamLength > 0) { // BlobProviderData parameter is irrelevant because it will be overridden in the Allocate method var ctx = new BlobStorageContext(blobProvider) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; blobProvider.AllocateAsync(ctx, CancellationToken.None).GetAwaiter().GetResult(); isExternal = true; value.BlobProviderName = ctx.Provider.GetType().FullName; value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } var isRepositoryStream = value.Stream is RepositoryStream; var hasStream = isRepositoryStream || value.Stream is MemoryStream; if (!isExternal && !hasStream) { // do not do any database operation if the stream is not modified return(STT.Task.CompletedTask); } var db = DataProvider.DB; var fileId = db.Files.GetNextId(); db.Files.Insert(new FileDoc { FileId = fileId, ContentType = value.ContentType, Extension = value.FileName.Extension, FileNameWithoutExtension = value.FileName.FileNameWithoutExtension, Size = Math.Max(0, value.Size), BlobProvider = value.BlobProviderName, BlobProviderData = value.BlobProviderData }); var binaryPropertyDoc = db.BinaryProperties.FirstOrDefault(x => x.BinaryPropertyId == value.Id); if (binaryPropertyDoc != null) { binaryPropertyDoc.FileId = fileId; } if (fileId > 0 && fileId != value.FileId) { value.FileId = fileId; } // update stream with a new context var newCtx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; if (streamLength == 0) { blobProvider.ClearAsync(newCtx, dataContext.CancellationToken) .ConfigureAwait(false).GetAwaiter().GetResult(); } else { using (var stream = blobProvider.GetStreamForWrite(newCtx)) value.Stream?.CopyTo(stream); } return(STT.Task.CompletedTask); }