اشتراک‌ها
یادگیری SASS در 15 دقیقه

If you write copious amounts of CSS, a pre-processor can greatly decrease your stress levels and save you a lot of precious time. Using tools such as Sass, Less, Stylus or PostCSS makes large and complicated stylesheets clearer to understand and easier to maintain. Thanks to features like variables, functions and mixins the code becomes more organized, allowing developers to work quicker and make less mistakes. 

یادگیری SASS در 15 دقیقه
اشتراک‌ها
درباره ConnectJs
All the great stuff from last year. JavaScript. Web. CSS. HTML5. Mobile. With more of all that, and new tracks on PHP and Rails. Early Bird registration & CFP now open!
درباره ConnectJs
مطالب
پیاده سازی عملیات CRUD با استفاده از پروتکل OData
OData  یکی از بهترین روش‌های پیاده سازی RESTful Apis میباشد. Open Data Protocol یا به اصطلاح OData یک data access protocol برای وب میباشد که اجازه‌ی تغییر دادن و نوشتن کوئری درون CRUD مربوطه را میدهد (create - read - update - delete). Asp.Net WebApi از ورژن 3 و 4 این پروتکل بطور کامل پشتیبانی می‌نماید.
در این آموزش ما از WebApi 2.2 , OData V4, Ef 6 استفاده کرده‌ایم.
با استفاده از ویژوال استودیو یک پروژه‌ی Asp.Net را از نوع Empty به نام ProductService میسازیم.

هم چنین در قسمت Add folders and core references تیک گزینه‌ی Web Api را نیز فعال مینماییم.


حال احتیاج به نصب پکیج OData با استفاده از nuget package manager داریم. کافیست دستور زیر را در package manager console وارد نماییم.

Install-Package Microsoft.AspNet.Odata

این دستور آخرین ورژن Odata package را از nuget دانلود مینماید.

بعد از نصب شدن OData نیاز به اضافه کردن یک Model داریم. کلاسی را به نام Product در پوشه‌ی Models میسازیم.

کلاس Product.cs حاوی فیلد‌های زیر است.

namespace ProductService.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }
}

پراپرتی Id، کلید این entity است و کلاینت میتواند کوئری را بر روی entity، به وسیله‌ی key بزند. برای مثال برای گرفتن Product با Id برابر 2، باید این url را ارسال نمود "(2)Products/"

پرواضح است که Id در Database به عنوان Primary key در نظر گرفته شده است.

حال احتیاج به نصب Entity Framework داریم که با ارسال دستور زیر از طریق nuget نصب خواهد شد

Install-Package EntityFramework

بعد از نصب کردن ef نیاز به اضافه کردن connection string در web config داریم.

<connectionStrings>
    <add name="ProductsContext" connectionString="Data Source=.; 
        Initial Catalog=ProductsContext; Integrated Security=True;MultipleActiveResultSets=True;"
      providerName="System.Data.SqlClient" />
  </connectionStrings>

الان میتوانیم کلاس ProductsContext را درون پوشه‌ی Models ایجاد نماییم. محتویات آن را به صورت زیر وارد مینماییم

using System.Data.Entity;
namespace ProductService.Models
{
    public class ProductsContext : DbContext
    {
        public ProductsContext() 
                : base("name=ProductsContext")
        {
        }
        public DbSet<Product> Products { get; set; }
    }
}

درون Constructor کلاس ProductsContext، داریم name=ProductsContext که باید برابر name درون connection string باشد.

حال نیاز به کانفیگ OData داریم. درون پوشه‌ی App_Start و کلاس WebApiConfig.cs محتویات زیر را جایگزین متد register نمایید:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Product>("Products");
        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: null,
            model: builder.GetEdmModel());
    }
}

این کد دو فرآیند زیر را انجام میدهد

1) ساخت Entity Data Model (EDM)

2) اضافه کردن route

EDM یک مدل انتزاعی از data است. EDM برای تولید سند metadata استفاده میشود. کلاس ODataModelBuilder برای ساخت EDM با استفاده از default naming convention میباشد که باعث کاهش کد‌ها میشود. ضمنا کلاس MapODataServiceRoute برای ساخت OData v4 route میباشد. همانگونه که اطلاع دارید، تعریف route برای مدیریت کردن WebApi و چگونگی مسیریابی درخواست‌های http میباشد.

اگر application شما احتیاج به چند OData endpoint داشته باشد، میتوانید برای هر کدام route‌های جدا و همچنین نام یکتایی را برای routeName و routePrefix آن در نظر بگیرید.


