Beispiel #1
0
 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;
        }
Beispiel #5
0
        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);
            }
        }