مطالب
خواندن فید گزارش آب و هوای یاهو با استفاده از روش Xml serialization

در مطلب قبلی (در مورد کتابخانه anti-xss مایکروسافت) از روش xml serialization برای خواندن فایل xml حملات استفاده کردیم.
ایجاد این کلاس و نگاشت اشیاء با توجه به ساختار ساده آن به صورت دستی و به‌سادگی انجام شد. اکنون به مثال زیر دقت بفرمائید:
سرویس آب و هوای یاهو برای شهرهای مختلف ایران از طریق لینک زیر قابل استفاده است:
http://weather.yahoo.com/regional/IRXX.html
اگر به صفحات شهرهای مختلف مراجعه نمائید، یک فید rss هم مشاهده خواهید کرد، برای مثال در مورد تهران داریم:
http://weather.yahooapis.com/forecastrss?p=IRXX0018&u=c
ساختار این فایل xml تا حدودی با یک rss استاندارد تطابق دارد. اما اگر به سورس xml آن دقت کنیم تگ‌های دیگری را نیز مشاهده خواهیم کرد که برای مثال دما ، تاریخ و شرایط جوی را به صورت دقیقی و با استفاده از اصول xml ارائه می‌دهند.

<yweather:condition text="Partly Cloudy" code="29" temp="10" date="Tue, 11 Nov 2008 5:30 pm IRT" />

خوب، برای دریافت این اطلاعات چه باید کرد؟ یکی از روش‌های متداول برای کار با این نوع داده‌ها، استفاده از کلاس DataSet در دات نت و فراخوانی متد ReadXml آن است (یک آدرس اینترنتی را هم می‌تواند دریافت کند). سپس مطابق روش‌های معمول ADO.Net می‌توان به تگ‌ها ومقادیر آنها دسترسی داشت.
روش‌ بالا هر چند مشکلی ندارد اما به زیبایی کار با خواص یک کلاس متناظر با آن فایل xml نیست. اما در اینجا برای استفاده از روش xml serialization یک مشکل وجود دارد! ایجاد دستی این کلاس که بیانگر عملکرد آن فایل xml است کار ساده‌ای نیست.
خوشبختانه به همراه SDK‌ دات نت فریم ورک 2، برنامه‌ای به نام xsd.exe نیز همراه است که کار ایجاد یک کلاس cs یا vb را از یک فایل xml جهت این منظور انجام می‌دهد (این برنامه برای مثال در مسیر C:\Program Files\Microsoft.NET\SDK\v2.0\Bin قرار دارد).

برای ایجاد فایل کلاس به صورت خودکار از روی یک فایل xml موجود باید به ترتیب زیر عمل کرد:
الف) ایجاد فایل xsd متناظر (XML Schema Definition)
برای اینکار در خط فرمان تایپ کنید:
xsd.exe file.xml

نکته 1:
روش دیگر انجام این کار : فایل xml را در VS.net باز کنید، از منوی بالای صفحه گزینه xml را انتخاب نموده و بر روی دکمه Create Schema کلیک کنید.

ب) ایجاد فایل cs یا vb از روی فایل(های) xsd ایجاد شده
در اینجا برای فید آب و هوای یاهو سه فایل xsd تولید خواهد شد. برای تبدیل آنها به کلاس cs باید دستور زیر را در خط فرمان اجرا کرد:

Xsd.exe file_1.xsd file_2.xsd file_3.xsd /c

این مورد نکته مهمی است و تنها اگر یکی از فایل‌ها اینجا ذکر شوند، کلاس ناقصی تشکیل خواهد شد. (برای نمونه فایل xssAttacks.xml مطلب قبلی، ساختار ساده‌ای داشته و تنها به یک فایل xsd ختم خواهد شد)

نکته 2:
برای انتخاب زبان VB (با توجه به این‌که پیش فرض آن CS است) می‌توان به صورت زیر عمل کرد:
xsd.exe file.xsd /c  /l:vb

نکته 3:
برای تولید فایل xsd ، از برنامه Infer.exe نیز می‌توان استفاده کرد (خروجی نهایی دقیق‌تری را ارائه می‌دهد). این برنامه را از اینجا دریافت کنید.

تصاویر زیر مقایسه دو فایل کلاس نهایی تولید شده از xsd های این دو برنامه است:






پس از طی این مراحل فایل کلاس ما برای xml serialization آماده خواهد شد. مرحله بعد دریافت اطلاعات و نگاشت آن به این کلاس تولید شده است:

public static rss DeserializeFromXML()
{
XmlSerializer deserializer =
new XmlSerializer(typeof(rss));
using (XmlReader reader = XmlReader.Create("http://weather.yahooapis.com/forecastrss?p=IRXX0018&u=c"))
{
return (rss)deserializer.Deserialize(reader);
}
}

کلاس rss از فید xml و فایل‌های xsd آن که تولید کردیم به صورت خودکار ایجاد شده است.
اکنون برای مثال خواندن وضعیت فعلی جوی از فید دریافتی به سادگی زیر است:

rss data = DeserializeFromXML();
MessageBox.Show(data.channel.item.condition.text);


مطالب
استفاده از shim و stub برای mock کردن در آزمون واحد
مقدمه:
از آنجایی که در این سایت در مورد shim و stub صحبتی نشده دوست داشتم مطلبی در این باره بزارم. در آزمون واحد ما نیاز داریم که یک سری اشیا را moq کنیم تا بتوانیم آزمون واحد را به درستی انجام دهیم. ما در آزمون واحد نباید وابستگی به لایه‌های پایین یا بالا داشته باشیم پس باید مقلدی از object هایی که در سطوح مختلف قرار دارند بسازیم.
شاید برای کسانی که با آزمون واحد کار کردند، به ویژه با فریم ورک تست Microsoft، یک سری مشکلاتی با mock کردن اشیا با استفاده از Mock داشته اند که حالا می‌خواهیم با معرفی فریم ورک‌های جدید، این مشکل را حل کنیم.
برای اینکه شما آزمون واحد درستی داشته باشید باید کارهای زیر را انجام دهید:
1- هر objectی که نیاز به mock کردن دارد باید حتما یا non-static باشد، یا اینترفیس داشته باشد.
2- شما احتیاج به یک فریم ورک تزریق وابستگی‌ها دارید که به عنوان بخشی از معماری نرم افزار یا الگوهای مناسب شی‌ءگرایی مطرح است، تا عمل تزریق وابستگی‌ها را انجام دهید.
3- ساختارها باید برای تزریق وابستگی در اینترفیس‌های object‌های وابسته تغییر یابند.

