/// <summary> /// Marks orphaned file records (the ones that do not have a referencing binary record anymore) as Deleted. /// </summary> public void CleanupFilesSetDeleteFlag() { var isLocalTransaction = false; if (!TransactionScope.IsActive) { TransactionScope.Begin(); isLocalTransaction = true; } try { using (var proc = new SqlProcedure { CommandText = CleanupFileSetIsdeletedScript, CommandType = CommandType.Text }) { proc.CommandType = CommandType.Text; proc.ExecuteNonQuery(); } if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Commit(); } } catch (Exception ex) { if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Rollback(); } throw new DataException("Error during setting deleted flag on files.", ex); } }
/// <summary> /// Finalizes a chunked save operation. /// </summary> /// <param name="versionId">Content version id.</param> /// <param name="propertyTypeId">Binary property type id.</param> /// <param name="fileId">File identifier.</param> /// <param name="fullSize">Full size (stream length) of the binary value.</param> /// <param name="source">Binary data containing metadata (e.g. content type).</param> public void CommitChunk(int versionId, int propertyTypeId, int fileId, long fullSize, BinaryDataValue source = null) { // start a new transaction here if needed var isLocalTransaction = !TransactionScope.IsActive; if (isLocalTransaction) { TransactionScope.Begin(); } try { // commit the process: set the final full size and checksum using (var cmd = new SqlProcedure { CommandText = CommitChunkScript, CommandType = CommandType.Text }) { cmd.Parameters.Add("@FileId", SqlDbType.Int).Value = fileId; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId; cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value = fullSize; cmd.Parameters.Add("@Checksum", SqlDbType.VarChar, 200).Value = DBNull.Value; cmd.Parameters.Add("@ContentType", SqlDbType.NVarChar, 50).Value = source != null ? source.ContentType : string.Empty; cmd.Parameters.Add("@FileNameWithoutExtension", SqlDbType.NVarChar, 450).Value = source != null ? source.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)source.FileName.FileNameWithoutExtension : DBNull.Value; cmd.Parameters.Add("@Extension", SqlDbType.NVarChar, 50).Value = source != null?ValidateExtension(source.FileName.Extension) : string.Empty; cmd.ExecuteNonQuery(); } } catch (Exception ex) { // rollback the transaction if it was opened locally if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Rollback(); } throw new DataException("Error during committing binary chunk to file stream.", ex); } finally { // commit the transaction if it was opened locally if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Commit(); } } }
/// <summary> /// Starts a chunked save operation on an existing content. It does not write any binary data /// to the storage, it only makes prerequisite operations - e.g. allocates a new slot in the storage. /// </summary> /// <param name="blobProvider">Blob storage provider.</param> /// <param name="versionId">Content version id.</param> /// <param name="propertyTypeId">Binary property type id.</param> /// <param name="fullSize">Full size (stream length) of the binary value.</param> /// <returns>A token containing all the information (db record ids) that identify a single entry in the blob storage.</returns> public string StartChunk(IBlobProvider blobProvider, int versionId, int propertyTypeId, long fullSize) { var isLocalTransaction = !TransactionScope.IsActive; if (isLocalTransaction) { TransactionScope.Begin(); } var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = fullSize }; string blobProviderName = null; string blobProviderData = null; bool useSqlFileStream; if (IsBuiltInOrSqlFileStreamProvider(blobProvider)) { useSqlFileStream = SqlFileStreamBlobProvider.UseFileStream(blobProvider, fullSize); } else { useSqlFileStream = false; blobProvider.Allocate(ctx); blobProviderName = blobProvider.GetType().FullName; blobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } try { using (var cmd = new SqlProcedure { CommandText = InsertStagingBinaryScript, CommandType = CommandType.Text }) { cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId; cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value = fullSize; cmd.Parameters.Add("@UseSqlFileStream", SqlDbType.TinyInt).Value = useSqlFileStream ? 2 : 0; cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = blobProviderName != null ? (object)blobProviderName : DBNull.Value; cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = blobProviderData != null ? (object)blobProviderData : DBNull.Value; int binaryPropertyId; int fileId; using (var reader = cmd.ExecuteReader()) { if (reader.Read()) { binaryPropertyId = reader.GetSafeInt32(0); fileId = reader.GetSafeInt32(1); } else { throw new DataException("File row could not be inserted."); } } ctx.FileId = fileId; return(new ChunkToken { VersionId = versionId, PropertyTypeId = propertyTypeId, BinaryPropertyId = binaryPropertyId, FileId = fileId }.GetToken()); } } catch (Exception ex) { if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Rollback(); } throw new DataException("Error during saving binary chunk to SQL Server.", ex); } finally { if (isLocalTransaction && TransactionScope.IsActive) { TransactionScope.Commit(); } } }