اضافه کردن OData Controller

یک Controller، کلاسی برای مدیریت کردن درخواست‌های http میباشد. شما باید Controllerهای مجزایی را برای هر entity set در OData service خود بسازید. در این مقاله Controller مربوط به موجودیت Product را میسازیم.

در Solution Explorer با کلیک راست بر روی پوشه‌ی Controller، کلاسی به نام ProducsController را میسازیم. دقت کنید نام آن حتما باید به Controller ختم شود.

در OData V3 میتوانیم Controller را با استفاده از Scaffolding بسازیم؛ ولی در V4 این ویژگی وجود ندارد!

محتویات زیر را در این کنترلر اضافه مینماییم:

using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
    public class ProductsController : ODataController
    {
        ProductsContext db = new ProductsContext();
        private bool ProductExists(int key)
        {
            return db.Products.Any(p => p.Id == key);
        } 
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

این مرحله‌ی ابتدایی از پیاده سازی کنترلر میباشد و در قسمت بعد به پیاده سازی CRUD مربوط به آن میپردازیم.


Querying The Entity Set

این 2 متد را به کنترلر خود اضافه مینماییم

[EnableQuery]
public IQueryable<Product> Get()
{
    return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
    IQueryable<Product> result = db.Products.Where(p => p.Id == key);
    return SingleResult.Create(result);
}

ویژگی EnableQuery به معنای امکان Query زدن از سمت کلاینت به آن میباشد. FromODataUri نیز برای امکان پاس دادن پارامتر از طریق Uri است.

متد Get بدون پارامتر، قادر به برگرداندن تمامی Product‌ها میباشد و متد Get با پارامتر، قادر به برگرداندن آن Product خاص با استفاده از unique Id است.

در صورت داشتن EnableQuery با استفاده از Query Option هایی مثل filter$ و sort$ و غیره از سمت کلاینت قادر به تغییر دادن کوئری‌های خود هستیم.


Adding and Entity to Entity Set

برای اجازه دادن به کلاینت، جهت اضافه کردن یک Product به دیتابیس، متد Post زیر را اضافه مینماییم

public async Task<IHttpActionResult> Post(Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Created(product);
}


Updation an Entity

OData از دو روش متفاوت برای Update کردن یک موجودیت استفاده مینماید.

1) Patch : امکان partial update برای موجودیت مربوطه را فراهم میسازد.

2) Put : موجودیت جدید را به صورت کامل جایگزین مینماید.

مشکل روش Put این است که کلاینت مجبور به ارسال تمامی فیلد‌های مربوطه میباشد. حتی آن هایی که اساسا تغییری نکرده‌اند. بنابراین روش Patch ترجیح داده میشود.

در هر صورت ما به پیاده سازی هر دو روش می‌پردازیم:

public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var entity = await db.Products.FindAsync(key);
    if (entity == null)
    {
        return NotFound();
    }
    product.Patch(entity);
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ProductExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return Updated(entity);
}
public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    if (key != update.Id)
    {
        return BadRequest();
    }
    db.Entry(update).State = EntityState.Modified;
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ProductExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return Updated(update);
}

در قسمت Patch کنترلر از <Delta<T استفاده میکند که typeی است برای track کردن تغییرات در مدل مربوطه.


Deleting an Entity

برای حذف هر موجودیت نیز کافیست متد زیر را به کنترلر خود اضافه نمایید:

public async Task<IHttpActionResult> Delete([FromODataUri] int key)
{
    var product = await db.Products.FindAsync(key);
    if (product == null)
    {
        return NotFound();
    }
    db.Products.Remove(product);
    await db.SaveChangesAsync();
    return StatusCode(HttpStatusCode.NoContent);
}

من چند رکورد تستی را به صورت زیر وارد کرده‌ام:

حال پروژه‌ی خود را run نموده و آدرس زیر را وارد نمایید:

http://localhost:YourPort/Products

پاسخ، مجموعه‌ای از entity‌های زیر خواهد بود:

{
  "@odata.context":"http://localhost:4516/$metadata#Products","value":[
    {
      "Id":1,"Name":"Ali","Price":2.00,"Category":"aaa"
    },{
      "Id":2,"Name":"Reza","Price":1.00,"Category":"bbb"
    },{
      "Id":3,"Name":"Ahmad","Price":0.00,"Category":"ccc"
    }
  ]
}

شما میتوانید از هر کدام از فیلتر‌های زیر برای کوئری زدن از کلاینت به سمت سرور استفاده نمایید. بطور مثال هر کدام از اینها پاسخ متفاوت و مربوط به خود را برگشت میدهد:

