protected virtual void Dispose(bool disposing) { if (disposing) { if (sqlProc != null) { sqlProc.Dispose(); sqlProc = null; } } }
private static Tuple <VersionNumber, VersionNumber> GetLastVersions(string path) { VersionNumber majorVersion = null; VersionNumber minorVersion = null; SqlProcedure cmd = null; SqlDataReader reader = null; try { cmd = new SqlProcedure { CommandText = Scripts.LastVersions, CommandType = CommandType.Text }; cmd.Parameters.Add("@Path", SqlDbType.NVarChar, 450).Value = path; reader = cmd.ExecuteReader(); while (reader.Read()) { var majorNumber = reader.GetInt16(reader.GetOrdinal("MajorNumber")); var minorNumber = reader.GetInt16(reader.GetOrdinal("MinorNumber")); var statusCode = reader.GetInt16(reader.GetOrdinal("Status")); var isLastMajor = reader.GetBoolean(reader.GetOrdinal("LastMajor")); var isLastMinor = reader.GetBoolean(reader.GetOrdinal("LastMinor")); var versionNumber = new VersionNumber(majorNumber, minorNumber, (VersionStatus)statusCode); if (isLastMajor) { majorVersion = versionNumber; } if (isLastMinor) { minorVersion = versionNumber; } } } finally { reader?.Dispose(); cmd?.Dispose(); } return(new Tuple <VersionNumber, VersionNumber>(majorVersion, minorVersion)); }
/// <summary> /// Deletes a binary property value from the metadata database, making the corresponding blbo storage entry orphaned. /// </summary> /// <param name="versionId">Content version id.</param> /// <param name="propertyTypeId">Binary property type id.</param> public void DeleteBinaryProperty(int versionId, int propertyTypeId) { SqlProcedure cmd = null; try { cmd = new SqlProcedure { CommandText = "proc_BinaryProperty_Delete" }; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId; cmd.ExecuteNonQuery(); } finally { cmd?.Dispose(); } }
/// <summary> /// Inserts a new binary record into the metadata database containing an already exising file id, /// removing the previous record if the content is not new. /// </summary> /// <param name="value">Binary data to insert.</param> /// <param name="versionId">Content version id.</param> /// <param name="propertyTypeId">Binary property type id.</param> /// <param name="isNewNode">Whether this value belongs to a new or an existing node.</param> public void InsertBinaryPropertyWithFileId(BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode) { SqlProcedure cmd = null; int id; try { cmd = new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyWithKnownFileIdScript : DeleteAndInsertBinaryPropertyWithKnownFileId, CommandType = CommandType.Text }; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId != 0 ? (object)versionId : DBNull.Value; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId != 0 ? (object)propertyTypeId : DBNull.Value; cmd.Parameters.Add("@FileId", SqlDbType.Int).Value = value.FileId; id = (int)cmd.ExecuteScalar(); } finally { cmd?.Dispose(); } value.Id = id; }
internal static void UpdateStream(BlobStorageContext context, Stream stream) { var fileId = context.FileId; var fileStreamData = ((SqlFileStreamBlobProviderData)context.BlobProviderData).FileStreamData; SqlProcedure cmd = null; try { // if possible, write the stream using the special Filestream technology if (UseFileStream(context.Provider, stream.Length)) { WriteSqlFileStream(stream, fileId, fileStreamData); return; } // We have to work with an integer since SQL does not support // binary values bigger than [Int32.MaxValue]. var streamSize = Convert.ToInt32(stream.Length); cmd = new SqlProcedure { CommandText = "proc_BinaryProperty_WriteStream" }; cmd.Parameters.Add("@Id", SqlDbType.Int).Value = fileId; var offsetParameter = cmd.Parameters.Add("@Offset", SqlDbType.Int); var valueParameter = cmd.Parameters.Add("@Value", SqlDbType.VarBinary, streamSize); cmd.Parameters.Add("@UseFileStream", SqlDbType.TinyInt).Value = false; var offset = 0; byte[] buffer = null; stream.Seek(0, SeekOrigin.Begin); // The 'while' loop is misleading here, because we write the whole // stream at once. Bigger files should go to the Filestream // column anyway. while (offset < streamSize) { // Buffer size may be less at the end os the stream than the limit var bufferSize = streamSize - offset; if (buffer == null || buffer.Length != bufferSize) { buffer = new byte[bufferSize]; } // Read bytes from the source stream.Read(buffer, 0, bufferSize); offsetParameter.Value = offset; valueParameter.Value = buffer; // Write full stream cmd.ExecuteNonQuery(); offset += bufferSize; } } finally { cmd?.Dispose(); } }
/// <summary> /// Updates an existing binary property value in the database and the blob storage. /// </summary> /// <param name="blobProvider">Blob storage provider.</param> /// <param name="value">Binary data to update.</param> public void UpdateBinaryProperty(IBlobProvider blobProvider, BinaryDataValue value) { var streamLength = value.Stream?.Length ?? 0; var isExternal = false; if (!IsBuiltInOrSqlFileStreamProvider(blobProvider)) { var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; blobProvider.Allocate(ctx); isExternal = true; value.BlobProviderName = ctx.Provider.GetType().FullName; value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } else { value.BlobProviderName = null; value.BlobProviderData = null; } var isRepositoryStream = value.Stream is RepositoryStream || value.Stream is SenseNetSqlFileStream; var hasStream = isRepositoryStream || value.Stream is MemoryStream; if (!isExternal && !hasStream) { // do not do any database operation if the stream is not modified return; } SqlFileStreamData fileStreamData = null; SqlProcedure cmd = null; try { string sql; CommandType commandType; if (IsBuiltInOrSqlFileStreamProvider(blobProvider)) { commandType = CommandType.StoredProcedure; sql = "proc_BinaryProperty_Update"; } else { commandType = CommandType.Text; sql = UpdateBinarypropertyNewFilerowFilestreamScript; } cmd = new SqlProcedure { CommandText = sql, CommandType = commandType }; cmd.Parameters.Add("@BinaryPropertyId", SqlDbType.Int).Value = value.Id; cmd.Parameters.Add("@ContentType", SqlDbType.NVarChar, 450).Value = value.ContentType; cmd.Parameters.Add("@FileNameWithoutExtension", SqlDbType.NVarChar, 450).Value = value.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)value.FileName.FileNameWithoutExtension; cmd.Parameters.Add("@Extension", SqlDbType.NVarChar, 50).Value = ValidateExtension(value.FileName.Extension); cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value = value.Size; cmd.Parameters.Add("@Checksum", SqlDbType.VarChar, 200).Value = value.Checksum != null ? (object)value.Checksum : DBNull.Value; cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value; cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value; int fileId; string path; byte[] transactionContext; // Update row and retrieve file path and // transaction context for the Filestream column using (var reader = cmd.ExecuteReader()) { reader.Read(); fileId = reader.GetInt32(0); path = reader.GetSafeString(1); transactionContext = reader.IsDBNull(2) ? null : reader.GetSqlBytes(2).Buffer; } if (!string.IsNullOrEmpty(path)) { fileStreamData = new SqlFileStreamData { Path = path, TransactionContext = transactionContext } } ; if (fileId > 0 && fileId != value.FileId) { value.FileId = fileId; } } finally { cmd?.Dispose(); } if (blobProvider == BlobStorageBase.BuiltInProvider) { var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, BlobProviderData = new SqlFileStreamBlobProviderData { FileStreamData = fileStreamData } }; BuiltInBlobProvider.UpdateStream(ctx, value.Stream); } else if (blobProvider is SqlFileStreamBlobProvider) { var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, BlobProviderData = new SqlFileStreamBlobProviderData { FileStreamData = fileStreamData } }; SqlFileStreamBlobProvider.UpdateStream(ctx, value.Stream); } else { var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData) { VersionId = 0, PropertyTypeId = 0, FileId = value.FileId, Length = streamLength, }; using (var stream = blobProvider.GetStreamForWrite(ctx)) value.Stream?.CopyTo(stream); } }
/// <summary> /// Inserts a new binary property value into the metadata database and the blob storage, /// removing the previous one if the content is not new. /// </summary> /// <param name="blobProvider">Blob storage provider.</param> /// <param name="value">Binary data to insert.</param> /// <param name="versionId">Content version id.</param> /// <param name="propertyTypeId">Binary property type id.</param> /// <param name="isNewNode">Whether this value belongs to a new or an existing node.</param> public void InsertBinaryProperty(IBlobProvider blobProvider, BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode) { var streamLength = value.Stream?.Length ?? 0; var useFileStream = SqlFileStreamBlobProvider.UseFileStream(blobProvider, streamLength); var ctx = new BlobStorageContext(blobProvider) { VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength }; // In case of an external provider allocate the place for bytes and // write the stream beforehand and get the generated provider data. // Note that the external provider does not need an existing record // in the Files table to work, it just stores the bytes. if (!IsBuiltInOrSqlFileStreamProvider(blobProvider)) { blobProvider.Allocate(ctx); using (var stream = blobProvider.GetStreamForWrite(ctx)) value.Stream?.CopyTo(stream); value.BlobProviderName = ctx.Provider.GetType().FullName; value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData); } SqlProcedure cmd = null; SqlFileStreamData fileStreamData = null; try { cmd = useFileStream ? new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyFilestreamScript : DeleteAndInsertBinaryPropertyFilestream, CommandType = CommandType.Text } : new SqlProcedure { CommandText = isNewNode ? InsertBinaryPropertyScript : DeleteAndInsertBinaryProperty, CommandType = CommandType.Text }; cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value = versionId != 0 ? (object)versionId : DBNull.Value; cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value = propertyTypeId != 0 ? (object)propertyTypeId : DBNull.Value; cmd.Parameters.Add("@ContentType", SqlDbType.NVarChar, 450).Value = value.ContentType; cmd.Parameters.Add("@FileNameWithoutExtension", SqlDbType.NVarChar, 450).Value = value.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)value.FileName.FileNameWithoutExtension; cmd.Parameters.Add("@Extension", SqlDbType.NVarChar, 50).Value = ValidateExtension(value.FileName.Extension); cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value = Math.Max(0, value.Size); cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value; cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value; cmd.Parameters.Add("@Checksum", SqlDbType.VarChar, 200).Value = value.Checksum != null ? (object)value.Checksum : DBNull.Value; // insert binary and file rows and retrieve file path and transaction context for the Filestream column using (var reader = cmd.ExecuteReader()) { reader.Read(); value.Id = Convert.ToInt32(reader[0]); value.FileId = Convert.ToInt32(reader[1]); value.Timestamp = Utility.Convert.BytesToLong((byte[])reader.GetValue(2)); if (useFileStream) { fileStreamData = new SqlFileStreamData { Path = reader.GetString(3), TransactionContext = reader.GetSqlBytes(4).Buffer }; } } } finally { cmd.Dispose(); } // The BuiltIn blob provider saves the stream after the record // was saved into the Files table, because simple varbinary // and sql filestream columns must exist before we can write a // stream into the record. // ReSharper disable once InvertIf if (blobProvider == BlobStorageBase.BuiltInProvider && value.Stream != null) { ctx.FileId = value.FileId; ctx.BlobProviderData = new SqlFileStreamBlobProviderData { FileStreamData = fileStreamData }; BuiltInBlobProvider.AddStream(ctx, value.Stream); } else if (blobProvider is SqlFileStreamBlobProvider && value.Stream != null) { ctx.FileId = value.FileId; ctx.BlobProviderData = new SqlFileStreamBlobProviderData { FileStreamData = fileStreamData }; SqlFileStreamBlobProvider.AddStream(ctx, value.Stream); } }