شروع کار با مانگو در سی شارپ
افزودن شاخص(ایندکس) به مجموعهها
نرمافزار MongoVUE ابزاری بهغایت کاربردی و مفید برای مشاهده ایندکسهای موجود در یک مجموعه بوده و همچنین این قابلیت را فراهم میآورد تا بهسادگی و سهولت ایندکسهای جدیدی را نیز به یک مجموعه افزود. برای این منظور کافی است تا مراحل زیر را انجام دهید:
روی هر یک از مجموعههای دلخواه خود (برای مثال games ) در قسمت Database Explorer کلیک راست کرده و گزینه Add Index… را در منوی باز شده انتخاب کنید (شکل ۷). پس از انجام این کار منوی New Index روی نمایشگر نمایان خواهد شد (شکل ۸).
شکل ۷
شکل ۸
در این محیط شما قادر خواهید بود تا با استفاده از فرمت JSON یا استفاده از ابزار بصری، در زمانی که مجموعه خود را ساخته باشید، نسبت به ساخت ایندکس مورد نظر خود اقدام کنید. برای این منظور نام مورد نظر خود برای ایندکس را (برای مثال name) را در کادر متنی Name وارد کرده، سپس با انتخاب زبانه visual، ازمیان فیلدهای موجود در مجموعه انتخابی (در اینجا games ) فیلد مورد نظر خود را انتخاب کرده و از لیست روبهروی آن گزینه Ascending(1). را برمیگزینید.گزینه Unique را انتخاب میکنید تا از این پس، از ورود اطلاعات تکراری در این فیلد جلوگیری شود. بنابراین، از این پس دو بازی همنام نخواهید داشت.در نهایت روی دکمه Create کلیک میکنید تا شاخص مورد نظر ساخته شود .
کد زیر که متناظر با ساخت ایندکس جدید است در پوسته آموزشی نمایان خواهد شد.
db.games.ensureIndex({“name” : ۱},{“name” : “name”, “unique” : true });
توجه کنید که پس از ساختن ایندکس، MongoVUE، بهصورت خودکار لیست ایندکسهای مجموعه انتخابی شما را در بخش Database Explorer بهروزرسانی نخواهد کرد و در نتیجه لازم است تا دکمه Refresh را کلیک کنید. پس از انجام این فرآیند، ایندکس ساخته شده، نمایان خواهد شد .اما بگذارید پیش از پایان دادن به این بخش، نکتهای را درمورد ایندکسگذاری دادههای بزرگ مطرح کنیم. اگرچه در اینجا ما گزینه Create Index In Background را به دلیل وجود تنها یک سند در مجموعه games انتخاب نکردیم، اما باید توجه داشته باشیم که در زمانی که حجم انبوهی از داده در یک مجموعه قرار دارد، انتخاب نکردن این گزینه میتواند منجر به خارج شدن پایگاه داده از دسترس کاربران بهدلیل نیاز به منابع بسیار زیاد برای ساختن در لحظه ایندکسها شود که گزینهای نامطلوب بوده و باید تا حد امکان از آن پرهیز شود.
بدون تردید ابزار MongoVUE علاوه بر تمامی مواردی که در اینجا به آن اشاره شد، مانند هر ابزار دیگری گزینهها و کارکردهای گوناگونی دارد که کافی است اندکی با آن کار کنید تا بتوانید نیازهای روتین و معمول خود را به بهترین شکل ممکن برآورده سازید.
کار با راهانداز سي شارپ داتنت در MongoDB
شرکت ۱۰Gen که میتوان آنرا توسعهدهنده اصلی و بهنوعی پدر MongoDB دانست، برای این پایگاههای داده راهاندازهای گوناگونی را به زبانهای مختلف برنامهنویسی تدارک دیده است تا تمامی برنامهنویسان بدون هیچ مشکلی بتوانند به استفاده از آن در برنامههای کاربردی خود بپردازند. ما نیز برای توسعه یک برنامه کاربردی به زبان # C با مراجعه به سایت رسمی این شرکت روی شبکه گیتهاب اقدام به بارگذاری راهانداز نسخه ۱٫۷٫۰٫۴۷۱۴ آن کردیم. توصیه میکنیم تا فایل msi این راهانداز با نام CSharpDriver-1.7.04714.msi را بارگذاری کنید تا زحمت جاگذاری فایلها در مکان مناسب را نیز بهخود نداده باشید.
با استفاده از این بسته نصب، فایلهای مورد نیاز بهطور خودکار در آدرس C:\Program Files (x86)\MongoDB\CSharpDriver 1.7 برای ویندوزهای ۶۴ بیتی ذخیره خواهد شد. توجه داشته باشید که اگرچه این راهانداز به نام C# نامگذاری شده است، اما برای برنامهنویسی با سایر زبانهای داتنت مانند F# و VB.NET نیز کاملاً سازگار است. بدیهی است که اگر فایل zip را بارگذاری کنید، قادر خواهید بود تا فایلهای مورد نیاز را در هرجایی از سیستم خود قرار دهید. راهانداز سي شارپ این پایگاه دادهها شامل دو فایل است:
- MongoDB.Bson.dll: این فایل کتابخانه Bson را شامل شده و کلاسهایی را در خود دارد که توابع لازم برای کار با این نوع دادهای را در خود جای داده است. این کلاسها الگوریتمهای مورد نیاز برای serialization و deserialization نوع دادهای Bson را در خود دارد.
- MongoDB.Driver.dll: کلاسهای لازم برای اتصال، تعامل و اجرای دستورات روی پایگاههای داده MongoDB در این فایل قرار دارند.
بدیهی است هر زمان که شما نیاز به کار با پایگاه داده MongoDB داشته باشید، گام نخست، ارجاع به این فایلها در پروژه است. برای این منظور ما از یک مثال ساده در قالب یک برنامه کنسول که تنها اطلاعاتی را از پایگاه داده retrogames واکشی میکند، استفاده خواهیم کرد. با این روش شما با namespace، کلاسها، انواع دادهای و توابع اولیه و پایه آشنا شده و در آینده به شکل بهتری از آنها استفاده خواهید کرد. بنابراین، هدف از پروژه کنسول پیشرو، آشنا ساختن شما با برخی گزینههای موجود در زمان کار با راهانداز سي شارپ در تعامل با MongoDB خواهد بود.
برای شروع کار، نرمافزار ویرایش کد Visual Studio 2010 یا نسخه ۲۰۱۲ را اجرا کرده و یک پروژه جدید کنسول به زبان سي شارپ ایجاد کنید و نام پروژه خود را RetrogamesConsole یا هرنام دیگری که مایل هستید، بگذارید. پس از آنکه پروژه جدید با موفقیت ساخته شد، لازم است یک ارجاع (refrence) جدید به پروژه RetrogamesConsole ایجاد شود. برای این منظور از قسمت Solution Explorer روی گزینه References کلیک راست کرده و گزینه Add Reference را انتخاب میکنیم (شکل ۹).
شکل ۹
با انتخاب این گزینه پنجرهای برای انتخاب ارجاع جدید مطابق شکل ۱۹ باز خواهد شد. با باز شدن این صفحه روی گزینه Browse کلیک میکنیم و با مراجعه به آدرسی که دو فایل dll عنوان شده در قسمت پیشین در آن قرار دارند، این دو فایل را انتخاب کرده و دکمه OK را کلیک میکنیم تا دو راهانداز مورد بحث به بخش References افزوده شوند . پس از اضافه شدن این دو ارجاع، میتوانیم کار کدنویسی را آغاز کنیم.
اعمال ساده در راهانداز سي شارپ
همانطور که عنوان شد ما با ساخت یک پروژه ساده کنسول، قصد داریم تا به تمرین کارکردهای پایهای راهانداز سي شارپ در تعامل با پایگاه دادههای MongoDB بپردازیم. پس بگذارید تا کار را با یک واکشی ساده از پایگاهداده retrogames با دو روش متفاوت آغاز کنیم.
در روش نخست شما میتوانید کلاسهای خود را برای نمایش مستندات و انجام نگاشتهای ضروری به زبان سي شارپ بنویسید. در نتیجه هرگاه که شما مستندی را از پایگاههای داده میخوانید، یک شی سي شارپ موسوم به POCO (سرنام Plain Old C# Object) دریافت میکنید.
درواقع در اینجا، راهانداز استفاده شده برای تعامل میان زبان برنامهنویسی مورد استفاده و پایگاه داده، مستند BSON را با استفاده از deserialization به یک نمونه POCO تبدیل میکند. بهطور مشابه، عکس این رابطه در زمان اضافهکردن یک مستند روی میدهد. به این معنا که هرگاه شما برای افزودن یک مستند یک نمونه POCO تولید میکنید، راهانداز مورد بحث، با استفاده از فرآیند serialization، این شئ را به یک مستند BSON تبدیل کرده و برای MongoDB ارسال میکند.
توجه داشته باشید که اگر این روش تعامل را برگزینید، ممکن است بهلحاظ انعطافپذیری در لایههای زیرین شِمای مورد استفاده با مشکلاتی مواجه شوید. درواقع راهحلی دیگری وجود دارد که این امکان را فراهم میآورد تا با حفظ انعطافپذیری شِمای زیرین و از طریق کار با نمونههای BsonDocuments خالص به تعامل با پایگاههای داده بپردازید. موضوعی که در ادامه این مطلب به آن خواهیم پرداخت.
اما بد نیست برای روش نخست تعامل، یعنی استفاده از POCO مثالی عملی را پیاده کنیم. برای این منظور ما روی ساخت کلاسها دامنه تمرکز خواهیم کرد. ابتدا یک رابط (Interface) جدید با نام IMongoEntity ساخته و قطعه کد زیر را درون آن قرار میدهیم (برای اضافهکردن یک رابط کافی است روی نام پروژه خود راست کلیک کرده و از منوی Add گزینه New Item را انتخاب و سپس روی گزینه Interface کلیک کنید):
using System; using MongoDB.Bson; namespace RetrogamesConsole { public interface IMongoEntity { ObjectId Id { get; set; } } }
این رابط، یک فیلد Id از نوع MongoDB.Bson.ObjectId را تعریف میکند که در واقع نمایانگر یک BSON ObjectId است. در مرحله بعد یک کلاس جدید با نام MongoEntity را به پروژه اضافه میکنیم که رابط IMongoEntity ساخته شده در مرحله پیشین را پیادهسازی میکند:
using System; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace RetrogamesConsole { public class MongoEntity { [BsonId] public ObjectId Id { get; set; } } }
همانطور که در کد این کلاس مشخص است، Mongo Entity.cs از خصیصه MongoDB.Bson.Serialization.Attributes.BsonIdAttribute (BsonId) برای مشخص ساختن این موضوع که فیلد Id در فرآیندهای serialization و deserialization باید به فیلد id_ هر مستند نگاشت شود، استفاده شده است. برای درک بهتر موضوع، چنانچه دوباره نگاهی به زبانه Text View مجموعه game در نرمافزار MongoVUE بیاندازید (فهرست زیر)، بهراحتی فیلدهایی را که برای شناسایی یک مستند game مورد نیاز هستند، مشاهده خواهید کرد.
/* ۰ */ { "_id" : ObjectId("51e10c50085977bc3cd92a65"), "name" : "Invaders 2013", "release_date" : ISODate("2013-04-01T19:30:00Z"), "categories" : ["space", "shooter", "remake"], "played" : true }
در این مرحله کلاس دیگری به نام Game خواهیم ساخت که از کلاس MongoEntity ارث میبرد:
using System; using System.Collections.Generic; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; namespace RetrogamesConsole { [BsonIgnoreExtraElements] public class Game : MongoEntity { public Game() { Categories = new List<string>(); } [BsonElement(«name»)] public string Name { get; set; } [BsonElement(«release_date»)] public DateTime ReleaseDate { get; set; } [BsonElement(«categories»)] public List<string> Categories { get; set; } [BsonElement(«played»)] public bool Played { get; set; } } }
در اینجا کلاس Game از خصیصه MongoDB.Bson.Serialization.Attributes.BsonElementAttribute (BsonElement) برای مشخص ساختن نام فیلد اطلاعاتی سند BSON استفاده میکند که باید به ویژگی آن نگاشت شود. بنابراین، فرآیند serialization بهدرستی میداند که مقدار فیلد release_date بهویژگی ReleaseDate تخصیص مییابد.
توجه کنید که از آنجا که ما در این پروژه بهجای استفاده از نام فیلدهای اطلاعاتی موجود در سند از نامهایی با نگارش متفاوت استفاده کردهایم (برای مثال، از نام ReleaseDate برای مقداردهی و خواندن مقدار فیلد release_date استفاده شده است) لازم است تا این موضوع را با استفاده از کدهایی مانند [BsonElement(“release_date”)] برای کامپایلر سي شارپ مشخص کنیم تا فرآیند serialization بتواند بهصورت خودکار انجام شود. طبیعی است که اگر این تغییر نام صورت نپذیرد نیازی به استفاده از این کدها نخواهد بود.
ذکر این نکته ضروری است که با استفاده از برخی کدها میتوان رفتار عادی فرآیند serialization را تحتتأثیر قرار داده و تغییر داد. برای مثال، شما با استفاده از کد زیر میتوانید نمایش BSON در داتنت را به BSON Int64 تغییر دهید:
[BsonRepresentation(BsonType.Int64)]
حال با ایجاد این کلاسها، زمان آن رسیده است تا قسمت اصلی برنامه که با پایگاه داده MongoDB تعامل میکند را اضافه کنیم. برای این منظور کلاسی با نام Program.cs ایجاد کرده و کد زیر را درون آن قرار میدهیم. این کد با استفاده از تابع FindOne نخستین سند موجود در مجموعه games که فیلد اطلاعات name آن برابر با “Invaders 2013” است را دریافت میکند. ما در این کد برای حفظ سادگی، هیچگونه کدی برای پشتیبانی از شرایط خطا را قرار ندادهایم و در نتیجه درصورت لزوم میتوانید خودتان این کدها را اضافه کنید. در این قطعه برنامه، راهانداز استفاده شده، سند BSON را با استفاده از فرآیند deserialization به یک نمونه (Instance) از کلاس Game تبدیل میکند (شکل ۱۰).
شکل ۱۰
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.Builders; using MongoDB.Driver.GridFS; using MongoDB.Driver.Linq; namespace RetrogamesConsole { class Program { static void Main(string[] args) { //// Warning: The following code is an example without the appropriate //// Exception handling var connectionString = «mongodb://localhost»; //// Get a thread-safe client object by using a connection string var mongoClient = new MongoClient(connectionString); //// Get a reference to a server object from the Mongo client object var mongoServer = mongoClient.GetServer(); //// Get a reference to the «retrogames» database object from the Mongo ////server object var databaseName = «retrogames»; var db = mongoServer.GetDatabase(databaseName); //// Get a reference to the «games» collection object from the Mongo ///database object var games = db.GetCollection<Game>(“games”); var gameQuery = Query<Game>.EQ(g => g.Name, “Invaders 2013”); var foundGame = games.FindOne(gameQuery); } } }