/Products(2)

Productی با آی دی 2 را بر میگرداند.

/Products?$filter=Id gt 1

محصولی را با آی دی بزرگتر از 1، بر میگرداند.

Products?$select=Name

روی محصولات select زده و فقط فیلد Name آن‌ها را بر میگرداند.

Products?$select=Name,Price

آرایه‌ای از objectهایی با پراپرتی Name و Price را بر میگرداند.

/Products?$top=3

فقط 3 رکورد اول را بر میگرداند.


همانطور که ملاحظه میفرمایید، استفاده از OData باعث کمتر شدن کد‌های سمت سرور و همچنین امکان کوئری زدن از سمت کلاینت به سمت سرور را مهیا می‌کند.

بعد از خواندن این مقاله ممکن است به این مساله فکر کنید که این کار باعث کاهش امنیت میشود. باید عرض کنم که امکانات زیادی برای محدود کردن کوئری‌ها، فراهم شده است و هیچ نگرانی از این بابت وجود ندارد. بطور مثال میتوانید تعیین کنید که از entity مربوطه فقط حداکثر 3 پراپرتی قابلیت کوئری زدن را دارند؛ یا اینکه حداکثر در هر کوئری، 10 رکورد قابلیت پاسخ دادن خواهد داشت.

پس بدین صورت میباشد که شما حداکثر امکانات ممکن را به سمت کلاینت میدهید و اختیار بدان واگذار شده که آیا از این امکانات حداکثری، استفاده نماید یا خیر.

امکانات این پروتکل منحصر به فرد است و در مقاله‌های بعدی به جزئیات بیشتر و دقیق‌تری خواهیم پرداخت.

مطالب
آشنایی با قابلیت FileStream اس کیوال سرور 2008 - قسمت دوم

در این قسمت نحوه‌ی فعال سازی قابلیت FileStream را بررسی خواهیم کرد و در قسمت بعدی نحوه‌ی دسترسی به آن‌را از طریق برنامه نویسی مرور می‌نمائیم.

فعال سازی قابلیت FileStream
همانند اکثر قابلیت‌های اس کیوال سرور، فعال سازی FileStream نیز حداقل به دو صورت استفاده از GUI و قابلیت‌های management studio میسر است و یا استفاده از دستورات T-SQL (و البته کتابخانه‌ی SMO یا همان محصور کننده‌ی توانایی‌های management studio نیز قابل استفاده است).

روش اول) استفاده از management studio
قابلیت FileStream به صورت پیش فرض غیرفعال است. برای فعال سازی آن به مسیر زیر مراجعه نمائید:

Start > All Programs > Microsoft SqlServer 2008 > Configuration Tools > SQL Server Configuration Manager

سپس در قسمت SQL Server services ، وهله مربوط به SQL Server را یافته، کلیک راست و به برگه خواص آن مراجعه کرده (شکل زیر) و قابلیت FileStream را فعال کنید:



گزینه‌های مختلف آن به شرح زیر هستند:
• Enable FileStream for transact-sql access : امکان استفاده از دستورات T-SQL را جهت دسترسی به فایل‌ها فعال می‌سازد (یا برعکس)
• Enable FileStream for File I/O streaming access : امکان دسترسی به فایل‌ها با استفاده از Win32 streaming access
• All remote clients to have streaming access to file stream data : اجازه‌ی دسترسی به کلاینت‌های راه دور جهت استفاده از قابلیت FileStream

مرحله بعد، فعال سازی سطح دسترسی به سرور است. به management studio مراجعه نمائید. سپس بر روی وهله سرور مورد نظر کلیک راست نموده و به خواص آن مراجعه کنید (شکل زیر). سپس در قسمت advanced سطح دسترسی را بر روی Full قرار دهید.



پس از این تنظیم به شما پیغام داده خواهد شد که باید دیتابیس سرور را یکبار راه اندازی مجدد نمائید تا تنظیمات مورد نظر، اعمال شوند.

در ادامه باید دیتابیسی را که نیاز است نوع داده FileStream را بپذیرد، تنظیم نمود.
بر روی دیتابیس مورد نظر کلیک راست کرده و در برگه خواص آن به گزینه‌ی Filegroups مراجعه کنید. سپس در اینجا یک گروه جدید را اضافه کرده ، نامی دلخواه را وارد نموده و سپس تیک مربوط به default بودن آن‌را نیز قرار دهید (شکل زیر):



