Перенос контента файлов из БД на диск
Перенос контента файлов из БД на диск¶
Если контент файла хранится в БД, но доступ к ним может быть несколько медленнее, чем к файлам на файловой системе в силу особенностей СУБД. Если для некоторых из файлов требуется перенести контент на диск, то можно написать универсальный запрос к сервису карточек и использовать его из кода или по нажатию кнопки.
Это расширение можно не реализовывать самостоятельно, т.к. оно уже есть в типовом решении (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);
}