BulkInsert در EF CodeFirst
مقدمهای بر Docker
دو مفهوم اساسی در محیط Docker وجود دارند که دانستن آنها ضروری است: Image و Container
image عملا چیزی است که از آن برای Build یک Container استفاده میشود. image دارای یک سری فایلهای لازم و اساسی است که باعث میشود بر روی یک Operation System اجرا شود؛ مثل Ubuntu یا Windows. بنابراین شما Application Framework خود را خواهید داشت و همچنین Databaseی که با آن کار میکند. بنابراین قابلیت استفاده از زبانها و فریم ورکهای مختلف چون Asp.net Core, Nodejs, Python و غیره را خواهد داشت. یک image به خودی خود غیر قابل استفاده است تا زمانیکه بر روی یک Container توزیع شده باشد، تا قابلیت اجرا پیدا کند. بنابراین نقطهی شروع اصلی اجرایی یک برنامه با Container مربوط به آن میباشد.
به صورت خلاصه Image یک template از نوع Readonly است که ترکیبی از لایههای File System میباشد، به همراه فایلهای share شدهی دیگر (از قبیل فریم ورکها و ...) که میتوانند یک Docker Container Instance را تولید نمایند.
Container یک محیط امن و ایزوله است که به وسیلهی image ساخته شده است و میتواند اجرا، متوقف، منتقل و یا حذف شود (بطور قابل ملاحظهای اجرا کردن و متوقف کردن آن سریع میباشد).
تفاوت Docker Containers و Virtual Machines
Virtual Machines همیشه بر روی Host Operation System اجرا میشوند (که میتواند بر روی ویندوز یا لینوکس باشد) و بعد از آن اجرای Guest OS بر روی سطحی به نام Hypervisor. پس میتوان گفت یک کپی کامل از سیستم عامل است که که بر روی hypervisor اجرا میشود و خودش نیز بر روی سخت افزار اجرا میشود. بنابراین میتوان مثل شکل زیر، یک App داشت که عملا یک سری باینری و کتابخانه است و اگر قرار باشد بر روی سیستم عاملهای مختلفی کار کند، احتیاج به کپی کردن کل آن میباشد و بطور واضحی زمان و هزینهی بیشتری برای بالا آوردن آن لازم است.
اما بر خلاف آن، داکر با استفاده از ابزاری به نام Docker Engine کار میکند که میتواند Containerهای مختلفی از OSهای مختلف را اجرا نماید و نیازی به کپی گرفتن از کل سیستم عامل برای اجرای هر container نخواهد بود.
بنابراین با استفاده از ابزارهای مجازی سازی چون Vmware، نسخهی کاملی را از سیستم عامل مطبوع خود میتوان نصب و اجرا نمود؛ اما برخلاف آن با استفاده از داکر، یک نسخهی کوچک از سیستم عامل، بدون وابستگیها و پیچیدگیهای نسخهی اصلی در اختیار خواهد بود.
با این وجود، بوسیله داکر به راحتی میتوان تعداد زیادی از Containerها را به راحتی و با سرعت بالا اجرا نموده و مورد تست و ارزیابی قرار داد.
چطور Docker میتواند سریعتر از Virtual Machineها عمل کند ؟
داکر از چیزی به نام Copy On Write استفاده میکند؛ به معنای کپی کردن همزمان با نوشتن. همانطور که گفته شد هر Container از یک Image ساخته میشود و عملا Imageها همان FileSystemهای از قبل تولید شده هستند و هر کدام از لایهای از کتابخانهها استفاده میکنند که برای اجرای برنامههای کاربردی مورد استفاده قرار میگیرند. سرور آپاچی را در نظر بگیرید، به عنوان یک فایل image که FileSystem بر روی آن ذخیره شدهاست. با نصب Php یک لایه بر روی لایه دیگر ایجاد شده و فقط تغییرات جدید به آن اضافه خواهند شد و حال اگر بخواهید تغییری را بر روی source code خود بدهید، عملا فقط آن تغییر به Image و FileSystem اضافه خواهد شد. این معماری لایه لایه باعث تولید یک FileSystem بصورت read-only میشود که شامل لایههای متفاوتی است و سبب کم حجم شدن آن، بالا رفتن سرعت آن میشود و همچنین با استفاده از Caching، قدرت زیادی را بدان میبخشد.
پس همانطور که در شکل فوق مشاهده میکنید، هر image از لایههای مختلفی تشکیل شده است و توانایی به اشتراک گذاشتن این لایههای متمایز از یکدیگر در Containerها وجود دارد.
بنابراین طبق شکل فوق، بحث را اینگونه خلاصه میکنیم که هر Image از ترکیبی از لایههایی از نوع read-only تشکیل شده است و با اضافه شدن Container، عملا یک لایهی دیگری که قابلیت read/write را دارد بر روی آن اضافه میشود و درون آن source code میتواند قرار گیرد و اینکه بر مبنای شکل زیر میبینید که قابلیت به اشتراک گذاری Image layerها به Containerهای مختلف تعبیه شده است که باعث میشود لایهی نصب شده بر روی سیستم، بصورت اشتراکی قابل استفادهی مجدد باشد و فضای دیسک کمتری، به علاوه سرعت اجرای بالاتری را داشته باشد. هر لایه یک مقدار هش شدهی یکتایی را در اختیار دارد تا از لایههای دیگر تمیز داده شود و قابل شناسایی باشد.
داکر در شبکه چگونه کار میکند؟
ضمنا نکتهی قابل توجه که در مقالههای بعدی به صورت عملی به آن میپردازیم این است که با استفاده از داکر میتوانیم وب سرورهایی را بر روی Containerهای مختلفی داشته باشیم که همگی بر روی پورت بطور مثال 80 هستند؛ طوری که درون هر Container بدلیل ایزوله بودن پروسسهای مخصوص Container مربوط به خود، به پورتهای باز داخل آن شبکه دسترسی دارند و میتوانند پورت در نظر گرفته شدهی درون Container را با پورت دیگری بیرون Container به اصطلاح Expose نمایند.
ضمن اینکه نکتهی دیگری که وجود دارد، ارتباط Containerها با یکدیگر است. برای مثال یک Container برای Database و دیگری برای WebApp میباشد که باید به همدیگر link شده تا قابل استفاده گردند و عملا نیازی به نوشتن ip یکدیگر در این حالت وجود ندارد. البته راههای دیگری از قبیل Compose کردن نیز وجود دارد که در ادامه بیشتر با آنها آشنا خواهیم شد.
Docker Volume چیست؟
بحث دیگری که وجود دارد، Volumeها هستند که قسمتی از FileSystemها میباشند و بصورت ساده، مثال کاربردیاش میتواند قسمتی از یک سیستم و دایرکتوری خاصی را بر روی Container خاصی Map کردن باشد و عملا داخل آن دایرکتوری میتواند source code بوده باشد (یکی از راههای ممکن برای map کردن source code به container) و بر روی Container ایجاد شود.
فوایدی که با استفاده از Volumeها میتوان به آن رسید از قبیل موارد زیر میباشند:
قابلیت به اشتراک گذاری یک Volume بین Containerهای مختلف که به شدت میتواند قابل استفاده باشد.
Data Volumeها ماندگار هستند. یعنی حتی بعد از اینکه Container مربوطه را حذف نمایید، volume مربوط به آن بطور اتوماتیک حذف نمیشود (مگر اینکه خودتان دستور حذف کردن آن را وارد نمایید). پس عملا قابلیت استفادهی مجدد را نیز خواهد داشت.
طبق شکل فوق ما میتوانیم درون یک container یک volume داشته باشیم. وقتی ما چیزی را درون آن مینویسیم عملا داریم در قسمت خاصی به نام Docker Host عمل write کردن را انجام میدهیم که باعث میشود داکر متوجه آن شود. وقتی اسمی را به یک Volume انتساب میدهیم همانند /var/www، در واقع یک اسم مستعار (alias) میباشد که اشاره میکند به این Docker host موجود. در ادامه بیشتر با Volumeها آشنا خواهیم شد.
DockerFile و ساخت imageها چگونه است؟
روش دیگر برای اجرای source code در داکر، ساخت یک image اختصاصی از آن و اجرا کردن آن بر روی یک container مجزا است. با استفاده از DockerFile میتوانید imageهای خود را build کرده که عملا هر image در آخر باید به یک سیستم عامل برسد و همانطور که گفته شد به صورت لایهای کار میکنند و مراتب اجرای آن از قبیل working directory و expose کردن بر روی پورتی خاص، همچنین استفاده از Environment Variableها میباشد و همچنین با استفاده از DockerHub (که نسخهی enterprise نیز دارد) میتوان imageهای ساخته شده را بر روی cloud نگه داشت و همهی اعضای تیم از یک image بخصوص استفاده کنند؛ برای مثال همهی اعضای تیم از یک نسخهی Nodejs استفاده کنند و اشتباها بر روی ماشینهای توسعهی مختلف برنامه نویسان، از نسخههای مختلفی استفاده نشود و همچنین روند بهروز رسانی به سادگی انجام گیرد.
مزایای Docker برای برنامه نویسان
فرض کنید که یک App Service از Azure تهیه کرده باشید. تستهای unit, integration, acceptance را انجام داده و با خیال راحت Container خود را از طریق برای مثال Visual studio team service بر روی App service به صورت انتشار از طریق مدل Continuous Integration و Continuous Deployment داشته باشید. پس عملا داکر به Devops بودن محیط و چابک بودن تیم توسعه کمک شایانی کرده و فرآیندهای سخت و زمانبر انتقال Codeها از محیط توسعه به محیط انتشار را تسریع میبخشد.
بنابراین از داکر به راحتی میتوان در محیط Production نیز استفاده کرد و مزایای فوق العاده ای را برای برنامه نویسان ارائه کرده است. بطور مثال فرض کنید در تولید نرمافزار یک Web server ، تعدادی Database و یک Caching server که کانفیگ کردن، اجرا و ... به صورت عادی بسیار صعب و مشکل ساز بوده را به راحتی میتوان اجرا نمود. ضمن اینکه ممکن است هر کدام از ابزارهایی که استفاده شده، فقط مخصوص سیستم عاملی خاص باشد که قاعدتا احتیاج به بالا آوردن Virtual Machine خواهید بود و در سناریوهای خاصی مثل سیستم هایی با معماری Microservice که هر کدام از این ریز سرویسها ممکن است زبان، فریم ورک، دیتابیس و ... مخصوص به خود را داشته باشند، عملا کار بسیار سخت و پر هزینه خواهد بود (ضمن اینکه استفادهی همزمان از چند Virtual Machine در کنار هم در محیط توسعه، حجم زیادی از memory و disk سیستم شما را خواهد گرفت و شما را مجبور به ارتقای سیستم خود خواهد کرد!).
مشکل دیگری که Docker آن را حل کرده، Conflictهای ورژنهای مختلف ابزارهای مورد استفاده است. به راحتی میتوان Containerی از Imageها را به صورت ایزوله با ورژنهای مختلفی ایجاد کرد تا بطور کامل برنامه نویسان را از مشکل همیشگی بهروزرسانیها و Role-back کردنها آسوده خاطر نماید.
از آنجایی که داکر قابلیت اجرای در محیط production را نیز دارد، عملا محیط Development با محیط Production تفاوتی ندارد و این جملهی معروف که «در سیستم من کار میکند اما در نسخهی انتشار داده شده خیر» دیگر اتفاق نخواهد افتاد.
به راحتی میتوانید از یک Image خاص، Containerهای ایزولهی متفاوتی را ساخته و همگی آنها را در کنار هم اجرا نمود و مورد تست و ارزیابی قرار داد.
Dokcer hub
مخرنی است از هزاران Image آماده از قبیل سیستم عامل، فریم ورک و... که قابلیت استفادهی مجدد خواهد داشت. همچنین شما میتوانید Imageهای خود را نیز بدان اضافه نموده تا دیگران از آن استفاده نمایند. استفاده از مخزنهای public آن رایگان میباشد. از آنجایی که Docker یک محصول متن باز و رایگان است، یک بخش از درآمدهای آن از فروش اختصاصی مخزنها در DokcerHub میباشد (چیزی شبیه به Private Repository در Github).
بیشتر از این به مفاهیم نمیپردازیم. برای مطالعهی بیشتر، کتاب فوق العادهی Mastering Docker را پیشنهاد میکنم.
شروع به کار با Docker
بعد از نصب کردن نسخهی رسمی Docker و باز کردن ترمینال مربوطه، اولین دستوراتی را که باید با آن آشنا باشیم، شامل موارد زیر میباشد:
لیست Imageهای کش شدهی بر روی سیستم:
docker images
docker ps
برای آزمایش کردن و نصب اولین image، دستور زیر را وارد میکنیم (میتوانید اطلاعات بیشتری از imageها را در dockerHub پیدا کنید). من در اینجا kitematic/hello-world-nginx را به عنوان image از مخزن dokcerhub، بر روی سیستم خود pull کردهام (این یک نسخهی بسیار سبک از کانتینر nginx میباشد).
docker pull kitematic/hello-world-nginx
حال وقت اجرای این image و توزیع آن بر روی container میباشد که با استفاده از دستور زیر است:
docker run -p 80:80 kitematic/hello-world-nginx
بعد از اجرای این دستور میتوانید با وارد کردن ip مربوط به virtual machine ساخته شده بر روی سیستم خود (اگر از مک یا ویندوز استفاده میکنید احتمالا 192.168.99.100 خواهد بود) که البته با دستور docker-machine ip میتوانید آن را پیدا کنید و وارد کردن آن بر روی مرورگر خود، تصویری مثل زیر را مشاهده کنید:
بدین معناست که container شما اجرا شده و قابلیت مورد استفاده قرار گرفتن را خواهد داشت. حال اگر دستور docker ps را مجددا وارد نمایید، اطلاعات این container را از نوع id, status port و غیره، مشاهده خواهید کرد.
چرا از این نوع داده استفاده کنیم؟
نخستین پرسشی که ممکن است برای شما پیش بیاید این است که چرا بهتر است از این نوع داده استفاده کنیم. برای پاسخ به این پرسش باید راهکارهای گذشته را بررسی کنیم. معمولاً طراحان پایگاه دادهها برای استفاده از تاریخ خورشیدی، زمان را به صورت میلادی ثبت میکنند؛ سپس با یک scalar-valued function زمان درج شده را به خورشیدی تبدیل میکنند. در این صورت میتوان با یک تابع کوچک دیگر بخش مربوط به ساعت را نیز از همان ستون به دست آورد. در این صورت میتوانیم از کلیهی متدهای مربوط به DateTime در SQL از جمله افزایش و کاهش و تفاضل دو تاریخ بهره برد. برخی دیگر از طراحان، ستونی از نوع (char(10 در نظر میگیرند و تاریخ خورشیدی را به صورت دهکاراکتری در آن ذخیره میکنند. این روش هرچند نیاز به تبدیل به خورشیدی را ندارد ولی کلیهی مزایایی که در استفاده از DateTime به آنها دسترسی داریم از دست میدهیم. افزون بر این جهت نگهداری زمان باید یک فیلد دیگر از نوع کاراکتری و یا در نگارشهای نوینتر از نوع time تعریف کنیم. برخی دیگر از هر دو را در کنار هم استفاده میکنند و در واقع جهت سرعت بالاتر نمایش و بررسی دادهها از طریق محیط SQL Server از فیلد کاراکتری تاریخ خورشیدی و برای مقایسه و بدست آوردن ساعت از فیلد نوع DateTime استفاده میکنند.
از نظر فضای اشغالشده نوع DataTime، هشت بایت، smalldatetime (در صورت استفاده) 4 بایت و فیلد 10 کاراکتری تاریخ 10 بایت فضا اشغال میکند در صورتی که نوع JalaliDate با درنظر گرفتن همهی مزایای انواع دادهی استفادهشده برای تاریخ، فقط 8 بایت فضا اشغال میکند. با استفاده از این نوع به راحتی دادهی تاریخ را بر اساس تقویم ایرانی اعتبارسنجی میکنید و بخشهای مختلف زمان از سال تا ثانیه را با یک متد به دست میآورید. میتوانید به راحتی به تاریخ خود زمانی را بیفزایید یا بکاهید و در گزارشها بدون نگرانی از تبدیل درست استفاده کنید. چون کدباز است میتوانید با کمی حوصله امکانات دیگر مد نظر خود را به آن بیفزایید و از آن در SQL بهره ببرید.
چگونه این نوع داده را حذف کنم!؟
شما میتوانید به سادگی نوع دادهی ایجادشده توسط CLR را در مسیر زیر بیابید و اقدام به حذف آن نمایید:
همانطور که مشاهده میشود؛ حتی نوع دادهی سیستمی hierarchyid که جهت ساختار سلسلهمراتبی مانند چارت سازمانی یا درخت تجهیزات استفاده میشود؛ نیز یک نوع دادهی CLR است.
آیا راه دیگری نیز برای افزودن این نوع داده به SQL به جز Publish کردن وجود دارد؟
مانند بسیاری دیگر از گونههای پروژه، در اینجا نیز شما یک فایل DLL خواهید داشت. این فایل برپایهی تنظیماتی که شما در قسمت Properties پروژهی خود انجام میدهید ساخته میشود. پس از تغییر مسیر فایل DLL در دستور زیر توسط یک New Query از Database خود، آن را اجرا کنید:
CREATE ASSEMBLY JalaliDate FROM 'F:\prgJalaliDate.dll' WITH PERMISSION_SET = SAFE;
ALTER ASSEMBLY JalaliDate FROM 'F:\prgJalaliDate.dll'
select * from sys.assemblies select * from sys.assembly_files
CREATE TYPE dbo.JalaliDate EXTERNAL NAME JalaliDate.[JalaliDate];
همچنین چنانچه در SQL Server 2012 از منوی راستکلیک پایگاه دادهها روی گزینه Tasks و سپس Generate Scripts را انتخاب کنیم، از مشاهدهی سند ساخته شده، درخواهیم یافت که حتی دستورهای مربوط به ساخت اسمبلی CLR با تبدیل فایل به کد در Scripts وجود دارد و با اجرای آن در سروری دیگر، انتقال مییابد.
GO /****** Object: SqlAssembly [prgJalaliDate] Script Date: 2013/04/30 08:27:00 ب.ظ ******/ CREATE ASSEMBLY [prgJalaliDate] FROM 0x4D5A90000300000004000000FFFF0000B8000000000000 ..... بقیهی کدها حذف شده WITH PERMISSION_SET = SAFE GO ALTER ASSEMBLY [prgJalaliDate] ADD FILE FROM 0x4D6963726F736F667420432F432B2B204D534620372E30300D0A1A44530..... بقیهی کدها حذف شده AS N'prgJalaliDate.pdb' GO /****** Object: UserDefinedType [dbo].[JalaliDate] Script Date: 2013/04/30 08:27:00 ب.ظ ******/ CREATE TYPE [dbo].[JalaliDate] EXTERNAL NAME [prgJalaliDate].[JalaliDate] GO
دنباله دارد ...
docker pull node
docker images
در ادامه نیاز داریم یک دایرکتوری را ایجاد کرده و فایل index.js را درون آن بسازیم:
mkdir testapp cd testapp touch index.js npm init npm i express --save
یک دایرکتوری را ساختیم و همچنین express را نیز نصب نمودیم.
اکنون package.json را باز کرده و این قسمت را جایگزین کنید؛ تا با استفاده از npm start، برنامه اجرا شود:
"scripts": { "start": "node index" }
index.js را باز کرده و کدهای زیر را وارد کنید:
const express = require('express') const app = express() const PORT = 3000; app.get('/', function (req, res) { res.send('Hello World') }) app.listen(PORT, function () { console.log(`listening on port ${PORT}!`) })
همه چیز خیلی ساده در نظر گرفته شده است. از فریمورک express استفاده کردیم و یک سرور را بر روی پورت 3000 اجرا کرده و همچنین بر روی آدرس "/" یک سطر کد Hello World اجرا میشود.
خوب، فرض کنید قصد داریم با استفاده از volume، کد فوق را بر روی container اجرا کنیم.
برای اجرا شدن این کدها بر روی Volume، دستور زیر را درون ترمینال خود وارد کنید:
docker run -d -p 3030:3000 -v $(pwd):/var/www -w "/var/www" node npm start
شرح دستور فوق:
دستور ساخت container با استفاده از ارگومان run
d- برای اجرا شدن container در حالت detached، باعث میشود اجرا شدن آن در حالت بکگراند بوده و بتوانید بر روی ترمینال مربوطه، دستورات دیگری را وارد نمایید.
p- پورت داخلی و خارجی را مشخص میکند. در اینجا پورت داخلی، 3000 و خارجی، 3030 میباشد.
آرگومان v- برای ساخت volume و (pwd)$ دایرکتوری جاری را بر روی سیستم شما، نشان خواهد داد. بعد از آن /var/www یک دایرکتوری فرضی است (هر آدرس دلخواهی را میتوانیم داشته باشیم) که قرار است بوسیلهیdocker ساخته شود و از آن اشارهگری به دایرکتوری جاری بر روی ماشین محلی زده شود.
w- همان WorkingDirectory میباشد. بدلیل اینکه میخواهیم بر روی container به دایرکتوری که کدهای ما وجود دارد، وارد شود.
بعد از آن اسم image ای را که قرار است از آن استفاده شود، آورده تا container ایجاد شود.
و بعد از npm start برنامه را اجرا خواهد کرد.
پس از اجرا کردن دستور فوق، container ایجاد میشود و قابلیت اجرایی دارد (با استفاده از ip و port خارجی بر روی browser میتوانیم برنامه را مشاهده کنیم).
حال با استفاده از دستور زیر لیست containerهای اجرایی را مشاهده خواهیم کرد:
docker ps
میبینید که container، اجرا شده و پورت آن مشخص شدهاست. تصویر و کلید هش شدهی منحصر به فرد آن را نیز مشاهده میفرمایید.
حتی میتوانید به راحتی درون container را با استفاده از دستور زیر مشاهده کنید:
docker exec -it 6003 bash
6003 ابتدای کلید container ایجاد شدهاست و با استفاده از bash وارد محیط command line در container ایجاد شده خواهیم شد و دسترسی کاملی خواهیم داشت.
بطور مثال برای دیدن کدهای index.js بر روی container ایجاد شده، بعد از دستور فوق، command زیر را وارد نمایید:
cat index.js
جالب است بدانید از آنجائیکه container از طریق volume به دایرکتوری محلی شما لینک شدهاست، به محض اینکه بر روی سیستم خود کدی را تغییر داده و دوباره دستور فوق را اجرا کنید، تغییرات را مشاهده خواهید کرد.
برای متوقف کردن container از دستور زیر باید استفاده کرد:
docker stop 6003
نکته: 6003 آی دی container است و برای اجرای مجدد آن docker start 6003
بعد از متوقف کردن container و اجرای دستور docker ps متوجه خواهید شد که دیگر Container در لیست containerهای باز نیست.
با استفاده از دستور زیر به لیست تمامی Containerها چه در حال اجرا و چه متوقف شده، دسترسی خواهیم داشت:
docker ps -a
برای حذف container نیز از دستور زیر استفاده میکنیم:
docker rm -v 6003
rm برای حذف container و همچنین v- برای حذف volume میباشد.
ASP.NET MVC #7
توضیح تکمیلی:
- کلاس پایهای در ASP.NET MVC وجود دارد به نام (^)WebViewPage. این کلاس حاوی تعاریف اولیه TempData، ViewBag، ViewData و ... Model است. این Model ریشهاش به اینجا بر میگردد و با حرف بزرگ شروع شده است. بنابراین در Viewهای سی شارپ Razor برای تعریف نوع مدل نیاز است بین model و شیء Model تفاوت وجود داشته باشد.
- در یک View شما هر تعداد مدل رو میتونید از طریق ViewBag و ViewData و غیره که در قسمت 5 توضیح داده شده، دریافت کنید و محدودیتی ندارد. اما اینها هیچکدام به معنای Strongly typed بودن View نیست. بنابراین برای حالت داشتن View از نوع Strongly typed، یکبار باید این نوع، تعریف شود.
البته یک راه هوشمندانه برای ارسال بیش از یک شیء به Model وجود دارد. یک کلاس تعریف کنید که خواص آن چندین شیء مورد نظر شما باشند. سپس این کلاس را به عنوان نوع Model در ابتدای View معرفی کنید. در اینجا به راحتی و به صورت Strongly typed با چند شیء میشود به عنوان Model کار کرد.
AngularJS #2
Install-Package angularjs
<!DOCTYPE html> <html ng-app> <head> <title>Sample 1</title> </head> <body> <div ng-controller="GreetingController"> <p>{{greeting.text}}, World!</p> </div> <script src="../Scripts/angular.js"></script> <script> function GreetingController($scope) { $scope.greeting = { text: "Hello" }; } </script> </body> </html>