سپس در همین برگه‌ی خواص دیتابیس که باز است، به گزینه‌ی Files مراجعه کنید. در اینجا سه کار را باید انجام دهید. ابتدا بر روی دکمه Add کلیک کرده و در قسمت logical name ردیف اضافه شده، نامی دلخواه را وارد کنید. سپس file type آن را بر روی FileStream قرار دهید. در ادامه به قسمت path در همین ردیف مراجعه نموده و مسیر ذخیره سازی را مشخص کنید. در پایان بر روی دکمه‌ی OK کلیک نمائید تا کار تنظیم دیتابیس به پایان رسد (شکل زیر):



روش دوم) استفاده از دستورات T-SQL
منهای قسمت تنظیمات SQL Server Configuration Manager که باید از طریق روش عنوان شده صورت گیرد، سایر موارد فوق را با استفاده از دستورات T-SQL نیز می‌توان انجام داد:

الف) تنظیم سطح دسترسی بر روی سرور

EXEC sp_configure filestream_access_level, 2 -- 0 : Disable , 1 : Transact Sql Access , 2 : Win IO Access
GO
RECONFIGURE
GO
ب) تنظیمات دیتابیس

اگر نیاز باشد دیتابیس جدیدی ایجاد شود: (ایجاد گروه فایل مربوطه و سپس تنظیمات مسیر آن)

CREATE DATABASE Test_Db
ON
PRIMARY ( NAME = TestDb1,
FILENAME = 'C:\DATA\Test_Db.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Testfsg1,
FILENAME = 'C:\DATA\Learning_DbStream')
LOG ON ( NAME = TestDbLog1,
FILENAME = 'C:\DATA\Test_Db.ldf')
GO

و یا ایجاد تغییرات بر روی دیتابیسی موجود: (ایجاد گروه فایل مخصوص و سپس افزودن فایل مربوطه و تنظیمات آن)

--add filegroup
alter database TestDb
Add FileGroup FileStreamFileGroup1 contains FileStream
go

--Add FileGroup To DB
alter database TestDB
add file
(
name = 'UserDocuments' ,
filename = 'C:\FileStream\UserDocuments'
) to filegroup FileStreamFileGroup1


تعریف جدولی آزمایشی به همراه فیلدی از نوع FileStream :
تا اینجا سرور و همچنین دیتابیس جهت پذیرش این نوع داده آماده شدند. اکنون نوبت به استفاده از آن است:

CREATE TABLE [tblFiles]
(
FileId UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE DEFAULT(NEWID()),
Title NVARCHAR(255) NOT NULL,
SystemFile VARBINARY(MAX) FILESTREAM NULL
)
ON [PRIMARY] FILESTREAM_ON [fsg1]

توسط دستور T-SQL فوق جدولی که از نوع داده FileStream استفاده می‌کند، ایجاد خواهد شد. این جدول همانطور که مشخص است حتما باید دارای یک فیلد منحصربفرد باشد (ر.ک. مقاله قبل) و همچنین برچسب فایل استریم به فیلدی از نوع VARBINARY(MAX) نیز الصاق شده است. به علاوه گروه فایل آن نیز باید به صورت صریح مشخص گردد؛ که در مثال ما مطابق تصاویر به fsg1 تنظیم شده بود.

ادامه دارد ...

اشتراک‌ها
Tools for Apache Cordova - مثال ها و مستندات
Open source code is the norm for so many developers these days, and unsurprisingly, so is open documentation. From Azure to TypeScript, public repositories have become a go-to place for sharing samples, tutorials, and “tips and tricks” so that everyone can learn and contribute together as a community.
Tools for Apache Cordova - مثال ها و مستندات
اشتراک‌ها
SQLite در Windows 10

با همکاری مایکروسافت و تیم SQLite این بانک اطلاعاتی قرار است به عنوان جزئی از اجزای سیستمی ویندوز، معرفی، پشتیبانی، به روز رسانی و نگهداری شود.

SQLite در Windows 10
نظرات مطالب
کار با چندین نوع بانک اطلاعاتی متفاوت در Entity Framework Core
با سلام.
اگر بانک اطلاعاتی MariaDB هم باشد باز روال کار به همین صورت است؟
آیا IDesignTimeDbContextFactory  فعلی که زحمت کشیدید، فقط مخصوص SQLite می‌باشد؟
با سپاس فراوان.
اشتراک‌ها
معرفی SQL Server 2016 Query Store

The Query Store feature helps you to track query plans, runtime statistics and queries/plans history. It also helps you find regressing queries. You can quickly find new queries with multiple plans, identify un-efficient plans and force a better plan.

معرفی SQL Server 2016 Query Store