Shims و Stubs:
نوع stub همانند فریم ورک mock می‌باشد که برای مقلد ساختن اینترفیس‌ها و کلاس‌های non-sealed virtual یا ویژگی ها، رویدادها و متدهای abstract استفاده می‌شود. نوع shim می‌تواند کارهایی که stub نمی‌تواند بکند انجام دهد یعنی برای مقلد ساختن کلاس‌های static یا متدهای non-overridable استفاده می‌شود. با مثال‌های زیر می‌توانید با کارایی بیشتر shim و stub آشنا شوید.
یک پروژه mvc ایجاد کنید و نام آن را FakingExample بگذارید. در این پروژه کلاسی با نام CartToShim به صورت زیر ایجاد کنید:
namespace FakingExample
{
    public class CartToShim
    {
        public int CartId { get; private set; }
        public int UserId { get; private set; }
        private List<CartItem> _cartItems = new List<CartItem>();
        public ReadOnlyCollection<CartItem> CartItems { get; private set; }
        public DateTime CreateDateTime { get; private set; }
 
        public CartToShim(int cartId, int userId)
        {
            CartId = cartId;
            UserId = userId;
            CreateDateTime = DateTime.Now;
            CartItems = new ReadOnlyCollection<CartItem>(_cartItems);
        }
 
        public void AddCartItem(int productId)
        {
            var cartItemId = DataAccessLayer.SaveCartItem(CartId, productId);
            _cartItems.Add(new CartItem(cartItemId, productId));
        }
    }
}
و همچنین کلاسی با نام CartItem به صورت زیر ایجاد کنید:
public class CartItem
    {
        public int CartItemId { get; private set; }
        public int ProductId { get; private set; }
 
        public CartItem(int cartItemId, int productId)
        {
            CartItemId = cartItemId;
            ProductId = productId;
        }
    }
حالا یک پروژه unit test را با نام FakingExample.Tests اضافه کرده و نام کلاس آن را CartToShimTest بگذارید. یک reference از پروژه FakingExample تان به پروژه‌ی تستی که ساخته اید اضافه کنید. برای اینکه بتوانید کلاس‌های پروژه FakingExample را shim و یا stub کنید باید بر روی Reference پروژه تان راست کلیک کنید و گزینه Add Fakes Assembly را انتخاب کنید. وقتی این گزینه را می‌زنید، پوشه ای با نام Fakes در پروژه تست ایجاد شده و FakingExample.fakes در داخل آن قرار دارد همچنین در reference‌های پروژه تست، FakingExample.Fakes نیز ایجاد می‌شود.
اگر بر روی فایل fakes که در reference ایجاد شده دوبار کلیک کنید می‌توانید کلاس‌های CartItem و CartToShim را مشاهده کنید که هم نوع stub شان است و هم نوع shim آنها که در تصویر زیر می‌توانید مشاهده کنید.

ShimDataAccessLayer را که مشاهده می‌کنید یک متد SaveCartItem دارد که به دیتابیس متصل شده و آیتم‌های کارت را ذخیره می‌کند.

حالا می‌توانیم تست خود را بنویسیم. در زیر یک نمونه از تست را مشاهده می‌کنید:

[TestMethod]
        public void AddCartItem_GivenCartAndProduct_ThenProductShouldBeAddedToCart()
        {
            //Create a context to scope and cleanup shims
            using (ShimsContext.Create())
            {
                int cartItemId = 42, cartId = 1, userId = 33, productId = 777;
 
                //Shim SaveCartItem rerouting it to a delegate which 
                //always returns cartItemId
                Fakes.ShimDataAccessLayer.SaveCartItemInt32Int32 = (c, p) => cartItemId;
 
                var cart = new CartToShim(cartId, userId);
                cart.AddCartItem(productId);
 
                Assert.AreEqual(cartId, cart.CartItems.Count);
                var cartItem = cart.CartItems[0];
                Assert.AreEqual(cartItemId, cartItem.CartItemId);
                Assert.AreEqual(productId, cartItem.ProductId);
            }
        }
همانطور که در بالا مشاهده می‌کنید کدهای تست ما در اسکوپی قرار گرفته اند که محدوده shim را تعیین می‌کند و پس از پایان یافتن تست، تغییرات shim به حالت قبل بر می‌گردد. متد SaveCartItemInt32Int32 را که مشاهده می‌کنید یک متد static است و نمی‌توانیم با mock ویا stub آن را مقلد کنیم. تغییر اسم متد SaveCartItem به SaveCartItemInt32Int32 به این معنی است که متد ما دو ورودی از نوع Int32 دارد و به همین خاطر fake این متد به این صورت ایجاد شده است. مثلا اگر شما متد Save ای داشتید که یک ورودی Int و یک ورودی String داشت fake آن به صورت SaveInt32String ایجاد می‌شد.

به این نکته توجه داشته باشید که حتما برای assert کردن باید assert‌ها را در داخل اسکوپ ShimsContext قرار گرفته باشد در غیر این صورت assert شما درست کار نمی‌کند.

این یک مثال از shim بود؛ حالا می‌خواهم مثالی از یک stub را برای شما بزنم. یک اینترفیس با نام ICartSaver به صورت زیر ایجاد کنید:

public interface ICartSaver
    {
        int SaveCartItem(int cartId, int productId);
    }
