یکی از مواردی که در بانکهای اطلاعاتی امروزه بیشتر
مورد استفاده قرار میگیرد، ذخیره فایلها در خود دیتابیس، بجای ذخیره نام
یا آدرس آنها بر روی دیسک سخت است. از همان ابتدا که Raven به بازار عرضه شد، امکان
ذخیره فایلهای باینری را با استفاده از
افزونه هایی که به همراه داشت برای برنامه نویسان مهیا ساخت. این امکان از طریق کد زیر برای ذخیره یک فایل کفایت میکرد:
using (var store = new DocumentStore
{
Url = "http://localhost:8080"
}.Initialize())
{
using (var session = store.OpenSession())
{
store.DatabaseCommands.PutAttachment(key: "file/1",
etag: null,
data: System.IO.File.OpenRead(@"D:\Prog\packages.config"),
metadata: new RavenJObject
{
{ "Description", "توضیحات فایل" }
});
var question = new Question
{
By = "users/Vahid",
Title = "Raven Intro",
Content = "Test....",
FileId = "file/1"
};
session.Store(question);
session.SaveChanges();
}
}
ولی اگر از نسخه سه بعد RavenDb را استفاده کنید، میبینید که متد PutAttachment و دیگر خانواده این متد با ویژگی Obsolete (منسوخ شده) مزین
شدهاند و توصیه شدهاست از این پس از قابلیت جدیدی به نام RavenFs
استفاده شود.
RavenFS یک فایل سیستم مجازی توزیع شدهاست و برای فایلهای بزرگ چند گیگابایتی به طور بهینهای طراحی گردیدهاست تا کارآیی بانک
اطلاعاتی را بالا ببرد و وجود فایلهای تکراری، از بین برود. این سیستم جدید شامل سیستم پیش فرض ایندکس گذاری
میباشد و به شما این اجازه را میدهد تا بر روی متادیتاهای یک فایل از قبیل
حجم، تاریخ آخرین نگارش و حتی متادیتاهای اختصاصی که شما در حین ذخیره
سازی به آن اضافه میکنید، به جستوجو بپردازد. این سیستم جدید همچنین این
امکان را به شما میدهد تا این اطلاعات را بین Nodeها، با کمترین میزان
انتقالات جابجا کنید و دسترسی سریعتری را بین نودهای مختلف داشته باشید.
برای
ذخیره سازی یک فایل ابتدا باید یک FileStore را همانند آنچه که برای
DocumentStore داشتید تعریف کنید. Url که شامل همان رشته اتصالی بوده و
DefaultFileSystem هم همانند DefaultDatabase که نام دیتابیس در آن ذکر
میشد، در اینجا نام فایل سیستم ذکر میگردد:
var fileStore = new FilesStore()
{
Url = "http://localhost:8080",
DefaultFileSystem = "SampleFs"
};
fileStore.Initialize();
بعد از آن باید از طریق Store جدید یک سشن ایجاد شود و فایل مورد نظر را در قالب یک استریم بخوانیم:
var session = fileStore.OpenAsyncSession();
var stream = File.OpenRead("D:\\Apocalypse.Now.Redux.1979.BDRip.YIFY.mkv");
توجه داشته
باشید که برای کار با فایل سیستم، همه متدهای session به صورت غیرهمزمان
بوده و متد همزمانی وجود ندارد. سپس در مرحله بعد میخواهم متادیتاهای شخصی
نیز به آن اضافه کنیم:
var metadata = new RavenJObject
{
{"User", "users/1345"},
{"Director","Francis Ford Coppola" },
{"Year","1979" }
};
با استفاده از شیء RavenObject میتوانیم در
قالب کلید و مقدار، مقادیر خود را ذخیره کنیم و بعد از آن همه موارد بالا که
شامل فایل هدر، استریم و متادیتای اختصاصی است را رجیستر کنیم. اگر هم چندین
فایل داریم میتوانید آنها را هم در همینجا رجیستر کنید:
session.RegisterUpload("mkv/sample.mkv", stream, metadata);
در مرحله بعدی تغییرات را تایید و عملیات آپلود آغاز میگردد:
await session.SaveChangesAsync();
همانطور که میبینید تمامی متدهای کاربردی این سشن به طور غیرهمزمان طراحی شدهاند.
کلیه عملیاتی که در بالا انجام شد:
var fileStore = new FilesStore()
{
Url = "http://localhost:8080",
DefaultFileSystem = "SampleFs"
};
fileStore.Initialize();
var session = fileStore.OpenAsyncSession();
var stream = File.OpenRead("D:\\Apocalypse.Now.Redux.1979.BDRip.YIFY.mkv");
var metadata = new RavenJObject
{
{"User", "users/1345"},
{"Director","Francis Ford Coppola" },
{"Year","1979" }
};
session.RegisterUpload("Mkv/sample.mkv", stream, metadata);
await session.SaveChangesAsync();
حالا اگر به
نسخه سرور ravenDb مراجعه کنید میبینید که فایل طبق فایل هدر داده شده
قرار گرفته است و اطلاعات مربوط به آن ذخیره شده است:
{
"User": "users/1345",
"Country": "Iran",
"City": "Kashan",
"Raven-Synchronization-History": [
{
"Version": 4,
"ServerId": "42d0cccb-103d-4bf0-9f3d-6f635b1c8ba4"
},
{
"Version": 5,
"ServerId": "42d0cccb-103d-4bf0-9f3d-6f635b1c8ba4"
}
],
"Raven-Synchronization-Version": "6",
"Raven-Synchronization-Source": "42d0cccb-103d-4bf0-9f3d-6f635b1c8ba4"
}
برای خواندن هم به شیوه زیر عمل میکنیم:
از طریق Store
ایجاد شده، یک سشن جدید را باز میکنیم و فایل مورد نظر را از طریق یکی از
متادیتاهای تعریف شده بازیابی میکنیم:
var fileStore = new FilesStore()
{
Url = "http://localhost:8080",
DefaultFileSystem = "SampleFs"
};
fileStore.Initialize();
var session = fileStore.OpenAsyncSession();
var file = await session.Query()
.WhereEquals("Year", "1979")
.FirstOrDefaultAsync();
سپس با آدرس دهی فایل هدر، فایل باینری را داخل استریم قرار میدهیم:
var stream = await session.DownloadAsync("mkv/"+file.Name);
سپس استریم را روی دیسک سخت دخیره یا به هر مکانی که مد نظر است ارسال میکنیم:
var fs = File.Create("D:\\file2.mkv");
stream.CopyTo(fs);
fs.Flush();
fs.Close();
البته از آنجائیکه عملیات بازیابی توسط بانک اطلاعاتی به صورت غیرهمزمان انجام میگیرد، بهتر هست که باقی عملیات هم به صورت غیرهمزمان انجام شود:
await stream.CopyToAsync(fs);
سپس کل کد بازیابی را به شکل زیر مینویسیم:
var fileStore = new FilesStore()
{
Url = "http://localhost:8080",
DefaultFileSystem = "SampleFs"
};
fileStore.Initialize();
var session = fileStore.OpenAsyncSession();
var file = await session.Query()
.WhereEquals("Year", "1979")
.FirstOrDefaultAsync();
var stream = await session.DownloadAsync("mkv/"+file.Name);
var fs = File.Create("D:\\file2.mkv");
await stream.CopyToAsync(fs);