Перейти к содержанию

Перенос контента файлов из БД на диск

Перенос контента файлов из БД на диск

Если контент файла хранится в БД, но доступ к ним может быть несколько медленнее, чем к файлам на файловой системе в силу особенностей СУБД. Если для некоторых из файлов требуется перенести контент на диск, то можно написать универсальный запрос к сервису карточек и использовать его из кода или по нажатию кнопки.

Это расширение можно не реализовывать самостоятельно, т.к. оно уже есть в типовом решении (Tessa.Extensions.Default.Server.Cards и Tessa.Extensions.Default.Shared.Cards). Для пояснения работы расширения его код приведён ниже.

Код расширения пишется на сервере в сборке Tessa.Extensions.Server:

public sealed class MoveFileToDiskRequestExtension : CardRequestExtension { public MoveFileToDiskRequestExtension( ICardGetStrategy getStrategy, ICardContentStrategy contentStrategy, IDbScope dbScope) { this.getStrategy = getStrategy; this.contentStrategy = contentStrategy; this.dbScope = dbScope; }

private readonly ICardGetStrategy getStrategy;

private readonly ICardContentStrategy contentStrategy;

private readonly IDbScope dbScope;

public override void AfterRequest(ICardRequestExtensionContext context) { if (!context.RequestIsSuccessful) { return; }

Guid? requestCardID = context.Request.CardID; if (!requestCardID.HasValue) { ValidationSequence .Begin(context.ValidationResult) .SetObjectName(this) .Error(CardValidationKeys.UnspecifiedCardID) .End();

return; }

using (this.dbScope.Create()) { var fileIDs = new List<Guid>(); Guid? requestFileID = context.Request.FileID; if (requestFileID.HasValue) { fileIDs.Add(requestFileID.Value); } else { var card = new Card(); IList<CardGetContext> contexts = this.getStrategy .TryLoadFileInstances( requestCardID.Value, card, this.dbScope.Db, context.CardMetadata, context.ValidationResult);

if (contexts == null || contexts.Count == 0) { return; }

foreach (CardGetContext getContext in contexts) { fileIDs.Add(getContext.CardID); } }

var contents = new List<CardContentContext>(); foreach (Guid fileID in fileIDs) { var file = new CardFile(); this.getStrategy.LoadFileVersions( fileID, file.Versions, this.dbScope.Db, context.ValidationResult);

ListStorage<CardFileVersion> versions = file.TryGetVersions(); if (versions != null) { foreach (CardFileVersion version in versions) { contents.Add( new CardContentContext( requestCardID.Value, fileID, version.RowID, version.Source, context.ValidationResult)); } } }

if (!context.ValidationResult.IsSuccessful()) { return; }

if (contents.Count > 0) { DbManager db = this.dbScope.Db; db.ExecuteSetXactAbortOn();

foreach (CardContentContext content in contents) { if (content.Source == CardFileSourceType.Database) { var newContent = new CardContentContext( content.CardID, content.FileID, content.VersionRowID, CardFileSourceType.FileSystem, content.ValidationResult);

using (Stream contentStream = this.contentStrategy.Get(content)) { this.contentStrategy.Store(newContent, contentStream); }

db.BeginTransaction();

this.contentStrategy.Delete(content);

db .SetCommand( "update dbo.FileVersions set SourceID = @SourceID where RowID = @RowID", db.Parameter("@RowID", content.VersionRowID), db.Parameter("@SourceID", (short)CardFileSourceType.FileSystem)) .LogCommand() .ExecuteNonQuery();

db.CommitTransaction(); } } } } } }

Регистрация расширения:

extensionContainer .RegisterExtension<ICardRequestExtension, MoveFileToDiskRequestExtension>(x => x .WithOrder(ExtensionStage.BeforePlatform) .WithUnity(unityContainer .RegisterType<MoveFileToDiskRequestExtension>(new ContainerControlledLifetimeManager())) .WhenRequestTypes(CardExtensionRequestTypes.MoveFilesToDisk));

В общей для клиента и сервера сборке Tessa.Extensions.Shared нужен хэлпер с идентификатором запроса:

public static class CardExtensionRequestTypes { public static readonly Guid MoveFilesToDisk = new Guid(0x64565091, 0x2c00, 0x4ecd, 0xb6, 0x41, 0x1c, 0x8c, 0x8f, 0x91, 0x2c, 0x58); }

Чтобы переместить на диск все файлы карточки со всеми версиями, на клиенте можно сделать следующий вызов:

Guid cardID = ... ; // идентификатор карточки var request = new CardRequest { CardID = cardID, RequestType = CardExtensionRequestTypes.MoveFilesToDisk }; CardResponse response = cardRepository.Request(request);

ValidationResult result = response.ValidationResult.Build(); if (!result.IsSuccessful) { CardUIHelper.ShowResult(result); }

Чтобы переместить все версии конкретного файла, не затрагивая остальные файлы карточки, вызов с клиента будет выглядеть так:

Guid cardID = ... ; // идентификатор карточки Guid fileID = ... ; // идентификатор файла var request = new CardRequest { CardID = cardID, FileID = fileID, RequestType = CardExtensionRequestTypes.MoveFilesToDisk }; CardResponse response = cardRepository.Request(request);

ValidationResult result = response.ValidationResult.Build(); if (!result.IsSuccessful) { CardUIHelper.ShowResult(result); }

Back to top