- در سایت Stack overflow از آن استفاده میشود (^).
- در SQL Server Azure حالت پیش فرض ایجاد دیتابیسها و تراکنشهای جدید است (^).
- در Entity framework 6 حالت پیش فرض تراکنشهای ایجاد شده، قرار گرفته است (^ ).
و ... در Oracle، تنها حالت مدیریت مسایل همزمانی است! (البته به نام MVCC، اما با همین عملکرد)
اما READ_COMMITTED_SNAPSHOT در SQL Server چیست و کاربرد آن کجا است؟
اگر استفاده گسترده و سنگینی از SQL Server داشته باشید، حتما به پیغامهای خطای deadlock آن برخوردهاید:
Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
در SQL Server 2005 برای بهبود مقیاس پذیری SQL Server و کاهش خطاهای deadlock، مکانیزم READ_COMMITTED_SNAPSHOT معرفی گشت.
به صورت خلاصه زمانیکه که تراکنش مورد نظر تحت حالت READ COMMITTED SNAPSHOT انجام میشود، optimistic reads and pessimistic writes خواهیم داشت (خواندنهای خوشبینانه و نوشتنهای بدبینانه). در این حالت تضمین میشود که خواندن اطلاعات داخل یک تراکنش، شامل اطلاعات تغییر یافته توسط سایر تراکنشهای همزمان نخواهد بود. همچنین زمانیکه در این بین، اطلاعاتی خوانده میشود، بر روی این اطلاعات برخلاف حالت READ COMMITTED قفل قرار داده نمیشود. بنابراین تراکنشهایی که درحال خواندن اطلاعات هستند، تراکنشهای همزمانی را که در حال نوشتن اطلاعات میباشند، قفل نخواهد کرد و برعکس.
نحوه فعال سازی READ_COMMITTED_SNAPSHOT
فعال سازی READ_COMMITTED_SNAPSHOT باید ابتدا در سطح یک بانک اطلاعاتی SQL Server انجام شود:
ALTER DATABASE testDatabase SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE testDatabase SET READ_COMMITTED_SNAPSHOT ON;
حالت READ_COMMITTED_SNAPSHOT خصوصا برای برنامههای وبی که تعداد بالایی Read در مقابل تعداد کمی Write دارند، به شدت بر روی کارآیی و بالا رفتن سرعت و مقیاس پذیری آنها تاثیر خواهد داشت؛ به همراه حداقل تعداد deadlockهای حاصل شده.
در Entity framework وضعیت به چه صورتی است؟
EF از حالت پیش فرض مدیریت مسایل همزمانی در SQL Server یا همان حالت READ COMMITTED در زمان فراخوانی متد SaveChanges استفاده میکند.
در EF 6 این حالت پیش فرض به READ_COMMITTED_SNAPSHOT تغییر کرده است. البته همانطور که عنوان شد، پیشتر باید بانک اطلاعاتی را نیز جهت پذیرش این نوع تراکنشها آماده ساخت.
اگر از نگارشهای پایینتر از EF 6 استفاده میکنید، برای استفاده از حالت READ_COMMITTED_SNAPSHOT باید صراحتا IsolationLevel را مشخص ساخت:
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel= IsolationLevel.Snapshot })) { // update some tables using entity framework context.SaveChanges(); transactionScope.Complete(); }
کتاب آموزش زبان برنامه نویسی Erlang
سخت افزارهای جدید به طور فزاینده ای همروند (parallel) شده اند، بنابراین زبانهای برنامه نویسی باید از همزمانی پشتیبانی کنند یا محکوم به مرگ هستند. نقل قولی از استیو جابز: راهی که شرکتهای ساخت پردازشگر در پیش گرفته اند این هست که هستههای بیشتر و بیشتر اضافه کنند، اما کسی نمیداند که چگونه برای آنها برنامه بنویسید. منظورم دو، بله؛ چهار، نه واقعا؛ هشت؛ کلا فراموشش کنید.
خب استیو اشتباه میکرده است؛ الان ما میدانیم که چگونه برای پردازشگرهای چند هسته ای برنامه بنویسیم. ما برنامه هایمان را با Erlang مینویسیم و هرچقدر که بر تعداد هستهها افزوده شود برنامهی ما نیز سریعتر از قبل کار میکند.
Erlang از همان ابتدا برای برنامه نویسی سیستمهای همزمان، توزیع پذیر، تحمل پذیر بودن خطا (fault-tolerant)، مقیاس پذیر (scalable)، نرم و بلادرنگ طراحی شده بود. سیستمهای نرم بلادرنگ به مانند سیستمهای ارتباطات تلفنی، سیستمهای بانکی و ... که در آنها تعدا دفعات پاسخ گویی سریع بسیار با اهمیت است. سیستمهای مبتنی بر Erlang در مقیاس عظیمی مستقر شده اند و بخشهای قابل توجهی از شبکه ارتباطات تلفن همراه دنیا را کنترل میکنند.
اگر مشکل شما همزمانی هست، اگر در حال ساخت سیستم چند کاربره هستید و یا اگر در حال ساخت سیستمی هستید که با زمان سرو کار دارد، استفاده از Erlang میتواند بخش زیادی از کارهای شما را کم کند، چرا که Erlang فقط برای ساخت چنین سیستمهای طراحی شده است.
ASP.NET MVC #6
آشنایی با انواع ActionResult
در قسمت چهارم، اولین متد یا اکشنی که به صورت خودکار توسط VS.NET به برنامه اضافه شد، اینچنین بود:
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
}
توضیحات تکمیلی مرتبط با خروجی از نوع ActionResult ایی را که مشاهده میکنید، در این قسمت ارائه خواهد شد.
رفتار یک کنترلر توسط متدهایی که در آن کلاس تعریف میشوند، مشخص میگردد. هر متد هم از طریق یک URL مجزا قابل دسترسی و فراخوانی خواهد بود. این متدها که به آنها اکشن نیز گفته میشود باید عمومی بوده، استاتیک یا متد الحاقی (extension method) نباشند و همچنین دارای پارامترهایی از نوع ref و out نیز نباشند.
هر درخواست رسیده، به یک کنترلر و متدی عمومی در آن توسط سیستم مسیریابی، نگاشت خواهد شد. اگر علاقمند باشید که در یک کلاس کنترلر، متدی عمومی را از این سیستم خارج کنید، تنها کافی است آنرا با ویژگی (attribute) به نام NonAction مزین کنید:
using System.Web.Mvc;
namespace MvcApplication2.Controllers
{
public class HomeController : Controller
{
[NonAction]
public string ShowData()
{
return "Text";
}
public ActionResult Index()
{
ViewBag.Message = string.Format("{0}/{1}/{2}",
RouteData.Values["controller"],
RouteData.Values["action"],
RouteData.Values["id"]);
return View();
}
public ActionResult Search(string data = "*")
{
// do something ...
return View();
}
}
}
چند نکته در این مثال قابل ذکر است:
الف) در اینجا اگر شخصی آدرس http://localhost/home/showdata را درخواست نماید، با توجه به استفاده از ویژگی NonAction، با پیغام یافت نشد یا 404 مواجه میگردد.
ب) صرفنظر از پارامترهای یک متد و ساختار کلاس جاری، اطلاعات مسیریابی از طریق شیء RouteData.Values نیز در دسترس هستند که نمونهای از آنرا در اینجا بر اساس مقادیر پیش فرض تعاریف مسیریابی یک پروژه ASP.NET MVC ملاحظه مینمائید.
ج) در متد Search، از قابلیت امکان تعریف مقداری پیش فرض جهت آرگومانها در سی شارپ 4 استفاده شده است. به این ترتیب اگر شخصی آدرس http://localhost/home/search را وارد کند، چون پارامتری را ذکر نکرده است، به صورت خودکار از مقدار پیش فرض آرگومان data استفاده میگردد.
انواع Action Results در ASP.NET MVC
در ASP.NET MVC بجای استفاده مستقیم از شیء Response، از شیء ActionResult جهت ارائه خروجی یک متد استفاده میشود و مهمترین دلیل آن هم مشکل بودن نوشتن آزمونهای واحد برای شیء Response است که وهله سازی آن مساوی است با به کار اندازی موتور ASP.NET و Http Runtime آن توسط یک وب سرور (بنابراین در ASP.NET MVC سعی کنید شیء Response را فراموش کنید).
سلسه مراتب ActionResultهای قابل استفاده در ASP.NET در تصویر زیر مشخص شدهاند:
و در مثال زیر تقریبا انواع و اقسام ActionResultهای مهم و کاربردی ASP.NET MVC را میتوانید مشاهده کنید:
using System.Web.Mvc;
namespace MvcApplication2.Controllers
{
public class ActionResultsController : Controller
{
//http://localhost/actionresults/welcome
public string Welcome()
{
return "Hello, World";
}
//http://localhost/actionresults/index
public ActionResult Index() // or ContentResult
{
return Content("Hello, World");
}
//http://localhost/actionresults/SendMail
public void SendMail()
{
}
public ActionResult SendMailCompleted() // or EmptyResult
{
// do whatever
return new EmptyResult();
}
public ActionResult GetFile() // or FilePathResult
{
return File(Server.MapPath("~/content/site.css"), "text/css", "mySite.css");
}
public ActionResult UnauthorizedStatus() // or HttpStatusCodeResult/HttpUnauthorizedResult
{
return new HttpUnauthorizedResult("You need to login first.");
}
public ActionResult Status() // or HttpStatusCodeResult
{
return new HttpStatusCodeResult(501, "Server Error");
}
public ActionResult GetJavaScript() // or JavaScriptResult
{
return JavaScript("...JavaScript...");
}
public ActionResult GetJson() // or JsonResult
{
var obj = new { prop1 = 1, prop2 = "data" };
return Json(obj, JsonRequestBehavior.AllowGet);
}
public ActionResult RedirectTo() // or RedirectResult
{
return RedirectPermanent("http://www.site.com");
//return RedirectToAction("Home", "Index");
}
public ActionResult ShowView() // or ViewResult
{
return View();
}
}
}
چند نکته در این مثال وجود دارد:
1) مثلا متد GetJavaScript را درنظر بگیرید. در این متد خاص، چه بنویسید public ActionResult GetJavaScript یا بنویسید public JavaScriptResult GetJavaScript تفاوتی نمیکند. در سایر موارد هم به همین ترتیب است. علت را در تصویر سلسله مراتبی ActionResultها میتوان جستجو کرد. تمام این کلاسها نوعی ActionResult هستند و از یک کلاس پایه به ارث رسیدهاند.
2) مثلا ContentResult شبیه به همان Response.Write سابق ASP.NET عمل میکند. علت وجودی آن هم عدم وابستگی مستقیم به شیء Response و سادهتر سازی نوشتن آزمونهای واحد برای این نوع اکشن متدها است.
3) منهای متد آخری که نمایش داده شده (ShowView)، هیچکدام از متدهای دیگر نیازی به View متناظر ندارند. یعنی نیازی نیست تا روی متد کلیک راست کرده و Add view را انتخاب کنیم. چون در همین متد کنترلر، کار Response به پایان میرسد و مرحله بعدی ندارد. مثلا در حالت return File، یک فایل به درون مرورگر کاربر Flush خواهد شد و تمام.
4) متد Welcome و متد Index در اینجا به یک صورت تفسیر میشوند. به این معنا که اگر خروجی متد تعریف شده در یک کنترلر از نوع ActionResult نباشد، به صورت پیش فرض درون یک ContentResult محصور خواهد شد.
5) اگر خروجی متدی در اینجا از نوع void باشد، با ActionResult ایی به نام EmptyResult یکسان خواهد بود. بنابراین با متدهای SendMail و SendMailCompleted به یک نحو رفتار میگردد.
6) return Json یاد شده که خروجیاش از نوع JsonResultاست در پیاده سازیهای Ajax ایی کاربرد دارد.
7) جهت بازگرداندن حالت وضعیت 403 یا غیرمجاز میتوان از return new HttpUnauthorizedResult استفاده کرد.
8) یا جهت اعلام مشکلی در سمت سرور به کمک return new HttpStatusCodeResultکد ویژهای را میتوان به کاربر نمایش داد.
9) به کمک return RedirectToAction میتوان به یک کنترلر و متدی خاص در آن، کاربر را هدایت کرد.
و خلاصه اینکه تمام کارهایی را که پیشتر در ASP.NET Web forms ، مستقیما به کمک شیء Response انجام میدادید (Response.Write، Response.End، Response.Redirect و غیره)، اینبار به کمک یکی از ActionResultهای یاد شده انجام دهید تا بتوان بدون نیاز به راه اندازی یک وب سرور، برای متدهای کنترلرها آزمون واحد نوشت. برای مثال:
[TestMethod]
public void TestMethod1()
{
// Arrange
var controller = new ActionResultsController();
// Act
var result = controller.Index() as ContentResult;
// Assert
Assert.NotNull(result);
Assert.AreEqual( "Hello, World", result.Content);
}
renderInput(name, label, type = "text", correspond) { const { data, errors } = this.state; return ( <Input name={name} type={type} label={label} value={data[name]} onChange={this.handleChange} error={errors[name]} correspond={correspond} /> ); }
<form onSubmit={this.handleSubmit}> {this.renderInput("username", "Username")} {this.renderInput("password", "Password", "password")} {this.renderInput( "confirmPassword", "Confirm Password", "password", "password" )} {this.renderInput("name", "Name")} {this.renderButton("Register")} </form>
state = { data: { username: "", password: "", name: "", confirmPassword: "" }, errors: {}, }; schema = { username: Joi.string() .required() .email({ minDomainSegments: 2, tlds: { allow: ["com", "net", "info"] } }) .label("Username"), password: Joi.string().required().min(5).label("Password"), name: Joi.string().required().label("Name"), confirmPassword: Joi.any().valid(Joi.ref("password")).required().messages({ "any.only": "با رمز عبور مطابقت ندارد", }), };
validateProperty = ({ name, value, attributes }) => { const userInputObject = { [name]: value }; const schemaMap = { [name]: this.schema[name] }; if (attributes.correspond) { const correspondFieldName = attributes.correspond.value; userInputObject[correspondFieldName] = this.state.data[ correspondFieldName ]; schemaMap[correspondFieldName] = this.schema[correspondFieldName]; } const propertySchema = Joi.object(schemaMap); const { error } = propertySchema.validate(userInputObject, { abortEarly: true, }); return error ? error.details[0].message : null; };
[StringLength(10, ErrorMessage = "حداکثر 10 حرف")] public string Name { set; get; }
$(function () { $("input[data-val-length-max]").each(function (i, e) { var input = $(e); var maxlength = input.attr("data-val-length-max"); input.attr("maxlength", maxlength); }); });
<input class="text-box single-line" data-val="true" data-val-length="حداکثر 10 حرف" data-val-length-max="10" data-val-required="(*)" id="Name" name="Name" type="text" value="" />