برای shim کردن ما نیازی به اینترفیس نداشتیم اما برای استفاده از stub و یا Mock ما حتما به یک اینترفیس نیاز داریم تا بتوانیم object موردنظر را مقلد کنیم. حال باید یک کلاسی با نام CartSaver برای پیاده سازی اینترفیس خود بسازیم:
public class CartSaver : ICartSaver
    {
        public int SaveCartItem(int cartId, int productId)
        {
            using (var conn = new SqlConnection("RandomSqlConnectionString"))
            {
                var cmd = new SqlCommand("InsCartItem", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@CartId", cartId);
                cmd.Parameters.AddWithValue("@ProductId", productId);
 
                conn.Open();
                return (int)cmd.ExecuteScalar();
            }
        }
    }
حال تستی که با shim انجام دادیم را با استفاده از Stub انجام می‌دهیم:
[TestMethod]
        public void AddCartItem_GivenCartAndProduct_ThenProductShouldBeAddedToCart()
        {
            int cartItemId = 42, cartId = 1, userId = 33, productId = 777;
 
            //Stub ICartSaver and customize the behavior via a 
            //delegate, ro return cartItemId
            var cartSaver = new Fakes.StubICartSaver();
            cartSaver.SaveCartItemInt32Int32 = (c, p) => cartItemId;
 
            var cart = new CartToStub(cartId, userId, cartSaver);
            cart.AddCartItem(productId);
 
            Assert.AreEqual(cartId, cart.CartItems.Count);
            var cartItem = cart.CartItems[0];
            Assert.AreEqual(cartItemId, cartItem.CartItemId);
            Assert.AreEqual(productId, cartItem.ProductId);
        }
امیدوارم که این مطلب برای شما مفید بوده باشد.
نظرات مطالب
اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
سلام.  سناریویی رو در نظر بگیرید که کاربر(client) برای دسترسی به اکشن‌ها در کنترلر‌های api هر بار با درخواست خود access token که در مرحله قبلی ایجاد و ارسال شده را به سمت سرور ارسال کند. در این مورد میشه فقط با access token کار کرد و refresh token را از سیستم فوق حذف کرد. چون در مطلب فوق فرمودید : "refreshToken فقط یک Guid است. کار آن ساده سازی و به روز رسانی عملیات Login بدون ارائه‌ی نام کاربری و کلمه‌ی عبور است. ".  فلسفه استفاده از refreshToken در سیستم مذکور  با خود accessToken قابل پیاده سازی نیست؟ هر بار که کاربر درخواستی به سمت سرور ارسال کرد AccessToken را ارسال و پس از بررسی و احراز هویت کاربر دسترسی‌ها رو مشخص کند.
مطالب
بررسی Transactions و Locks در SQL Server

مقدمه

SQL Server، با هر تقاضا به عنوان یک واحد مستقل رفتار می‌کند. در وضعیت‌های پیچیده ای که فعالیت‌ها توسط مجموعه ای از دستورات SQL انجام می‌شود، به طوری که یا همه باید اجرا شوند یا هیچکدام اجرا نشوند، این روش مناسب نیست. در چنین وضعیت هایی، نه تنها تقاضاهای موجود در یک دنباله به یکدیگر بستگی دارند، بلکه شکست یکی از تقاضاهای موجود در دنباله، به معنای این است که کل تقاضاهای موجود در دنباله باید لغو شوند، و تغییرات حاصل از تقاضاهای اجراشده در آن دنباله خنثی شوند تا بانک اطلاعاتی به حالت قبلی برگردد.

1- تراکنش چیست؟

تراکنش شامل مجموعه ای از یک یا چند دستور SQL است که به عنوان یک واحد عمل می‌کنند. اگر یک دستور SQL در این واحد با موفقیت اجرا نشود، کل آن واحد خنثی می‌شود و داده هایی که در اجرای آن واحد تغییر کرده اند، به حالت اول برگردانده می‌شود. بنابراین تراکنش وقتی موفق است که هر یک از دستورات آن با موفقیت اجرا شوند. برای درک مفهوم تراکنش مثال زیر را در نظر بگیرید: سهامدار A در معامله ای 400 سهم از شرکتی را به سهامدار B می‌فروشد. در این سیستم، معامله وقتی کامل می‌شود که حساب سهامدار A به اندازه 400 بدهکار و حساب سهامدار B همزمان به اندازه 400 بستانکار شود. اگر هر کدام از این مراحل با شکست مواجه شود، معامله انجام نمی‌شود.


2- خواص تراکنش

هر تراکنش دارای چهار خاصیت است (معروف به ACID) که به شرح زیر می‌باشند:


2-1- خاصیت یکپارچگی (Atomicity)

یکپارچگی به معنای این است که تراکنش باید به عنوان یک واحد منسجم (غیر قابل تفکیک) در نظر گرفته شود. در مثال مربوط به مبادله سهام، یکپارچگی به معنای این است که فروش سهام توسط سهامدار A و خرید آن سهام توسط سهامدار B، مستقل از هم قابل انجام نیستند و برای این که تراکنش کامل شود، هر دو عمل باید با موفقیت انجام شوند.
اجرای یکپارچه، یک عمل "همه یا هیچ" است. در عملیات یکپارچه، اگر هر کدام از دستورات موجود در تراکنش با شکست مواجه شوند، اجرای تمام دستورات قبلی خنثی می‌شود تا به جامعیت بانک اطلاعاتی آسیب نرسد.

2-2- خاصیت سازگاری (Consistency)

سازگاری زمانی وجود دارد که هر تراکنش، سیستم را در یک حالت سازگار قرار دهد (چه تراکنش به طور کامل انجام شود و چه در اثر وجود خطایی خنثی گردد). در مثال مبادله سهام، سازگاری به معنای آن است که هر بدهکاری مربوط به حساب فروشنده، موجب همان میزان بستانکاری در حساب خریدار می‌شود.
در SQL Server، سازگاری با راهکار ثبت فایل سابقه انجام می‌گیرد که تمام تغییرات را در بانک اطلاعاتی ذخیره می‌کند و جزییات را برای ترمیم تراکنش ثبت می‌نماید. اگر سیستم در اثنای اجرای تراکنش خراب شود، فرآیند ترمیم SQL Server با استفاده از این اطلاعات، تعیین می‌کند که آیا تراکنش با موفقیت انجام شده است یا خیر، و در صورت عدم موفقیت آن را خنثی می‌کند. خاصیت سازگاری تضمین می‌کند که بانک اطلاعاتی هیچگاه تراکنش‌های ناقص را نشان نمی‌دهد.

2-3- خاصیت تفکیک (Isolation)

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

2-4- پایداری (Durability)

پایداری به معنای این است که تغییرات حاصل از نهایی شدن تراکنش، حتی در صورت خرابی سیستم نیز پایدار می‌ماند. اغلب سیستم‌های مدیریت بانک اطلاعاتی رابطه ای، از طریق ثبت تمام فعالیت‌های تغییر دهنده‌ی داده‌ها در بانک اطلاعاتی، پایداری را تضمین می‌کنند. در صورت خرابی سیستم یا رسانه ذخیره سازی داده ها، سیستم قادر است آخرین بهنگام سازی موفق را هنگام راه اندازی مجدد، بازیابی کند. در مثال مربوط به مبادله سهام، پایداری به معنای این است که وقتی انتقال سهام از سهامدار A به B با موفقیت انجام گردید، حتی اگر سیستم بعداً خراب شد، باید نتیجه‌ی آن را منعکس سازد.

3- مشکلات همزمانی(Concurrency Effects):

3-1- Dirty Read:

زمانی روی می‌دهد که تراکنشی رکوردی را می‌خواند، که بخشی از تراکنشی است که هنوز تکمیل نشده است، اگر آن تراکنش Rollback شود اطلاعاتی از بانک اطلاعاتی دارید که هرگز روی نداده است.
 اگر سطح جداسازی تراکنش (پیش فرض) Read Committed باشد، این مشکل بوجود نمی‌آید.

3-2- Non-Repeatable Read:

زمانی ایجاد می‌شود که رکوردی را دو بار در یک تراکنش می‌خوانید و در این اثنا یک تراکنش مجزای دیگر داده‌ها را تغییر می‌دهد. برای پیشگیری از این مسئله باید سطح جداسازی تراکنش برابر با Repeatable Read یا Serializable باشد.

3-3- Phantoms:

با رکوردهای مرموزی سروکار داریم که گویی تحت تاثیر عبارات Update و Delete صادر شده قرار نگرفته اند. به طور خلاصه شخصی عبارت Insert را درست در زمانی که Update مان در حال اجرا بوده انجام داده است، و با توجه به اینکه ردیف جدیدی بوده و قفلی وجود نداشته، به خوبی انجام شده است. تنها چاره این مشکل تنظیم سطح Serializable است و در این صورت بهنگام رسانی‌های جداول نباید درون بخش Where قرار گیرد، در غیر این صورت Lock خواهند شد.

3-4- Lost Update:

زمانی روی می‌دهد که یک Update به طور موفقیت آمیزی در بانک اطلاعاتی نوشته می‌شود، اما به طور اتفاقی توسط تراکنش دیگری بازنویسی می‌شود. راه حل این مشکل بستگی به کد شما دارد و بایست به نحوی تشخیص دهید، بین زمانی که داده‌ها را می‌خوانید و زمانی که می‌خواهید آنرا بهنگام کنید، اتصال دیگری رکورد شما را بهنگام کرده است.

4- منابع قابل قفل شدن

6 منبع قابل قفل شدن برای SQL Server وجود دارد و آن‌ها سلسله مراتبی را تشکیل می‌دهند. هر چه سطح قفل بالاتر باشد، Granularity  کمتری دارد. در ترتیب آبشاری Granularity عبارتند از:
•  Database: کل بانک اطلاعاتی قفل شده است، معمولاً طی تغییرات Schema بانک اطلاعاتی روی می‌دهد.
•  Table: کل جدول قفل شده است، شامل همه اشیای مرتبط با جدول.
•  Extent: کل Extent (متشکل از هشت Page) قفل شده است.
•  Page: همه داده‌ها یا کلیدهای Index در آن Page قفل شده اند.
•  Key: قفلی در کلید مشخصی یا مجموعه کلید هایی Index وجود دارد. ممکن است سایر کلید‌ها در همان Index Page تحت تاثیر قرار نگیرند.
•  (Row or Row Identifier (RID: هر چند قفل از لحاظ فنی در Row Identifier قرار می‌گیرد ولی اساساً کل ردیف را قفل می‌کند.

5- تسریع قفل (Lock Escalation) و تاثیرات قفل روی عملکرد

اگر تعداد آیتم‌های قفل شده کم باشد نگهداری سطح بهتری از Granularity (مثلاً RID به جای Page) معنی دار است. هرچند با افزایش تعداد آیتم‌های قفل شده، سربار مرتبط با نگهداری آن قفل‌ها در واقع باعث کاهش عملکرد می‌شود، و می‌تواند باعث شود قفل به مدت طولانی‌تری در محل باشد(هر چه قفل به مدت طولانی‌تری در محل باشد، احتمال این که شخصی آن رکورد خاص را بخواهد بیشتر است).
هنگامی که تعداد قفل نگهداری شده به آستانه خاصی برسد آن گاه قفل به بالاترین سطح بعدی افزایش می‌یابد و قفل‌های سطح پایین‌تر نباید به شدت مدیریت شوند (آزاد کردن منابع و کمک به سرعت در مجادله).
توجه شود که تسریع مبتنی بر تعداد قفل هاست و نه تعداد کاربران.

6- حالات قفل (Lock Modes):

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

6-1- (Shared Locks (S:

زمانی استفاده می‌شود، که فقط باید داده‌ها را بخوانید، یعنی هیچ تغییری ایجاد نخواهید کرد. Shared Lock با سایر Shared Lock‌های دیگر سازگار است، البته قفل‌های دیگری هستند که با Shared Lock سازگار نیستند. یکی از کارهایی که Shared Lock انجام می‌دهد، ممانعت از انجام Dirty Read از طرف کاربران است.

6-2- (Exclusive Locks (X:

این قفل‌ها با هیچ قفل دیگری سازگار نیستند. اگر قفل دیگری وجود داشته باشد، نمی‌توان به Exclusive Lock دست یافت و همچنین در حالی که Exclusive Lock فعال باشد، به هر قفل جدیدی از هر شکل اجازه ایجاد شدن در منبع را نمی‌دهند.
این قفل از اینکه دو نفر همزمان به حذف کردن، بهنگام رسانی و یا هر کار دیگری مبادرت ورزند، پیشگیری می‌کند.

6-3- (Update Locks (U:

این قفل ‌ها نوعی پیوند میان Shared Locks و Exclusive Locks هستند.
برای انجام Update باید بخش Where را (در صورت وجود) تایید اعتبار کنید، تا دریابید فقط چه ردیف هایی را می‌خواهید بهنگام رسانی کنید. این بدان معنی است که فقط به Shared Lock نیاز دارید، تا زمانی که واقعاً بهنگام رسانی فیزیکی را انجام دهید. در زمان بهنگام سازی فیزیکی نیاز به Exclusive Lock دارید.
Update Lock نشان دهنده این واقعیت است که دو مرحله مجزا در بهنگام رسانی وجود دارد، Shared Lock ای دارید که در حال تبدیل شدن به Exclusive Lock است. Update Lock تمامی Update Lock‌های دیگر را از تولید شدن باز می‌دارند، و همچنین فقط با Shared Lock و Intent Shared Lock‌ها سازگار هستند.

6-4- Intent Locks:

با سلسله مراتب شی سر و کار دارد. بدون Intent Lock، اشیای سطح بالاتر نمی‌دانند چه قفلی را در سطح پایین‌تر داشته اید. این قفل‌ها کارایی را افزایش می‌دهند و 3 نوع هستند:

6-4-1- (Intent Shared Lock (IS:

Shared Lock در نقطه پایین‌تری در سلسله مراتب، تولید شده یا در شرف تولید است. این نوع قفل تنها به Table و Page اعمال می‌شود.

6-4-2- (Intent Exclusive Lock (IX:

همانند Intent Shared Lock است اما در شرف قرار گرفتن در آیتم سطح پایین‌تر است.

6-4-3- (Shared With Intent Exclusive (SIX:

Shared Lock در پایین  سلسله مراتب شی تولید شده یا در شرف تولید است اما Intent Lock قصد اصلاح داده‌ها را دارد بنابراین در نقطه مشخصی تبدیل به Intent Exclusive Lock می‌شود.

6-5- Schema Locks:

به دو شکل هستند:

6-5-1- (Schema Modification Lock (Sch-M:

تغییر Schema به شی اعمال شده است. هیچ پرس و جویی یا سایر عبارت‌های Create، Alter و Drop نمی‌توانند در مورد این شی در مدت قفل Sch-M اجرا شوند. با همه حالات قفل ناسازگار است.

6-5-2- (Schema Stability Lock (Sch-S:

بسیار شبیه به Shared Lock است، هدف اصلی این قفل پیشگیری از Sch-M است وقتی که قبلاً قفل هایی برای سایر پرس و جو-ها (یا عبارت‌های Create، Alter و Drop) در شی فعال شده اند. این قفل با تمامی انواع دیگر قفل سازگار است به جز با Sch-M.

6-6- (Bulk Update Locks (BU:

این قفل‌ها بارگذاری موازی داده‌ها را امکان پذیر می‌کنند، یعنی جدول در مورد هر فعالیت نرمال (عبارات T-SQL) قفل می‌شود، اما چندین عمل bcp یا Bulk Insert را می‌توان در همان زمان انجام داد. این قفل فقط با Sch-S و سایر قفل هایBU سازگار است.

7- سطوح جداسازی (Isolation Level):

7-1- Read Committed (وضعیت پیش فرض):

با Read Committed همه Shared Lock‌های ایجاد شده، به محض اینکه عبارت ایجاد کننده آنها تکمیل شود، به طور خودکار آزاد می‌شوند. به طور خلاصه قفل‌های مرتبط با عبارت Select به محض تکمیل عبارت Select آزاد می‌شوند و SQL Server منتظر پایان تراکنش نمی‌ماند. اگر تراکنش پرس و جویی را انجام می‌دهد که داده‌ها را اصلاح می‌کند (Insert، Delete و Update) قفل‌ها برای مدت تراکنش نگه داشته می‌شوند.
با این سطح پیش فرض، می‌توانید مطمئن شوید جامعیت کافی برای پیشگیری از Dirty Read دارید، اما همچنان Phantoms و Non-Repeatable Read می‌تواند روی دهد.

7-2- Read Uncommitted:

خطرناک‌ترین گزینه از میان تمامی گزینه‌ها است، اما بالاترین عملکرد را به لحاظ سرعت دارد. در واقع با این تنظیم سطح تجربه همه مسائل متعدد هم زمانی مانند Dirty Read امکان پذیر است. در واقع با تنظیم این سطح به SQL Server اعلام می‌کنیم هیچ قفلی را تنظیم نکرده و به هیچ قفلی اعتنا نکند، بنابراین هیچ تراکنش دیگری را مسدود نمی‌کنیم.
می‌توانید همین اثر Read Uncommitted را با اضافه کردن نکته بهینه ساز  NOLOCK در پرس و جو‌ها بدست آورید.

7-3- Repeatable Read:

سطح جداسازی را تا حدودی افزایش می‌دهد و سطح اضافی محافظت همزمانی را با پیشگیری از Dirty Read و همچنین Non-Repeatable Read فراهم می‌کند.
پیشگیری از Non-Repeatable Read بسیار مفید است اما حتی نگه داشتن Shared Lock تا زمان پایان تراکنش می‌تواند دسترسی کاربران به اشیا را مسدود کند، بنابراین به بهره وری لطمه وارد می‌کند.
نکته بهینه ساز برای این سطح REPEATEABLEREAD است.

7-4- Serializable:

این سطح از تمام مسائل هم زمانی پیشگیری می‌کند به جز برای Lost Update.
این تنظیم سطح به واقع بالاترین سطح آنچه را که سازگاری نامیده می‌شود، برای پایگاه داده فراهم می‌کند. در واقع فرآیند بهنگام رسانی برای کاربران مختلف به طور یکسان عمل می‌کند به گونه ای که اگر همه کاربران یک تراکنش را در یک زمان اجرا می‌کردند، این گونه می‌شد « پردازش امور به طور سریالی».
با استفاده از نکته بهینه ساز SERIALIZABLE یا HOLDLOCK در پرس و جو شبیه سازی می‌شود.

7-5- Snapshot:

جدترین سطح جداسازی است که در نسخه 2005 اضافه شد، که شبیه ترکیبی از Read Committed و Read Uncommitted است. به طور پیش فرض در دسترس نیست، در صورتی در دسترس است که گزینه ALLOW_SNAPSHOT_ISOLATION برای بانک اطلاعاتی فعال شده  باشد.(برای هر بانک اطلاعاتی موجود در تراکنش)
Snapshot مشابه Read Uncommitted هیچ قفلی ایجاد نمی‌کند. تفاوت اصلی آن‌ها در این است که تغییرات صورت گرفته در بانک اطلاعاتی را در زمان‌های متفاوت تشخیص می‌دهند. هر تغییر در بانک اطلاعاتی بدون توجه به زمان یا Commit شدن آن، توسط پرس و جو هایی که سطح جداسازی Read Uncommitted را اجرا می‌کنند، دیده می‌شود. با Snapshot فقط تغییراتی که قبل از شروع تراکنش، Commit شده اند، مشاهده می‌شود.
از شروع تراکنش Snapshot، تمامی داده‌ها دقیقاً مشاهده می‌شوند، زیرا در شروع تراکنش Commit شده اند.
نکته: در حالی که Snapshot توجهی به قفل‌ها و تنظیمات آنها ندارد، یک حالت خاص وجود دارد. چنانچه هنگام انجام Snapshot یک عمل Rollback (بازیافت) بانک اطلاعاتی در جریان باشد، تراکنش Snapshot قفل‌های خاصی را برای عمل کردن به عنوان یک مکان نگهدار  و سپس انتظار برای تکمیل Rollback تنظیم می‌کند. به محض تکمیل Rollback، قفل حذف شده و Snapshot به طور طبیعی به جلو حرکت خواهد کرد.


 
بازخوردهای دوره
ارتباطات بلادرنگ و SignalR
به نظر اسکریپت‌های آن بارگذاری نشده‌اند. در کروم روی دکمه F12 کلیک کنید تا کنسول آن ظاهر شود. بعد بررسی کنید آیا خطایی در برگه network آن گزارش شده یا حتی در کنسول لاگ‌های آن که خطاهای جاوا اسکریپتی را نمایش می‌دهد. با فایرباگ هم می‌شود این نوع برنامه‌ها را دیباگ کرد.
اطلاعات بیشتر: «عیب یابی و دیباگ برنامه‌های SignalR »
همچنین این مثال‌ها را از اینجا نیز می‌توانید دریافت کنید: SignalRSamples.zip  
مطالب
پیکربندی electron packager
یکی از ابزارهایی که برای این بسته تولید شده‌است و به شما کمک می‌کند تا بسته بندی راحت‌تری داشته باشید و یک نوع ویزارد را در CLI به شما نشان می‌دهد، ابزار electron-packager-interactive است که به طریق زیر آن را نصب می‌کنیم:
npm install -g electron-packager-interactive
سپس با وارد کردن دستور زیر
electron-packager-interactive
یا خلاصه تر
epi
آن را اجرا میکنیم و سوال‌های زیر به ترتیب از شما پرسیده و طبق پاسخ آن، بسته بندی صورت می‌گیرد:
? Overwrite output directory ? Yes
? Use asar source packaging ? Yes
? Select Electron app source directory: E:\Projects\electron\dbtest
? Select Electron app output directory: E:\Projects\electron\dbtest\releases
? Select Application name: myapp
? Select App Bundle Id (optional): 12
? Select App Version(optional): 0.0.1
? Select Electron icon file:
? Select Electron version release: 0.34.1
? Select platforms: all
? Select architecture: all


پیکربندی از طریق packages.json
شما می‌توانید برای بسته بندی از طریق این فایل، یک پروفایل ایجاد کنید و بر اساس اطلاعات هر پروفایلی که دوست دارید، بسته بندی را انجام دهید؛ یا مثلا دوست دارید برای هر پلتفرم تنظیمات خاصی را داشته باشید. برای اینکار شما می‌توانید به تعداد دلخواهی از خصوصیت build را مانند کد زیر داشته باشید:
"scripts": {
    "start": "./node_modules/.bin/electron .",
    "test":"eslint .",
    "build":"electron-packager . myapp --platform=all --arch=all --overwrite --ignore=node_modules/dev-dependency --asar",
    "build:win32":"electron-packager . myapp --platform=win32 --arch=ia32 --overwrite --ignore=node_modules/dev-dependency --asar",
    "build:win64":"electron-packager . myapp --platform=win64 --arch=x64 --overwrite"
  },
در کد بالا من سه نوع پیکربندی را برای build تعریف کرده‌ام. در اولین پیکربندی بسته بندی برنامه برای همه پلتفرم‌ها و معماری‌ها انجام می‌گیرد و در دومین پیکربندی فقط برای سیستم عامل ویندوز نسخه 32 بیتی آن و  در سومین پیکربندی، نسخه 64 بیتی مد نظر است که البته ویژگی asar و فلگ ignore را مانند دو پیکربندی قبلی به همراه ندارد. برای صدا زدن آن‌ها در CLI هم باید به شکل زیر عمل کنید:
npm run build
npm run build:win32
npm run build:win64

افزودن فایل‌های ایستا به بسته بندی
یکی از مشکلاتی که هنگام بسته بندی به آن برخوردم این بود که فایل sql.txt به بسته نهایی اضافه نشده بود و برنامه به همین علت terminate میشد. برای اینکه به این مشکل دچار نشوید، بهتر هست این موارد را داخل یک دایرکتوری قرار داده تا بعد از بسته بندی، دایرکتوری را به راحتی به بسته نهایی کپی کنید. با توجه به صحبت‌هایی که با یکی از تولیدکنندگان پکیج داشتم، ایشان متذکر شدند با اینکه این بسته حاوی یک لیست سیاه برای انتقال فایل‌هاست، ولی فایلی مثل sql.txt مشکلی ندارد. اما با این حال اگر به مشکل برخورد کردید، این مورد را خودتان دستی انجام دهید.
مطالب
معرفی Decorator Design Pattern

فرض کنید که می‌خواهیم یک برنامه برای یک فروشگاه نوشیدنی (مانند coffee shop) بنویسیم ، این فروشگاه در ابتدای کار ممکن است ، منوی ساده‌ای جهت ارائه به مشتری داشته باشد. برای مثال ممکن است که فقط 3 یا 4 محصول داشته باشد. بنابراین ممکن است ما برنامه‌ای را که می‌خواهیم برای این مشتری بنویسیم به صورت زیر طراحی کنیم:

 


که بسیار طبیعی و درست می‌باشد. اما حالا در نظر بگیرید که این فروشگاه در آینده ممکن است محصولات خود را افزایش بدهد و یا حالاتی که ممکن است این محصولات با هم ادغام شوند را در نظر بگیرید. برای مثال ممکن است شما بخواهید که قهوه‌تان را با شیر نوش جان کنید و یا ....

بنابراین تعداد این حالات را در نظر بگیرید که در آینده ممکن است چقدر زیاد بشود:

 

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

خوب با این روش ما n   کلاس تشکیل شده در رویکرد اول را فقط به 5 کلاس تبدیل کردیم. خوب این روشی بسیار ایده‌ال به نظر می‌رسد. اما ممکن است در آینده که تعداد چاشنی‌های ما بالا می‌رود و همچنین تعداد محصولاتمان نیز ممکن است بیشتر شود مجبور شویم که تعداد این کلاس‌ها را بیشتر کنیم،  و یا فکر کنید که ما می‌خواهیم هریک از چاشنی‌هایمان، یک قیمت را نسبت بدهیم. بنابراین مجبوریم که تمامی این‌ها را در کلاس پایه اضافه کنیم؛ بله درست است، ما با کلاس پایه‌ی حجیمی روبرو می‌شویم که بیشتر خواص و یا متدهای آن برای زیر کلاس‌های دیگر مناسبت نیستند. خوب آیا روش بهتری برای جلوگیری از این مشکل داریم؟ بلی.

خوب ما به این مسئله به این صورت نگاه می‌کنیم که شروع می‌کنیم با نوشیدنی‌ها و آن‌ها را با چاشنی‌ها در زمان اجرا تزیین (Decorate) می‌کنیم؛ نه کامپایل.

برای مثال اگر مشتری ما یک نوشیدنی DarkRoast با Mocha و Whip خواست، سپس ما :
1- یک شی از DarkRoast  ایجاد می‌کنیم .
2- آن را با یک شی از  Mocha  تزئین می‌کنیم.
3- آن را با یک شی از Whip - تزیین می‌کنیم.
4- متد Cost()  را صدا می‌زنیم و  یک Delegation  را برای اضافه کردن قیمت چاشنی‌ها در نظر می‌گیریم.

بسیار خوب؛ اما ما عملیات تزئین یک شی را چگونه انجام می‌دهیم و delegation ما چگونه عمل می‌کند .
یک اشاره : به شیء تزئین کننده، مانند یک Wrappers فکر کنید. اجاز بدهید ببینم که چه طور این کار را انجام می‌دهیم.
1- یک شی از DarkRoast  ایجاد می‌کنیم.
 
 

2- آن را با یک شی از  Mocha  تزئین می‌کنیم.

3- آن را با یک شی از Whip تزیین می‌کنیم 


 4- حالا زمان محاسبه قیمت محصول برای مشتری فرا رسیده است. ما این کار را را با صدا زدن بیرونی‌ترین Decorator(Whip)  انجام می‌دهیم و شی  whip به کمک  Delegate مابقی توابع cost را صدا می‌زند.



  در آخر شما می‌توانید پیاده سازی این برنامه را به زبان جاوا در زیر مشاهد نمایید.

public abstract class Beverage
{
     string description ="unknow beverage";
     public String getDescription(){
         return description;
     }
     public abstract double cost();
}

public abstract class CondimentDecorator extends Beverage {
    public abstract string getDescription();
}

public class Espersso extends Beverage{
   public Espersso()
   {
      description="Espersso";
   }
   public double cost(){
     return 1.99;
   }
}

public class HouseBelend extends Beverage {
   public HouseBelend()
   {
     description="HouseBelend";
   }
   public double cost()
   {
     return .89;
   }
}

public class mocha extends condimateDecorator {
  Beverage beverage;
  public mocha(Beverage beverage)
  {
     this.beverage=beverage;
  }
   public string getDescription(){
      return beverage.getdescription() + "Mocha";
   }
   public double cost(){
     return .20 +beverage.cost
   }
}


// Now Use These classes in Final form
Beverage beverage=new Espersso();
//Customers want a coffe with double milk and whip
beverage=new mocha(beverage);
beverage=new mocha(meverage);
beverage=new whip(beverage);

system.out.println(beverage.getDescription() + "$" +beverage.cost());
نظرات مطالب
آشنایی با TransactionScope
با سلام
من روی پروژه‌ای کار می‌کنم که در اون سرور داده‌ها از سرور وب جداست. روی هردو سرور فایروال خاموش بوده و تنظیمات مربوط به Network DTC نیز روی هردو سرور انجام شده است(منظور تنظیمات زیر است)
1-Notwork DTC Access
2- Allow Remote Client
3- Allow Remote Administration
4-Allow Inbound
5-Allow OutBound
6 -No Authentication Required. 

اما با وجود همه این تنظیمات در هنگام کارکردن با دیتابیس با خطای زیر مواجه میشم
System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed 
توی اینترنت خیلی سرچ کردم ولی همه معتقد هستند که مشکل فایروال هست در حالی که فایروال سرورها کلا خاموشه.
نکته اینکه روی هردو سرور ویندوز سرور 2003 نصب هست. 
آیا کسی هست که بتونه در این مورد منو راهنمایی کنه. ممنون
مطالب
آزمایش Web APIs توسط Postman - قسمت سوم - نکات تکمیلی ایجاد درخواست‌ها
تا اینجا، یک دید کلی را نسبت به postman و توانمندی‌های آن پیدا کرده‌ایم. در ادامه قصد داریم، تعدادی نکته‌ی تکمیلی مهم را که در حین ساخت درخواست‌ها در postman، به آن‌ها نیاز پیدا خواهیم کرد، بررسی کنیم.


ایجاد یک request bin جدید

برای مشاهده‌ی محتوای ارسالی توسط postman بدون برپایی وب سرویس خاصی، از سایت requestbin استفاده خواهیم کرد. در اینجا با کلیک بر روی دکمه‌ی create a request bin، یک آدرس موقتی را مانند http://requestbin.fullcontact.com/1gdduy21 برای شما تولید می‌کند. می‌توان انواع و اقسام درخواست‌ها را به این آدرس ارسال کرد و سپس با ریفرش کردن آن در مرورگر، دقیقا محتوای ارسالی به سمت سرور را بررسی نمود.
برای مثال اگر همین آدرس را در postman وارد کرده و سپس بر روی دکمه‌ی send آن کلیک کنیم، پس از ریفرش صفحه، چنین تصویری حاصل می‌شود:



Encoding کوئری استرینگ‌ها در postman

مثال زیر را درنظر بگیرید:


در اینجا با استفاده از گرید ساخت Query Params، دو کوئری استرینگ جدید را ایجاد کرده‌ایم که در دومی، مقدار وارد شده، دارای فاصله است. اگر این درخواست را ارسال کنیم، مشاهده خواهیم کرد که مقدار ارسالی توسط آن encoded نیست:


برای رفع این مشکل می‌توان بر روی تکست‌باکس ورود مقدار یک کلید، کلیک راست کرد و از منوی باز شده، گزینه‌ی encode URI component را انتخاب نمود:


البته برای اینکه این گزینه درست عمل کند، نیاز است یکبار کل متن را انتخاب کرد و سپس بر روی آن کلیک راست نمود، تا انتخاب گزینه‌ی encode URI component، به درستی اعمال شود:



امکان تعریف متغیرها در آدرس‌های HTTP

Postman از امکان تعریف path variables پشتیبانی می‌کند. برای مثال مسیر api.example.com/users/5/contracts/2 را در نظر بگیرید که می‌تواند سبب نمایش اطلاعات قرارداد دوم کاربر پنجم شود. برای پویا کردن یک چنین آدرسی در postman می‌توان از مسیری مانند api.example.com/users/:userid/contracts/:contractid استفاده کرد:


اگر به تصویر فوق دقت کنیم، متغیرهای شروع شده‌ی با :، در قسمت path variables ذکر شده‌اند و به سادگی قابل تغییر و مقدار دهی می‌باشند (در گریدی همانند گرید کوئری استرینگ‌ها) که برای آزمایش دستی، بسیار مفید هستند.


امکان ارسال فایل‌ها به سمت سرور

زمانیکه برای مثال، نوع درخواست به Post تغییر می‌کند، امکان تنظیم بدنه‌ی آن نیز مسیر می‌شود. در این حالت اگر گزینه‌ی form-data را انتخاب کنیم، با نزدیک کردن اشاره‌گر ماوس به هر ردیف جدید (پیش از ورود کلید آن ردیف)، می‌توان نوع Text و یا File را انتخاب کرد:


در اینجا پس از انتخاب گزینه‌ی File، می‌توان علاوه بر تعیین کلید این ردیف، با استفاده از دکمه‌ی select files، چندین فایل را نیز برای ارسال انتخاب کرد:



روش انتقال درخواست‌های پیچیده به Postman

تا اینجا روش ساخت درخواست‌های متداولی را بررسی کردیم که آنچنان پیچیده، طولانی و به همراه جزئیات زیادی (مانند کوکی‌ها،انواع و اقسام هدرها و ...) نبودند. فرض کنید می‌خواهید درخواست ارسال یک امتیاز جدید را به مطلبی در سایت جاری، توسط Postman شبیه سازی کنیم. برای اینکار، توسط مرورگر کروم به سایت وارد شده و پس از لاگین و تنظیم خودکار کوکی‌های اعتبارسنجی، برگه‌ی developer tools مرورگر را باز کرده و در آن، قسمت network را انتخاب کنید:


در اینجا گزینه‌ی preserve log را نیز انتخاب کنید تا پس از ارسال درخواستی، سابقه‌ی عملیات، پاک نشود. سپس به صورت معمولی به مطلبی امتیاز دهید. اکنون بر روی مدخل درخواست آن کلیک راست کرده و از منوی ظاهر شده، گزینه‌ی Copy->Copy as cURL را انتخاب کنید تا این عملیات و تمام جزئیات مرتبط با آن‌را تبدیل به یک دستور cURL کرده و به حافظه کپی کند.
سپس در postman، از منوی بالای صفحه، سمت چپ آن، گزینه‌ی Import را انتخاب کنید:


در ادامه این دستور کپی شده‌ی در حافظه را در قسمت Paste Raw Text، قرار دهید و بر روی دکمه‌ی import کلیک کنید:


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

یک نکته‌ی مهم: در حالت انتخاب Copy->Copy as cURL در مرورگر کروم، دو گزینه‌ی cmd و bash موجود هستند. حالت bash را باید انتخاب کنید تا توسط postman به دسترسی parse شود. حالت cmd یک چنین خروجی مشکل داری را در postman تولید می‌کند که قابل ارسال به سمت سرور نیست:


اما جزئیات حالت bash آن، به درستی parse شده‌است و قابلیت send مجدد را دارد:



کار با کوکی‌ها در Postman

کوکی‌ها نیز در اصل به صورت یک هدر HTTP به صورت خودکار توسط مرورگرها به سمت سرور ارسال می‌شوند؛ اما Postman روش ساده‌تری را برای تعریف و کار با آن‌ها ارائه می‌دهد (و ترجیح می‌دهد که بین کوکی‌ها و هدرها تفاوت قائل شود؛ هم در زمان ارسال و هم در زمان نمایش response که در کنار قسمت هدرهای دریافتی از سرور، لیست کوکی‌های دریافتی نیز به صورت مجزایی نمایش داده می‌شوند).


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


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


به اشتراک گذاری سابقه‌ی درخواست‌ها

در قسمت اول مشاهده کردیم که برای ذخیره سازی درخواست‌ها، باید آن‌ها را در مجموعه‌های Postman، ذخیره و ساماندهی کرد. برای گرفتن خروجی از این مجموعه‌ها و به اشتراک گذاشتن آن‌ها، اگر اشاره‌گر ماوس را بر روی نام یک مجموعه حرکت دهیم، یک دکمه‌ی جدید با برچسب ... ظاهر می‌شود:


با کلیک بر روی آن، یکی از گزینه‌های آن، export نام دارد که جزئیات تمام درخواست‌های یک مجموعه را به صورت یک فایل JSON ذخیره می‌کند. برای نمونه فایل JSON خروجی دو قسمت قبل این سری را می‌توانید از اینجا دریافت کنید: httpbin.postman_collection.json
پس از تولید این فایل JSON، برای بازیابی آن می‌توان از دکمه‌ی Import که در منوی سمت چپ، بالای postman قرار دارد، استفاده کرد که نمونه‌ای از آن‌را برای Import جزئیات درخواست‌های cURL پیشتر مشاهده کردید. در اینجا، همان اولین گزینه‌ی دیالوگ Import که Import file نام دارد، دقیقا برای همین منظور تدارک دیده شده‌است.