Learn ASP.NET Core MVC (.NET 8) - The Complete Guide
In this Complete Guide course, we will learn MVC (Model-View-Controller) with .NET 8.
When we are working with .NET Core Web Applications, there are two common ways of building website.
1. MVC (Model-View-Controller) Web Application
2. Razor Pages Web Application
In this course we will learn the basics of .NET Core (.NET 8) and then learn basics of MVC and Razor Pages as we enhance MVC Application to a more complex final project!.
Topics Covered
- Fundamentals of .NET Core
- MVC Application
- Razor Pages
- Entity Framework Core
- Repository Pattern
- ViewBag
- ViewData
- TempData
- Taostr and sweet alerts in .NET Core
- Datatables in .NET Core
- Assignments
- Errors and how to solve them!
همانطور که مطلع هستید در تنظیمات یک دایرکتوری مجازی در IIS6 یا 5، حتی پس از نصب دات نت فریم ورک سه و نیم، گزینه انتخاب نگارش 3.5 ظاهر نمیشود و همان تنظیمات ASP.Net 2.0 کافی است (شکل زیر) (دات نت 3 و سه و نیم را میتوان بعنوان افزونههایی با مقیاس سازمانی (WF ، WCF و ...) برای دات نت 2 درنظر گرفت).
هنگام استفاده از VS.Net 2008 و تنظیم نوع پروژه به دات نت فریم ورک 3.5 ، به صورت خودکار تنظیمات لازم به وب کانفیگ برنامه جهت استفاده از کامپایلرهای مربوطه نیز اضافه میشوند که شاید از نظر دور بمانند.
برای آزمایش این مورد، فرض کنید صفحه زیر را بدون استفاده از code behind و VS.Net ایجاد کرده ایم (جهت آزمایش سریع یک قطعه کد Linq ).
<%@ Page Language="C#" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Linq" %>
<form id="Form1" method="post" runat="server">
<asp:GridView ID="GridView1" runat="server" />
</form>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
string[] cities = {
"London", "Amsterdam", "San Francisco", "Las Vegas",
"Boston", "Raleigh", "Chicago", "Charlestown",
"Helsinki", "Nice", "Dublin"
};
GridView1.DataSource = from city in cities
where city.Length > 4
orderby city
select city.ToUpper();
GridView1.DataBind();
}
</script>
این قطعه کد چون از قابلیتهای کامپایلر جدید سی شارپ استفاده میکند، با کامپایلر پیش فرض و تنظیم شده دات نت 2 کار نخواهد کرد و باید برای رفع این مشکل، فایل web.config جدیدی را نیز به پوشه برنامه اضافه کنیم:
<?xml version="1.0"?>
<configuration>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>
<system.web>
<compilation defaultLanguage="c#">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
</system.web>
</configuration>
همانطور که ذکر شد اگر از VS.Net 2008 استفاده کنید، هیچ وقت درگیر این مباحث نخواهید شد و همه چیز از پیش تنظیم شده است.
- Grid Panel
- Stack Panel
- Dock Panel
- Wrap Panel
- Canvas Panel
StackPanel
<StackPanel> <TextBlock Margin="10" FontSize="20">How do you like your coffee?</TextBlock> <Button Margin="10">Black</Button> <Button Margin="10">With milk</Button> <Button Margin="10">Latte machiato</Button> <Button Margin="10">Chappuchino</Button> </StackPanel>
نکتهی مهم اینکه میتوانید در اینجا از یک nested layout هم استفاده کنید بدین صورت که یک layout را داخل یک layout دیگر قرار دهید. کد زیر ترکیب دو stack panel را به صورت افقی و عمودی به ما نشان میدهد:
<StackPanel Orientation="Vertical"> <!-- Vertical is the default --> <Label Background="Red">Red 1</Label> <Label Background="LightGreen">Green 1</Label> <StackPanel Orientation="Horizontal"> <Label Background="Red">Red 2</Label> <Label Background="LightGreen">Green 2</Label> <Label Background="LightBlue">Blue 2</Label> <Label Background="Yellow">Yellow 2</Label> <Label Background="Orange">Orange 2</Label> </StackPanel> <Label Background="LightBlue">Blue 1</Label> <Label Background="Yellow">Yellow 1</Label> <Label Background="Orange">Orange 1</Label> </StackPanel>
Dock Panel
احتمالا به خاطر نامش، نحوه کارش را حدس زده اید. این پنل، اشیاء موجود را در 4 جهت و مرکز میچسباند. مشخص نمودن جهت چسبیده شدن هر کنترل توسط خاصیت DockPanel.Dock صورت میگیرد و مقدار Left، مقدار پیش فرض است. در صورتی که بخواهید المانی را در مرکز بچسبانید باید آن را به عنوان آخرین المان معرفی کرده و در Dock Panel مقدار خاصیت LastChildFill را با True برابر کنید.
<DockPanel LastChildFill="True"> <Button Content="Dock=Top" DockPanel.Dock="Top"/> <Button Content="Dock=Bottom" DockPanel.Dock="Bottom"/> <Button Content="Dock=Left"/> <Button Content="Dock=Right" DockPanel.Dock="Right"/> <Button Content="LastChildFill=True"/> </DockPanel>
به نحوهی تعریف خاصیت DockPanel.Dock دقت کنید به این نوع خاصیتها، Attached Dependency Property (شاید در فارسی بتوانیم خاصیتهای وابستگی متصل صدا بزنیم) میگویند. این خاصیتها نوع خاصی از خاصیتهای وابستگی هستند که به شما اجازه میدهند مقداری را به شیءایی نسبت دهید که آن شیء چیزی در مورد آن نمیداند. بهترین مثال در مورد این ویژگی، پنلها هستند که یکی از موارد استفادهی از آن را در بالا میبینید. هر پنل میتواند تا بی نهایت المان فرزند داشته باشد که هر المان باید خواصش توسط پنل مشخص گردد. ولی اگر پنل ما تعداد زیادی فرزند داشته باشد، نوشتن خواص هر کدام از فرزندها داخل تگ پنل، کاری غیر ممکن است. اینجاست که این نوع خاصیتها خودشان را نشان میدهند. پس به این نحو مقادیر، داخل کنترل هر تگ تعریف میشود ولی توسط پنل مورد استفاده قرار میگیرد. نحوهی نوشتن این نوع خاصیت: ابتدا یک پیشوند از نوع تگ پنل را در ابتدا آورده و سپس بعد از .(نقطه) نام خاصیت را ذکر میکنیم.
نحوهی تعریف این نوع خاصیتها در یک کلاس به صورت زیر است که برای شیء یا پنل canvas میباشد:
public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached("Top", typeof(double), typeof(Canvas), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.Inherits)); public static void SetTop(UIElement element, double value) { element.SetValue(TopProperty, value); } public static double GetTop(UIElement element) { return (double)element.GetValue(TopProperty); }
<Button Content="Dock=Top" DockPanel.Dock="Top"/> <Button Content="Dock=Bottom" DockPanel.Dock="Bottom"/> <Button Content="Dock=Left"/> <Button Content="Dock=Left2"/> <Button Content="Right2" DockPanel.Dock="Right"/> <Button Content="Dock=Right" DockPanel.Dock="Right"/> <Button Content="LastChildFill=True"/>
Wrap Panel
این پنل بسیار شبیه StackPanel هست ولی مثل آن اشیاء را در یک سطر یا ستون ادامه نمیدهد؛ بلکه با رسیدن به انتهای پنجره، سطر یا ستون جدیدی را آغاز میکند. در stack panel با پایان پنجره، ادامه اشیا آن قابل مشاهده نبود ولی در این شیء با اتمام و رسیدن به لبهی پنجره، اشیاء در سر جدید (افقی) یا ستون جدید (عمودی) نمایش داده میشوند. این پنلها میتوانند در ساخت تبها و نوار ابزار استفاده شوند.
Canvas Panel
پایهایترین layout موجود در WPF است. موقعیت قرارگیری المانهای فرزندش بر اساس نقاط تعیین شده است.این پنل بیشتر برای رسم اشکال و گرافیک دو بعدی مناسب است و اصلا برای قرارگیری کنترلهای WPF روی آن توصیه نمیشود و مشکل winformها در آن رخ خواهد داد.
شروع ترسیم یک شکل دو بعدی روی آن بر اساس دوتا از چهار "خاصیتهای وابستگی متصل" صورت میگیرد که به شرح زیر هستند:
- Canvas.LEFT
- Canvas.RIGHT
- Canvas.TOP
- Canvas.BOTTOM
نمونه از کد نوشته شده آن به صورت زیر است:
<Canvas> <Rectangle Canvas.Left="40" Canvas.Top="31" Width="63" Height="41" Fill="Blue" /> <Ellipse Canvas.Left="130" Canvas.Top="79" Width="58" Height="58" Fill="Blue" /> <Path Canvas.Left="61" Canvas.Top="28" Width="133" Height="98" Fill="Blue" Stretch="Fill" Data="M61,125 L193,28"/> </Canvas>
ترتیب قرارگیری اشکال روی هم در canvas به ترتیبی انجام میگیرد که در XAML نوشته اید ولی میتوان با استفاده از خاصیت Canvas.ZIndex این ترتیب را تغییر داد.
<Canvas> <Ellipse Fill="Green" Width="60" Height="60" Canvas.Left="30" Canvas.Top="20" Canvas.ZIndex="1"/> <Ellipse Fill="Blue" Width="60" Height="60" Canvas.Left="60" Canvas.Top="40"/> </Canvas>
ViewBox
نمونهی کد زیر را تست کنید تا تفاوت بین دو Button را ببینید:
<StackPanel Orientation="Vertical"> <Button Content="Test" /> <Viewbox Stretch="Uniform"> <Button Content="Test" /> </Viewbox> </StackPanel>
در بخش دوم Layoutها مبحث گرید و ساخت Layout اختصاصی و تعدادی از خاصیتها را بررسی خواهیم کرد.
اگر پس از مهاجرت به VS 2017، خطای ذیل را در حین اجرای مهاجرتها مشاهده کردید:
error MSB4006: There is a circular dependency in the target dependency graph involving target "GetEFProjectMetadata"
ب) اگر در دستورات شما «configuration Release--» وجود دارد، آنرا حذف کنید و نیازی به آن نیست؛ چون به صورت خودکار توسط MSBuild مدیریت میشود.
نمونهای از تغییرات مورد نیاز جهت رفع این مشکل
در این نوشتار که به صورت آموزش تصویری ارائه میشود؛ یک سرویس WCF در Visual Studio 2013 ایجاد میکنم، سپس روش استفاده از آنرا در یک برنامه ویندوزی آموزش خواهم داد. در اینجا در نظرگرفته شده است که شما افزونهی Resharper را روی ویژوال استودیوی خود نصب دارید. پس در صورتیکه هنوز به سراغ آن نرفته اید درنگ نکنید و واپسین نگارش آن را دانلود کنید.
در این پروژهی ساده در نظر میگیریم که دو جدول یکی برای اخبار، شامل عنوان، متن خبر و تاریخ ثبت و دسته بندی و دیگری برای نگهداری دستهها در پایگاه داده داریم و میخواهیم سرویسهای مناسب با این دو جدول را بسازیم. با کد زیر، پایگاه دادهی dbTest و جدولهای tblNews و tblCategory در SQL Server 2012 ساخته میشود:
USE [master] GO /****** Object: Database [dbMyNews] Script Date: 2014/01/14 09:46:04 ب.ظ ******/ CREATE DATABASE [dbMyNews] CONTAINMENT = NONE ON PRIMARY ( NAME = N'dbMyNews', FILENAME = N'D:\dbMyNews.mdf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG ON ( NAME = N'dbMyNews_log', FILENAME = N'D:\dbMyNews_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) GO USE [dbMyNews] GO /****** Object: Table [dbo].[tblCategory] Script Date: 2014/01/14 09:46:04 ب.ظ ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[tblCategory]( [tblCategoryId] [int] IDENTITY(1,1) NOT NULL, [CatName] [nvarchar](50) NOT NULL, [IsDeleted] [bit] NOT NULL, CONSTRAINT [PK_tblCategory] PRIMARY KEY CLUSTERED ( [tblCategoryId] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: Table [dbo].[tblNews] Script Date: 2014/01/14 09:46:04 ب.ظ ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[tblNews]( [tblNewsId] [int] IDENTITY(1,1) NOT NULL, [tblCategoryId] [int] NOT NULL, [Title] [nvarchar](50) NOT NULL, [Description] [nvarchar](max) NOT NULL, [RegDate] [datetime] NOT NULL, [IsDeleted] [bit] NULL, CONSTRAINT [PK_tblNews] PRIMARY KEY CLUSTERED ( [tblNewsId] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [dbo].[tblNews] WITH CHECK ADD CONSTRAINT [FK_tblNews_tblCategory] FOREIGN KEY([tblCategoryId]) REFERENCES [dbo].[tblCategory] ([tblCategoryId]) GO ALTER TABLE [dbo].[tblNews] CHECK CONSTRAINT [FK_tblNews_tblCategory] GO USE [master] GO ALTER DATABASE [dbMyNews] SET READ_WRITE GO
اکنون Visual Studio 2013 را بازکنید سپس روی گزینه New Project کلیک کنید و برابر با نگارهی زیر عمل کنید:
پروژه MyNewsWCFLibrary در راه حل MyNews ساخته میشود. این پروژه به صورت پیشگزیده دارای یک کلاس به نام Service و یک interface به نام IService است. هر دو را حذف کنید و سپس روی نام پروژه راستکلیک کرده، از منوی بازشده گزینهی Add -> New Item را انتخاب کنید. سپس برابر با نگارهی زیر عمل کنید:
در لایهی Service Interface کلیهی روالهای مورد نیاز برای ارتباط با پایگاه داده را میسازیم. پیش از آن باید یک Model برای ارتباط با پایگاه داده ساخته باشیم. برای این کار از پنجره Add New Item و از زیرمجموعه Data، گزینه ADO.NET Entity Data Model را انتخاب کنید و بهسان زیر پیش روید:
در گام پسین روی دکمه New Connection کلیک کنید و رشتهی اتصال به پایگاه دادهی dbMyNews را بسازید. سپس همانند تنظیمات نگارهی زیر ادامه دهید:
در گام پسین گزینهی Entity Framework 6.0 را برگزینید و روی دکمهی Next کلیک کنید.
در پنجره نشان داده شده، جدولهای مورد نیاز را همانند نگارهی زیر انتخاب کرده و روی دکمه Finish کلیک کنید:
در پایان مدل ما همانند نگارهی زیر خواهد بود.
در بخش پسین دربارهی شیوهی دستکاری کلاسهای Entity خواهم نوشت.
cloc-x.x.exe hello.c
1 text file. 1 unique file. 0 files ignored. https://github.com/AlDanial/cloc v 1.65 T=0.04 s (28.3 files/s, 340.0 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C 1 0 7 5 -------------------------------------------------------------------------------
cloc-x.x.exe projectDirectoryName
16 text files. 15 unique files. 3 files ignored. https://github.com/AlDanial/cloc v 1.65 T=0.23 s (57.1 files/s, 188914.0 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C 10 4680 6621 30812 C/C++ Header 3 99 286 496 ------------------------------------------------------------------------------- SUM: 13 4779 6907 31308 -------------------------------------------------------------------------------
مقدمه
در اکثر موارد در یک Landscape عملیاتی، چنانچه به تجمیع و انتقال دادهها از بانکهای اطلاعاتی مختلف نیاز باشد، از SSIS Package اختصار (SQL Server Integration Service) استفاده میشود و معمولاً با تعریف یک Job در سطح SQL Server به اجرای Package در زمانهای مشخص میپردازند. چنانچه در موقعیتی لازم باشد که از طریق برنامه کاربردی توسعه یافته، به اجرای Package مبادرت ورزیده شود و البته نخواهیم Job تعریف شده را از طریق کد برنامه، اجرا کنیم و در واقع این امکان را داشته باشیم که همانند یک رویه ذخیره شده تعریف شده در سطح بانک اطلاعاتی به اجرای عمل فوق بپردازیم، یک راه حل میتواند تعریف یک CLR Stored Procedures باشد. در این مقاله به بررسی این موضوع پرداخته میشود، در ابتدا لازم است به بیان تئوری موضوع پرداخته شود (قسمتهای 1 الی 5) در ادامه به ذکر پیاده سازی روش پیشنهادی پرداخته میشود.
1- اجرای Integration Service Package
جهت اجرای یک Package از ابزارهای زیر میتوان استفاده کرد:• command-line ابزار خط فرمان dtexec.exeتوجه: همچنین یک Package را در زمان طراحی در Business Intelligence Development Studio) BIDS) میتوان اجرا نمود.
• ابزار اجرائی پکیج dtexecui.exe
• استفاده از SQL Server Agent job
2- استفاده از dtexec جهت اجرای Package
با استفاده از ابزار dtexec میتوان Packageهای ذخیره شده در فایل سیستم، یک SQL Instance و یا Packageهای ذخیره شده در Integration Service را اجرا نمود.توجه: در سیستم عاملهای 64 بیتی، ابزار dtexec موجود در Integration Service با نسخه 64 بیتی نصب میشود. چنانچه بایست Packageهای معینی را در حالت 32 بیتی اجرا کنید، لازم است ابزار dtexec نسخه 32 بیتی نصب شود. ابزار dtexec دستیابی به تمامی ویژگیهای پیکربندی و اجرای Package از قبیل اتصالات، مشخصات(Properties)، متغیرها، logging و شاخصهای پردازشی را فراهم میکند.
توجه: زمانی که از نسخهی ابزار dtexec که با SQL Server 2008 ارائه شده استفاده میکنید برای اجرای یک SSIS Package نسخه 2005، Integration Service به صورت موقت Package را به نسخه 2008 ارتقا میدهد، اما نمیتوان از ابزار dtexec برای ذخیره این تغییرات استفاده کرد.
2-1- ملاحظات نصب dtexec روی سیستمهای 64 بیتی
به صورت پیش فرض، یک سیستم عامل 64 بیتی که هر دو نسخه 64 بیتی و 32 بیتی ابزار خط فرمان Integration Service را دارد، نسخه 32 بیتی نصب شده را در خط فرمان اجرا خواهد کرد. نسخه 32 بیتی بدین دلیل اجرا میشود که در متغیر محیطی (Path (Path environment variable مسیر directory نسخه 32 بیتی قرار گرفته است.به طور معمول:2-2- تفسیر کدهای خروجی
هنگامی که یک Package اجرا میشود، dtexec یک کد خروجی (Return Code) بر میگرداند:مقدار | توصیف |
0 | Package با موفقیت اجرا شده است. |
1 | Package با خطا مواجه شده است. |
3 | Package در حال اجرا توسط کاربر لغو شده است. |
4 | Package پیدا نشده است. |
5 | Package بارگذاری نشده است. |
6 | ابزار با یک خطای نحوی یا خطای معنایی در خط فرمان برخورد کرده است. |
2-3- قوانین نحوی dtexec
تمامی گزینهها (Options) باید با یک علامت Slash (/) و یا Minus (-) شروع شوند.یک آرگومان باید در یک quotation mark محصور شود چنانچه شامل یک فاصله خالی باشد.
گزینهها و آرگومانها بجز رمزعبور حساس به حروف کوچک و بزرگ نیستند.
2-3-1- Syntax
dtexec /option [value] [/option [value]]…
2-3-2- Parameters
نکته: در Integration Service، ابزار خط فرمان dtsrun که برایData Transformation Service) DTS)های نسخه SQL Server 2000 استفاده میشد، با ابزار خط فرمان dtexec جایگزین شده است.• تعدادی از گزینههای خط فرمان dtsrun به طور مستقیم در dtexec معادل دارند برای مثال نام Server و نام Package.
• تعدادی از گزینههای dtsrun به طور مستقیم در dtexec معادل ندارند.
• تعدادی گزینههای خط فرمان جدید dtsexec وجود دارد که در ویژگیهای جدید Integration Service پشتیبانی میشود.
2-3-3- مثال
1) به منظور اجرای یک SSIS Package که در SQL Server ذخیره شده است، با استفاده از Windows Authentication :dtexec /sq <Package Name> /ser <Server Name>
2) به منظور اجرای یک SSIS Package که در پوشه File System در SSIS Package Store ذخیره شده است :
dtexec /dts “\File System\<Package File Name>”
3) به منظور اجرای یک SSIS Package که در سیستم فایل ذخیره شده است و مشخص کردن گزینه logging:
dtexec /f “c:\<Package File Name>” /l “DTS.LogProviderTextFile; <Log File Name>”
4) به منظور اجرای یک SSIS Package که در SQL Server ذخیره شده با استفاده از SQL Server Authentication برای نمونه(user:ssis;pwd:ssis@ssis)و رمز (Package(123:
dtexec /server “<Server Name>” /sql “<Package Name>” / user “ssis” /Password “ssis@ssis” /De “123”
3- تنظیمات سطح حفاظتی یک Package
به منظور حفاظت از دادهها در Packageهای Integration Service میتوانید یک سطح حفاظتی (protection level) را تنظیم کنید که به حفاظت از دادههای صرفاً حساس یا تمامی دادههای یک Package کمک نماید. به علاوه میتوانید این دادهها را با یک Password یا یک User Key رمزگذاری نمائید یا به رمزگذاری دادهها در بانک اطلاعاتی اعتماد کنید. همچنین سطح حفاظتی که برای یک Package استفاده میکنید، الزاماً ایستا (static) نیست و در طول چرخه حیات یک Package میتواند تغییر کند. اغلب سطح حفاظتی در طول توسعه یا به محض (deploy) استقرار Package تنظیم میشود.توجه: علاوه بر سطوح حفاظتی که توصیف شد، Packageها در بانک اطلاعاتی msdb ذخیره میشوند که همچنین میتوانند توسط نقشهای ثابت در سطح بانک اطلاعاتی (fixed database-level roles) حفاظت شوند. Integration Service شامل 3 نقش ثابت بانک اطلاعاتی برای نسبت دادن مجوزها به Package است که عبارتند از db_ssisadmin ،db_ssisltduser و db_ssisoperator
3-1- درک سطوح حفاظتی
در یک Package اطلاعات زیر به عنوان حساس تعریف میشوند:• بخش password در یک connection string. گرچه، اگر گزینه ای را که همه چیز را رمزگذاری کند، انتخاب کنید تمامی connection string حساس در نظر گرفته میشود.
• گرههای task-generated XML که برچسب (tagged) هایی حساس هستند.
• هر متغییری که به عنوان حساس نشان گذاری شود.
3-1-1- Do not save sensitive
هنگامی که Package ذخیره میشود از ذخیره مقادیر ویژگیهای حساس در Package جلوگیری میکند. این سطح حفاظتی رمزگذاری نمیکند اما در عوض از ذخیره شدن ویژگی هایی که حساس نشان گذاری شده اند به همراه Package جلوگیری میکند.3-1-2- Encrypt all with password
به منظور رمزگذاری تمامی Package از یک Password استفاده میشود. Package توسط Password ای رمزگذاری میشود که کاربر هنگامی که Package را ایجاد یا Export میکند، ارائه میدهد. به منظور باز کردن Package در SSIS Designer یا اجرای Package توسط ابزار خط فرمان dtexec کاربر بایست رمز Package را ارائه نماید. بدون رمز کاربر قادر به دستیابی و اجرای Package نیست.3-1-3- Encrypt all with user key
به منظور رمزگذاری تمامی Package از یک کلید که مبتنی بر Profile کاربر جاری میباشد، استفاده میشود. تنها کاربری که Package را ایجاد یا Export میکند، میتواند Package را در SSIS Designer باز کند و یا Package را توسط ابزار خط فرمان dtexec اجرا کند.3-1-4- Encrypt sensitive with password
به منظور رمزگذاری تنها مقادیر ویژگیهای حساس در Package از یک Password استفاده میشود. برای رمزگذاری از DPAPI استفاده میشود. دادههای حساس به عنوان بخشی از Package ذخیره میشوند اما آن دادهها با استفاده از Password رمزگذاری میشوند. به منظور باز نمودن Package در SSIS Designer کاربر باید رمز Package را ارائه دهد. اگر رمز ارائه نشود، Package بدون دادههای حساس باز میشود و کاربر باید مقادیر جدیدی برای دادههای حساس فراهم کند. اگر کاربر سعی نماید Package را بدون ارائه رمز اجرا کند، اجرای Package با خطا مواجه میشود.3-1-5- Encrypt sensitive with user key
به منظور رمزگذاری تنها مقادیر ویژگیهای حساس در Package از یک کلید که مبتنی بر Profile کاربر جاری میباشد، استفاده میشود. تنها کاربری که از همان Profile استفاده میکند، Package را میتواند بارگذاری (load) کند. اگر کاربر متفاوتی Package را باز نماید، اطلاعات حساس با مقادیر پوچی جایگزین میشود و کاربر باید مقادیر جدیدی برای دادههای حساس فراهم کند. اگر کاربر سعی نماید Package را بدون ارائه رمز اجرا کند، اجرای Package با خطا مواجه میشود. برای رمزگذاری از DPAPI استفاده میشود.3-1-6- (Rely on server storage for encryption (ServerStorage
با استفاده از نقشهای بانک اطلاعاتی، SQL Server تمامی Package را حفاظت میکند. این گزینه تنها زمانی پشتیبانی میشود که Package در بانک اطلاعاتی msdb ذخیره شده است.4- استفاده از نقشهای Integration Service
برای کنترل کردن دستیابی به Package، SSIS شامل 3 نقش ثابت در سطح بانک اطلاعاتی است. نقشها میتوانند تنها روی Package هایی که در بانک اطلاعاتی msdb ذخیره شده اند، بکار روند. با استفاده از SSMS میتوانید نقشها را به Packageها نسبت دهید، این انتساب نقشها در بانک اطلاعاتی msdb ذخیره میشود.Write action | Read action | Role |
Import packages Delete own packages Delete all packages Change own package roles Change all package roles * به نکته رجوع شود | Enumerate own packages Enumerate all packages View own packages View all packages Execute own packages Execute all packages Export own packages Export all packages Execute all packages in SQL Server Agent | db_ssisadmin or sysadmin |
Import packages Delete own packages Change own package roles | Enumerate own packages Enumerate all packages View own packages Execute own packages Export own packages | db_ssisltduser |
None | Enumerate all packages View all packages Execute all packages Export all packages Execute all packages in SQL Server Agent | db_ssisoperator |
Stop all currently running packages | View execution details of all running packages | Windows administrators |
همچنین جدول sysssispackages در بانک اطلاعاتی msdb شامل Package هایی است که در SQL Server ذخیره میشوند. این جدول شامل ستون هایی که اطلاعاتی درباره نقش هایی که به Packageها نسبت داده شده است، میباشد.
به صورت پیش فرض، مجوزهای نقشهای ثابت بانک اطلاعاتی db_ssisadmin و db_ssisoperator و شناسه منحصر به فرد کاربری (unique security identifier) که Package را ایجاد کرده برای خواندن Package بکار میرود، و مجوزهای نقش db_ssisadmin و شناسه منحصر به فرد کاربری که Package را ایجاد کرده برای نوشتن Package به کار میرود. یک User باید عضو نقش db_ssisadmin و db_ssisltduser یا db_ssisoperator برای داشتن دسترسی خواندن Package باشد. یک User باید عضو نقش db_ssisadmin برای داشتن دسترسی نوشتن Package باشد.
5- اتصال به صورت Remote به Integration Service
زمانی که یک کاربر بدون داشتن دسترسی کافی تلاش کند به یک Integration Service به صورت Remote متصل شود، با پیغام خطای "Access is denied" مواجه میشود. برای اجتناب از این پیغام خطا میتوان تضمین کرد که کاربر مجوز مورد نیاز DCOM را دارد.به منظور پیکربندی کردن دسترسی کاربر به صورت Remote به سرویس Integration مراحل زیر را دنبال کنید:
- Component Service را باز نمایید ( در Run عبارت dcomcnfg را تایپ کنید).مجوز دسترسی Lunch به منظور شروع و خاتمه سرویس، اعطا یا رد میشود و مجوز دسترسیActivation به منظور متصل شدن به سرویس، اعطا (grant) یا رد (deny) میشود.
- گره Component Service را باز کنید، گره Computer و سپس My Computer را باز نمایید و روی DCOM Config کلیک نمایید.
- گره DCOM Config را باز کنید و از لیست برنامه هایی که میتوانند پیکربندی شوند MsDtsServer را انتخاب کنید.
- روی Properties برنامه MsDtsServer رفته و قسمت Security را انتخاب کنید.
- در قسمت Lunch and Activation Permissions، مورد Customize را انتخاب و سپس روی Edit کلیک نمایید تا پنجره Lunch Permission باز شود.
- در پنجره Lunch Permission، کاربران را اضافه و یا حذف کنید و مجوزهای مناسب را به کاربران یا گروههای مناسب نسبت دهید. مجوزهای موجود عبارتند از Local Lunch، Remote Lunch، Local Activation و Remote Activation .
- در قسمت Access Permission مراحل فوق را به منظور نسبت دادن مجوزهای مناسب به کاربران یا گروههای مناسب انجام دهید.
- سرویس Integration را Restart کنید.
6- پیاده سازی
در ابتدا به ایجاد یک CLR Stored Procedures پرداخته میشود نام اسمبلی ساخته شده به این نام RunningPackage.dll میباشد و حاوی کد زیر است:Partial Public Class StoredProcedures '------------------------------------------------ 'exec dbo.Spc_NtDtexec 'Package','ssis','ssis@ssis','1234512345' '------------------------------------------------ <Microsoft.SqlServer.Server.SqlProcedure()> _ Public Shared Sub Spc_NtDtexec(ByVal PackageName As String, _ ByVal UserName As String, _ ByVal Password As String, _ ByVal Decrypt As String) Dim p As New System.Diagnostics.Process() p.StartInfo.FileName = "C:\Program Files\Microsoft SQL Server\100\DTS\Binn\DTExec.exe" p.StartInfo.RedirectStandardOutput = True p.StartInfo.Arguments = "/sql " & PackageName & " /User " & UserName & " /Password " & Password & " /De " & Decrypt p.StartInfo.UseShellExecute = False p.Start() p.WaitForExit() Dim output As String output = p.StandardOutput.ReadToEnd() Microsoft.SqlServer.Server.SqlContext.Pipe.Send(output) End Sub End Class
در قدم بعدی نیاز به Register کردن dll ساخته شده در سطح بانک اطلاعاتی SQL Server است، این گامها پس از اتصال به SQL Server Management Studio به شرح زیر است:
1- فعال کردن CLR در سرویس SQL Server
SP_CONFIGURE 'clr enabled',1 GO RECONFIGURE
2- فعال کردن ویژگی TRUSTWORTHY در بانک اطلاعاتی مورد نظر
ALTER DATABASE <Database Name> SET TRUSTWORTHY ON GO RECONFIGURE
3- ایجاد Assembly و Stored Procedure در بانک اطلاعاتی مورد نظر
Assembly ساخته شده با نام RunningPacakge.dll در ریشه :C کپی شود. بعد از ثبت نمودن این Assembly لزومی به وجود آن نمیباشد.
USE <Database Name> GO CREATE ASSEMBLY [RunningPackage] AUTHORIZATION [dbo] FROM 'C:\RunningPackage.dll' WITH PERMISSION_SET = UNSAFE Go CREATE PROCEDURE [dbo].[Spc_NtDtexec] @PackageName [nvarchar](50), @UserName [nvarchar](50), @Password [nvarchar](50), @Decrypt [nvarchar](50) WITH EXECUTE AS CALLER AS EXTERNAL NAME [RunningPackage].[RunningPackage.StoredProcedures].[Spc_NtDtexec] GO
در برنامه کاربردی تان کافی است متدی به شکل زیر ایجاد و با توجه به نیازتان در برنامه به فراخوانی آن و اجرای Package بپردازید.
Private Sub ExecutePackage() Dim oSqlConnection As SqlClient.SqlConnection Dim oSqlCommand As SqlClient.SqlCommand Dim strCnt As String = String.Empty strCnt = "Data Source=" & txtServer.Text & ";User ID=" & txtUsername.Text & ";Password=" & txtPassword.Text & ";Initial Catalog=" & cmbDatabaseName.SelectedValue.ToString() & ";" Try oSqlConnection = New SqlClient.SqlConnection(strCnt) oSqlCommand = New SqlClient.SqlCommand With oSqlCommand .Connection = oSqlConnection .CommandType = System.Data.CommandType.StoredProcedure .CommandText = "dbo.Spc_NtDtexec" .Parameters.Clear() .Parameters.Add("@PackageName", System.Data.SqlDbType.VarChar, 50) .Parameters.Add("@UserName", System.Data.SqlDbType.VarChar, 50) .Parameters.Add("@Password", System.Data.SqlDbType.VarChar, 50) .Parameters.Add("@Decrypt", System.Data.SqlDbType.VarChar, 50) .Parameters("@PackageName").Value = txtPackageName.Text.Trim() .Parameters("@UserName").Value = txtUsername.Text.Trim() .Parameters("@Password").Value = txtPassword.Text.Trim() .Parameters("@Decrypt").Value = txtDecrypt.Text.Trim() End With If (oSqlCommand.Connection.State <> System.Data.ConnectionState.Open) Then oSqlCommand.Connection.Open() oSqlCommand.ExecuteNonQuery() System.Windows.Forms.MessageBox.Show("Success") End If If (oSqlCommand.Connection.State = System.Data.ConnectionState.Open) Then oSqlCommand.Connection.Close() End If Catch ex As Exception MessageBox.Show(ex.Message, "Error") End Try End Sub 'ExecutePackage
git log --oneline
Install-Module -Name Microsoft.PowerShell.Crescendo
$Configuration = @{ '$schema' = "https://aka.ms/PowerShell/Crescendo/Schemas/2021-11" Commands = @() } $parameters = @{ Verb = "Get" Noun = "GitLog" OriginalName = "git" } $Configuration.Commands += New-CrescendoCommand @parameters $Configuration | ConvertTo-Json -Depth 3 | Out-File ./git-ps.json
{ "Commands": [ { "Verb": "Get", "Noun": "GitLog", "OriginalName": "git", "OriginalCommandElements": null, "Platform": [ "Windows", "Linux", "MacOS" ], "Elevation": null, "Aliases": null, "DefaultParameterSetName": null, "SupportsShouldProcess": false, "ConfirmImpact": null, "SupportsTransactions": false, "NoInvocation": false, "Description": null, "Usage": null, "Parameters": [], "Examples": [], "OriginalText": null, "HelpLinks": null, "OutputHandlers": null } ], "$schema": "https://aka.ms/PowerShell/Crescendo/Schemas/2021-11" }
"": "https://aka.ms/PowerShell/Crescendo/Schemas/2021-11",
اکنون باید این فایل Configuration را به Crescendo معرفی کنیم تا cmdlet را برایمان تولید کند. اینکار را توسط Export-CrescendoModule انجام خواهیم داد:
Export-CrescendoModule -Configuration ./git-ps.json -ModuleName ./git-ps.psm1
با اجرای دستور فوق، فایلهای git.psm1 و همچنین git.psd1 تولید خواهند شد. نیاز به بررسی فایلهای جنریت شده نیست؛ چون تنها جایی که با آن باید در ارتباط باشیم، همان فایل JSON ابتدای بحث است که در ادامه آن را بررسی خواهیم کرد. اما قبل از آن اجازه دهید ماژول تولید شده را Import کنیم و دستور Get-GitLog را وارد کنیم:
PP /> Import-Module ./git-ps.psd1 PS /> Get-GitLog usage: git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] [--super-prefix=<path>] [--config-env=<name>=<envvar>] <command> [<args>] These are common Git commands used in various situations: start a working area (see also: git help tutorial) clone Clone a repository into a new directory init Create an empty Git repository or reinitialize an existing one work on the current change (see also: git help everyday) add Add file contents to the index mv Move or rename a file, a directory, or a symlink restore Restore working tree files rm Remove files from the working tree and from the index examine the history and state (see also: git help revisions) bisect Use binary search to find the commit that introduced a bug diff Show changes between commits, commit and working tree, etc grep Print lines matching a pattern log Show commit logs show Show various types of objects status Show the working tree status grow, mark and tweak your common history branch List, create, or delete branches commit Record changes to the repository merge Join two or more development histories together rebase Reapply commits on top of another base tip reset Reset current HEAD to the specified state switch Switch branches tag Create, list, delete or verify a tag object signed with GPG collaborate (see also: git help workflows) fetch Download objects and refs from another repository pull Fetch from and integrate with another repository or a local branch push Update remote refs along with associated objects 'git help -a' and 'git help -g' list available subcommands and some concept guides. See 'git help <command>' or 'git help <concept>' to read about a specific subcommand or concept. See 'git help git' for an overview of the system.
همانطور که مشاهده میکنید، خروجی دستور git، نمایش داده شدهاست. دلیل آن نیز این است که در فایل configuration، هیچ آرگومانی را به عنوان ورودی آن تعیین نکردهایم. برای اضافه کردن آرگومانهای موردنظر باید پراپرتی OrginalCommandElements را مقدار دهی کنیم:
"OriginalCommandElements": ["log", "--oneline"],
بنابراین با فراخوانی دستور Get-GitLog، در اصل دستور git log —oneline فراخوانی خواهد شد:
PS /> Get-GitLog e9590e8 init
اما تا اینجا نیز خروجی به صورت رشتهایی است. برای داشتن یک خروجی Object، باید پراپرتی OutputHandlers را از Configuration، تغییر دهیم:
"OutputHandlers": [ { "ParameterSetName": "Default", "Handler": "$args[0] | ForEach-Object { $hash, $message = $_.Split(' ', 2) ; [PSCustomObject]@{ Hash = $hash; Message = $message } }" } ]
در اینجا توسط args$ به خروجی کامند اصلی دسترسی خواهیم داشت. این خروجی را سپس با کمک ForEach-Object، به یک شیء با پراپرتیهای Hash و Message تبدیل کردهایم. در اینجا فقط میخواستم روال تهیه یک آبجکت را از کامندهایی که خروجی JSON ندارند، نشان دهم؛ اما خوشبختانه توسط پرچم pretty در git log، امکان تهیهی خروجی JSON را نیز داریم:
git log --pretty=format:'{"commit": "%h", "author": "%an", "date": "%ad", "message": "%s"}'
در نتیجه عملاً نیازی به split کردن نیست و بجای آن میتوانیم به صورت مستقیم، خروجی را توسط ConvertFrom-Json پارز کنیم:
"OutputHandlers": [ { "ParameterSetName": "Default", "Handler": "$args[0] | ConvertFrom-Json" } ]
همچنین درون فایل schema با کمک پراپرتی Parameters، امکان تعریف پارامتر را نیز برای کامند Get-GitLog خواهیم داشت. به عنوان مثال میتوانیم فلگ reverse را نیز به کامند اصلی از طریق PowerShell ارسال کنیم:
"Parameters": [ { "Name": "reverse", "OriginalName": "--reverse", "ParameterType": "switch", "Description": "Reverse the order of the commits in the output." } ],
دقت داشته باشیم که با هربار تغییر فایل schema باید توسط دستور Export-CrescendoModule ماژول موردنظر را تولید کنید:
Export-CrescendoModule -Configuration ./git-ps.json -ModuleName ./git-ps.psm1 Import-Module ./git-ps.psd1
در نهایت cmdletمان به این صورت قابل استفاده خواهد بود: