We would love to hear about your experience with building client applications in .NET. Your feedback will greatly help us to improve the .NET tooling and ensure our roadmap focuses on your needs. Participate in shaping the future of the .NET client development by taking this short survey (5 minutes to complete).
بازخوردهای دوره
تزریق خودکار وابستگیها در SignalR
ممنون، اتفاقاً Resharper هم این پیغام رو میداد:
Class 'StructureMap.ObjectFactory' is obsolete: ObjectFactory will be removed in a future 4.0 release of StructureMap. Favor the usage of the Container class for future work
نهایتاً به این صورت مشکلم حل شد:
SmObjectFactory.Container.Configure(x => { x.For<IDependencyResolver>().Singleton().Add<StructureMapDependencyResolver>(); }); GlobalHost.DependencyResolver = SmObjectFactory.Container.GetInstance<IDependencyResolver>();
با سلام؛ قبل از هر چیز ممنون از آموزش خوبتون. یک سوال در رابطه با قسمت اول این آموزش داشتم. من دقیقا با آموزش شما پیش رفتم و در قسمت هفتم آموزشتون در اجرای پروژه دچار مشکل شدم و در مرورگرم با خطای زیر مواجه شدم:
HTTP Error 403.14 - Forbidden The Web server is configured to not list the contents of this directory. Most likely causes: A default document is not configured for the requested URL, and directory browsing is not enabled on the server. Things you can try: If you do not want to enable directory browsing, ensure that a default document is configured and that the file exists. Enable directory browsing using IIS Manager. Open IIS Manager. In the Features view, double-click Directory Browsing. On the Directory Browsing page, in the Actions pane, click Enable. Verify that the configuration/system.webServer/directoryBrowse@enabled attribute is set to true in the site or application configuration file. Detailed Error Information: Module DirectoryListingModule Notification ExecuteRequestHandler Handler StaticFile Error Code 0x00000000 Requested URL http://localhost:80/3724/ Physical Path C:\inetpub\wwwroot\3724\ Logon Method Anonymous Logon User Anonymous
بوت استرپ، به همراه کلاسهایی است، برای نمایش زیباتر فرمها، که شامل کلاسهای اعتبارسنجی و حتی کنترل نحوهی چیدمان و اندازهی آنها نیز میشود.
ایجاد فرمهای مقدماتی، با بوت استرپ 4
بوت استرپ به همراه کلاسهایی مانند form-group و form-control است که از آنها میتوان برای ایجاد یک فرم مقدماتی استفاده کرد. در ابتدا مثال غیر تزئین شدهی زیر را در نظر بگیرید:
که چنین خروجی ابتدایی را نیز به همراه دارد:
در ادامه شروع میکنیم به تزئین کردن این فرم، با کلاسهای بوت استرپ 4:
- ابتدا به fieldsetهای تعریف شده، کلاس form-goup را انتساب میدهیم. این مورد سبب میشود تا اندکی فاصله بین آنها ایجاد شود.
- سپس به تمام divهایی که المانها را در بر گرفتهاند نیز کلاس form-group را اعمال میکنیم.
با اینکار فاصلهی مناسبی بین المانهای تعریف شدهی در صفحه ایجاد میشود:
- در ادامه به تمام المانهای input، select و textarea (منهای checkboxها) کلاس form-control را نسبت میدهیم:
با اینکار، ظاهر این المانها بسیار شکیلتر شدهاست و همچنین این فرم واکنشگرا نیز میباشد.
- پس از آن، تمام المانهای label را انتخاب کرده و کلاس form-control-label را به آنها انتساب میدهیم. هرچند با اینکار ظاهر فعلی فرم تغییری نمیکند، اما چنین تعریفی برای فعالسازی کلاسهای اعتبارسنجی ضروری است.
اگر به هر دلیلی نخواستید این برچسبها را نمایش دهید، میتوانید از کلاس sr-only استفاده کنید که صرفا سبب نمایش آنها به screen readers میشود.
- ذیل فیلد ورود ایمیل، متنی وجود دارد. این متن را با کلاسهای form-text text-muted مزین میکنیم:
- به دکمهی پایین صفحه نیز کلاسهای btn btn-primary را اضافه میکنیم که در مطلب «بررسی شیوهنامههای المانهای پر کاربرد بوت استرپ 4» بیشتر به آنها پرداختیم.
مزین سازی checkboxها و radio-buttonها در بوت استرپ 4
روش مزین سازی checkboxها و radio-buttonها در بوت استرپ، با سایر المانها اندکی متفاوت است:
در اینجا تفاوتی نمیکند که بخواهیم با checkboxها کار کنیم و یا radio-buttonها، هر دوی این المانها ابتدا داخل یک div با کلاس form-check قرار میگیرند. سپس برچسب آنها دارای کلاس form-check-label میشود و در آخر به خود این المانهای input، کلاس form-check-input اضافه خواهد شد.
یک نکته: اگر نیاز است این المانها کنار یکدیگر نمایش داده شوند، میتوان بر روی div آنها از کلاسهای form-check form-check-inline استفاده کرد. در این حالت اگر میخواهید برچسب برای مثال radio-button تعریف شده، در یک سطر و گزینهها آن در سطری دیگر باشند، از کلاس d-block بر روی این برچسب استفاده کنید:
با این خروجی:
کلاسهای کنترل اندازه و اعتبارسنجی المانهای فرمهای بوت استرپ 4
- با استفاده از کلاس form-control-sm میتوان اندازهی فیلدهای input را با ارتفاع کوچکتری نمایش داد و یا توسط کلاس form-control-lg میتوان آنها را بزرگتر کرد.
- کلاس form-inline سبب میشود تا یک form-group به صورت inline نمایش داده شود. یعنی برچسب و کنترلهای درون آن، در طی یک سطر نمایش داده خواهند شد. در این حالت، نیاز به کلاسهای Margin مانند mx-sm-2 خواهد بود تا فاصلهی بین کنترلها را بتوان کنترل کرد.
- برای نمایش نتایج اعتبارسنجی کنترلها:
- اگر کل فرم اعتبارسنجی شدهاست، کلاس was-validated را به المان form اضافه کنید.
- اگر اعتبارسنجی کنترلی با موفقیت روبرو شود، کلاس is-valid و اگر خیر کلاس is-invalid را به آن نسبت دهید.
- اگر میخواهید پیام خاصی را پس از موفقیت اعتبارسنجی نمایش دهید، آنرا درون یک div با کلاس valid-feedback قرار دهید و یا برعکس از کلاس invalid-feedback استفاده کنید.
- برای تغییر رنگ برچسب المانها نیز از کلاسهای text-color همانند قبل استفاده کنید؛ مانند text-success.
یک مثال:
با این خروجی:
تغییر نحوهی چیدمان عناصر فرمها در بوت استرپ 4
فرم زیر را در نظر بگیرید:
قصد داریم با استفاده از کلاسهای ویژهی بوت استرپ 4، آنرا دو ستونی کنیم؛ به طوریکه برچسبها در یک ستون و فیلدهای ورودی، در ستونی دیگر نمایش داده شوند. همچنین این فرم واکنشگرا نیز باشد؛ به این معنا که این دو ستونی شدن، فقط در اندازههای پس از md رخ دهد:
با این خروجی در اندازهی پس از md:
توضیحات:
برای ستونی کردن فرمها، ابتدا کلاس row، به form-group قرار گرفتهی داخل container اصلی اضافه میشود:
سپس توسط کلاس col-md-2 تعریف شدهی بر روی برچسب، سبب خواهیم شد تا در اندازهی صفحهی بیش از md، این برچسب در یک ستون با عرض دو واحد قرار گیرد. در یک چنین حالتی، ذکر col-form-label نیز ضروری است. همچنین اگر مایل باشیم تا این برچسب، در سمت راست این ستون قرار گیرد، میتوان از کلاس واکنشگرای text-md-right استفاده کرد.
پس از آن نوبت به تعریف ستون فیلد تعریف شدهاست که با ایجاد یک div و تعریف تعداد واحدی را که به خود اختصاص میدهد (col-md-10)، انجام میشود.
در اینجا برچسبهای فیلدهای city و zip با کلاس sr-only مشخص شدهاند. به همین جهت فقط به screen readers نمایش داده میشوند.
در یک چنین حالتی، برای اینکه این فیلدها در ستون دوم ظاهر شوند، از کلاس offset-md-2 استفاده شدهاست. از این offset برای تراز کردن دکمه، با ستون دوم نیز استفاده کردهایم:
ایجاد گروهی از ورودیها در بوت استرپ 4
برای افزودن آیکنهایی به فیلدهای ورودی، از روش ایجاد گروهی از ورودیها در بوت استرپ 4 استفاده میشود:
در مثال فوق، روش تعریف یک input-group را مشاهده میکنید. داخل آن یک input-group-prepend و سپس input-group-text تعریف میشود که میتواند شامل یک متن و یا آیکن باشد. اگر نیاز به تعریف دکمهای وجود داشت، از این کلاس استفاده نکنید. با این خروجی:
در بوت استرپ 4، کلاسهای input-group-addon و input-group-btn بوت استرپ 3 حذف و با کلاسهای input-group-prepend و input-group-append جایگزین شدهاند. از prepend برای قرار دادن آیکنی پیش از فیلد ورودی و از append همانند مثال فوق، برای قرار دادن آیکنی اختیاری پس از فیلد ورودی استفاده میشود.
نمونهی متداول دیگر آن، نحوهی تعریف ویژهی فیلد جستجوی سایت، در منوی راهبری آن است:
با این خروجی که در آن دکمه، توسط کلاس input-group-append، با فیلد ورودی کنار آن، یکپارچه به نظر میرسد:
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: Bootstrap4_10.zip
ایجاد فرمهای مقدماتی، با بوت استرپ 4
بوت استرپ به همراه کلاسهایی مانند form-group و form-control است که از آنها میتوان برای ایجاد یک فرم مقدماتی استفاده کرد. در ابتدا مثال غیر تزئین شدهی زیر را در نظر بگیرید:
<body> <div class="container"> <h2>Medical Questionnaire</h2> <form> <fieldset> <legend>Owner Info</legend> <div> <label for="ownername">Owner name</label> <input type="text" id="ownername" placeholder="Your Name"> </div> <div> <label for="owneremail">Email address</label> <input type="email" id="owneremail" aria-describedby="emailHelp" placeholder="Enter email"> <small id="emailHelp">We'll never share your email</small> </div> </fieldset> <fieldset> <legend>Pet Info</legend> <div> <label for="petname">Pet name</label> <input type="text" id="petname" placeholder="Your Pet's name"> </div> <div> <label for="pettype">Pet type</label> <select id="pettype"> <option>Choose</option> <option value="cat">Dog</option> <option value="cat">Cat</option> <option value="bird">Other</option> </select> </div> <div> <label for="reasonforvisit">Reason for today's visit</label> <textarea id="reasonforvisit" rows="3"></textarea> </div> <div> <label>Has your pet been spayed or neutered?</label> <label><input type="radio" name="spayneut" value="yes" checked> Yes</label> <label><input type="radio" name="spayneut" value="no"> No</label> </div> <div> <label>Has the pet had any of the following in the past 30 days</label> <label><input type="checkbox"> Abdominal pain</label> <label><input type="checkbox"> Lack of appetite</label> <label><input type="checkbox"> Weakness</label> </div> </fieldset> <button type="submit">Submit</button> </form> </div><!-- content container --> </body>
در ادامه شروع میکنیم به تزئین کردن این فرم، با کلاسهای بوت استرپ 4:
- ابتدا به fieldsetهای تعریف شده، کلاس form-goup را انتساب میدهیم. این مورد سبب میشود تا اندکی فاصله بین آنها ایجاد شود.
- سپس به تمام divهایی که المانها را در بر گرفتهاند نیز کلاس form-group را اعمال میکنیم.
با اینکار فاصلهی مناسبی بین المانهای تعریف شدهی در صفحه ایجاد میشود:
- در ادامه به تمام المانهای input، select و textarea (منهای checkboxها) کلاس form-control را نسبت میدهیم:
با اینکار، ظاهر این المانها بسیار شکیلتر شدهاست و همچنین این فرم واکنشگرا نیز میباشد.
- پس از آن، تمام المانهای label را انتخاب کرده و کلاس form-control-label را به آنها انتساب میدهیم. هرچند با اینکار ظاهر فعلی فرم تغییری نمیکند، اما چنین تعریفی برای فعالسازی کلاسهای اعتبارسنجی ضروری است.
اگر به هر دلیلی نخواستید این برچسبها را نمایش دهید، میتوانید از کلاس sr-only استفاده کنید که صرفا سبب نمایش آنها به screen readers میشود.
- ذیل فیلد ورود ایمیل، متنی وجود دارد. این متن را با کلاسهای form-text text-muted مزین میکنیم:
- به دکمهی پایین صفحه نیز کلاسهای btn btn-primary را اضافه میکنیم که در مطلب «بررسی شیوهنامههای المانهای پر کاربرد بوت استرپ 4» بیشتر به آنها پرداختیم.
مزین سازی checkboxها و radio-buttonها در بوت استرپ 4
روش مزین سازی checkboxها و radio-buttonها در بوت استرپ، با سایر المانها اندکی متفاوت است:
<div class="form-check"> <label class="form-check-label"> <input class="form-check-input" type="checkbox"> Lack of appetite </label> </div>
یک نکته: اگر نیاز است این المانها کنار یکدیگر نمایش داده شوند، میتوان بر روی div آنها از کلاسهای form-check form-check-inline استفاده کرد. در این حالت اگر میخواهید برچسب برای مثال radio-button تعریف شده، در یک سطر و گزینهها آن در سطری دیگر باشند، از کلاس d-block بر روی این برچسب استفاده کنید:
<div class="form-group"> <label class="d-block">Has your pet been spayed or neutered?</label> <div class="form-check form-check-inline"> <label class="form-check-label"> <input class="form-check-input" type="radio" name="spayneut" value="yes" checked> Yes </label> </div> <div class="form-check form-check-inline"> <label class="form-check-label"> <input class="form-check-input" type="radio" name="spayneut" value="no"> No </label> </div> </div>
کلاسهای کنترل اندازه و اعتبارسنجی المانهای فرمهای بوت استرپ 4
- با استفاده از کلاس form-control-sm میتوان اندازهی فیلدهای input را با ارتفاع کوچکتری نمایش داد و یا توسط کلاس form-control-lg میتوان آنها را بزرگتر کرد.
- کلاس form-inline سبب میشود تا یک form-group به صورت inline نمایش داده شود. یعنی برچسب و کنترلهای درون آن، در طی یک سطر نمایش داده خواهند شد. در این حالت، نیاز به کلاسهای Margin مانند mx-sm-2 خواهد بود تا فاصلهی بین کنترلها را بتوان کنترل کرد.
- برای نمایش نتایج اعتبارسنجی کنترلها:
- اگر کل فرم اعتبارسنجی شدهاست، کلاس was-validated را به المان form اضافه کنید.
- اگر اعتبارسنجی کنترلی با موفقیت روبرو شود، کلاس is-valid و اگر خیر کلاس is-invalid را به آن نسبت دهید.
- اگر میخواهید پیام خاصی را پس از موفقیت اعتبارسنجی نمایش دهید، آنرا درون یک div با کلاس valid-feedback قرار دهید و یا برعکس از کلاس invalid-feedback استفاده کنید.
- برای تغییر رنگ برچسب المانها نیز از کلاسهای text-color همانند قبل استفاده کنید؛ مانند text-success.
یک مثال:
<div class="form-group"> <label for="owneremail" class="text-success">Email address</label> <input class="form-control is-valid" type="email" id="owneremail" aria-describedby="emailHelp" placeholder="Enter email"> <small class="form-text text-muted" id="emailHelp">We'll never share your email</small> <div class="valid-feedback"> Looks good! </div> </div>
تغییر نحوهی چیدمان عناصر فرمها در بوت استرپ 4
فرم زیر را در نظر بگیرید:
قصد داریم با استفاده از کلاسهای ویژهی بوت استرپ 4، آنرا دو ستونی کنیم؛ به طوریکه برچسبها در یک ستون و فیلدهای ورودی، در ستونی دیگر نمایش داده شوند. همچنین این فرم واکنشگرا نیز باشد؛ به این معنا که این دو ستونی شدن، فقط در اندازههای پس از md رخ دهد:
<body> <div class="container"> <h2>Medical Questionnaire</h2> <form> <fieldset class="form-group"> <legend>Owner Info</legend> <div class="form-group row"> <label class="form-control-label col-md-2 col-form-label text-md-right" for="ownername">Owner</label> <div class="col-md-10"> <input class="form-control" type="text" id="ownername" placeholder="Your Name"> </div> </div> <div class="form-group row"> <label class="form-control-label col-md-2 col-form-label text-md-right" for="owneremail">Address</label> <div class="col-md-10"> <input class="form-control" type="text" id="owneremail" placeholder="Address"> </div> </div> <div class="form-group row"> <div class="form-group col-6 offset-md-2"> <label class="form-control-label sr-only" for="ownercity">City</label> <input class="form-control" type="text" id="ownercity" placeholder="City"> </div> <div class="form-group col-md-4 col-6"> <label class="form-control-label sr-only" for="ownerzip">Zip</label> <input class="form-control" type="text" id="ownerzip" placeholder="Zip"> </div> </div> <div class="form-group row"> <div class="offset-md-2 col-md-10"> <button class="btn btn-primary" type="submit">Submit</button> </div> </div> </fieldset> </form> </div> </body>
توضیحات:
برای ستونی کردن فرمها، ابتدا کلاس row، به form-group قرار گرفتهی داخل container اصلی اضافه میشود:
<div class="form-group row"> <label class="form-control-label col-md-2 col-form-label text-md-right" for="ownername">Owner</label> <div class="col-md-10"> <input class="form-control" type="text" id="ownername" placeholder="Your Name"> </div> </div>
پس از آن نوبت به تعریف ستون فیلد تعریف شدهاست که با ایجاد یک div و تعریف تعداد واحدی را که به خود اختصاص میدهد (col-md-10)، انجام میشود.
در اینجا برچسبهای فیلدهای city و zip با کلاس sr-only مشخص شدهاند. به همین جهت فقط به screen readers نمایش داده میشوند.
<div class="form-group row"> <div class="form-group col-6 offset-md-2"> <label class="form-control-label sr-only" for="ownercity">City</label> <input class="form-control" type="text" id="ownercity"placeholder="City"> </div>
<div class="form-group row"> <div class="offset-md-2 col-md-10"> <button class="btn btn-primary" type="submit">Submit</button> </div> </div>
ایجاد گروهی از ورودیها در بوت استرپ 4
برای افزودن آیکنهایی به فیلدهای ورودی، از روش ایجاد گروهی از ورودیها در بوت استرپ 4 استفاده میشود:
<div class="form-group"> <label class="form-control-label" for="donationamt"> Donation Amount </label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text">$</span> </div> <input type="text" class="form-control" id="donationamt" placeholder="Amount"> <div class="input-group-append"> <span class="input-group-text">.00</span> </div> </div> </div>
در بوت استرپ 4، کلاسهای input-group-addon و input-group-btn بوت استرپ 3 حذف و با کلاسهای input-group-prepend و input-group-append جایگزین شدهاند. از prepend برای قرار دادن آیکنی پیش از فیلد ورودی و از append همانند مثال فوق، برای قرار دادن آیکنی اختیاری پس از فیلد ورودی استفاده میشود.
نمونهی متداول دیگر آن، نحوهی تعریف ویژهی فیلد جستجوی سایت، در منوی راهبری آن است:
<nav class="navbar bg-dark navbar-dark navbar-expand-sm"> <div class="container"> <div class="navbar-brand d-none d-sm-inline-block"> Wisdom Pet Medicine </div> <div class="navbar-nav mr-auto"> <a class="nav-item nav-link active" href="#">Home</a> <a class="nav-item nav-link" href="#">Mission</a> <a class="nav-item nav-link" href="#">Services</a> <a class="nav-item nav-link" href="#">Staff</a> <a class="nav-item nav-link" href="#">Testimonials</a> </div> <form class="form-inline d-none d-md-inline-block"> <div class="input-group"> <label for="search" class="form-control-label sr-only"></label> <input type="text" id="search" class="form-control" placeholder="Search ..."> <div class="input-group-append"> <button class="btn btn-outline-light" type="submit">Go</button> </div> </div> </form> </div> </nav>
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: Bootstrap4_10.zip
اشتراکها
سایت rssheap سورس باز شد
اشتراکها
پروژه مدیریت محتوای squidex
اجرای پرس و جو روی دادههای به هم مرتبط (Related Data)
اگر به موجودیت Customer دقت کنید دارای خصوصیتی با نام Orders میباشد که از نوع <IList<Order هست یعنی دارای لیستی از Order هاست بنابراین یک رابطه یک به چند بین Customer و Order وجود دارد. در ادامه به بررسی نحوه پرس و جو کردن روی دادههای به هم مرتبط خواهیم پرداخت.
ابتدا به کد زیر دقت کنید:
private static void Query10() { using (var context = new StoreDbContext()) { var customers = context.Customers; foreach (var customer in customers) { Console.WriteLine("Customer Name: {0}, Customer Family: {1}", customer.Name, customer.Family); foreach (var order in customer.Orders) { Console.WriteLine("\t Order Date: {0}", order.Date); } } } }
اگر کد بالا را اجرا کنید هنگام اجرای حلقه داخلی با خطای زیر مواجه خواهید شد:
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first
همانطور که قبلا اشاره شد EF با اجرای یک پرس و جو به یکباره دادهها را باز نمیگرداند بنابراین در حلقه اصلی که روی Customers زده شده است با هر پیمایش یک customer از Database فراخوانی میشود درنتیجه DataReader تا پایان یافتن حلقه باز میماند. حال آنکه حلقه داخلی نیز برای خواندن Orderها نیاز به اجرای یک پرس و جو دارد بنابراین DataReader ای جدید باز میشود و در نتیجه با خطایی مبنی بر اینکه DataReader دیگری باز است، مواجه میشویم. برای حل این مشکل میبایست جهت باز بودن چند DataReader همزمان، کد زیر را به ConnectionString اضافه کنیم
MultipleActiveResultSets = true
که با این تغییر کد بالا به درستی اجرا میشود.
در بارگذاری دادههای به هم مرتبط EF سه روش را در اختیار ما قرار میدهد:
- Lazy Loading
- Eager Loading
- Explicit Loading
که در ادامه به بررسی آنها خواهیم پرداخت.
Lazy Loading: در این روش دادههای مرتبط در صورت نیاز با یک پرس وجوی جدید که به صورت اتوماتیک توسط EF ساخته میشود، گرفته خواهند شد. کد زیر را در نظر بگیرید:
private static void Query11() { using (var context = new StoreDbContext()) { var customer = context.Customers.First(); Console.WriteLine("Customer Name: {0}, Customer Family: {1}", customer.Name, customer.Family); foreach (var order in customer.Orders) { Console.WriteLine("\t Order Date: {0}", order.Date); } } }
اگر این کد را اجرا کنید خواهید دید که یک بار پرس و جویی مبنی بر دریافت اولین Customer روی database زده خواهد شد و پس از چاپ آن در ادامه برای نمایش Orderهای این Customer پرس و جوی دیگری زده خواهد شد. در حقیقت پرس و جوی اول فقط Customer را بازگشت میدهد و در ادامه، اول حلقه، جایی که نیاز به Orderهای این Customer میشود EF پرس و جو دوم را بصورت هوشمندانه و اتوماتیک اجرا میکند. به این روش بارگذاری دادههای مرتبط Lazy Loading گفته میشود که به صورت پیش فرض در EF فعال است.
برای غیرفعال کردن این روش، کد زیر را اجرا کنید:
context.Configuration.LazyLoadingEnabled = false;
EF از dynamic proxy برای Lazy Loading استفاده میکند. به این صورت که در زمان اجرا کلاسی جدید که از کلاس POCO مان ارث برده است، ساخته میشود. این کلاس proxy میباشد و در آن navigation propertyها بازنویسی شدهاند و کمی منطق برای خواندن دادههای وابسته اضافه شده است.
برای ایجاد dynamic proxy شروط زیر لازم است:
•کلاس POCO میبایست public بوده و sealed نباشد.
•Navigation propertyها میبایست virtual باشد.
در صورتیکه هرکدام از این دو شرط برقرار نباشند کلاس proxy ساخته نمیشود و Lazy Loading حتی در صورت فعال بودن انجام نخواهد شد. مثلا اگر پراپرتی Orders در کلاس Customer مان virtual نباشد. در شروع حلقه کد بالا پرس و جوی جدید اجرا نشده و در نتیجه مقدار این پراپرتی null خواهد ماند.
Lazy Loading به ما در عدم بارگذاری دادههای مرتبط که به آنها نیازی نداریم، کمک میکند. اما در صورتیکه به دادههای مرتبط نیاز داشته باشیم "مسئله Select n+1" پیش خواهد آمد که باید این مسئله را مد نظر داشته باشیم.
مسئله Select n+1: کد زیر را در نظر بگیرد
private static void Query12() { using (var context = new StoreDbContext()) { var customers = context.Customers; foreach (var customer in customers) { Console.WriteLine("Customer Name: {0}, Customer Family: {1}", customer.Name, customer.Family); foreach (var order in customer.Orders) { Console.WriteLine("\t Order Date: {0}", order.Date); } } } }
هنگام اجرای کد بالا یک پرس و جو برای خواندن Customerها زده خواهد شد و به ازای هر Customer یک پرس و جوی دیگر برای گرفتن Orderها زده خواهد شد. در این صورت پرس و جوی اول ما اگر n مشتری را برگرداند، n پرس و جو نیز برای گرفتن Orderها زده خواهد شد که روهم n+1 دستور Select میشود. این تعداد پرس و جو موجب عدم کارایی میشود و برای رفع این مسئله نیاز به امکانی جهت بارگذاری هم زمان دادههای مرتبط مورد نیاز خواهد بود. این امکان با استفاده از Eager Loading برآورده میشود.
روش Eager Loading: هنگامی که در یک پرس و جو نیاز به بارگذاری همزمان دادههای مرتبط نیز باشد، از این روش استفاده میشود. برای این منظور از متد Include استفاده میشود که ورودی آن navigation property مربوطه میباشد. این پارامتر ورودی را همانطور که در کد زیر مشاهده میکنید، میتوان به صورت string و یا Lambda Expression مشخص کرد.
دقت شود که برای حالت Lambda Expression بایدSystem.Data.Entity به usingها اضافه شود.
private static void Query13() { using (var context = new StoreDbContext()) { var customers = context.Customers.Include(c => c.Orders); //var customers = context.Customers.Include("Orders"); foreach (var customer in customers) { Console.WriteLine("Customer Name: {0}, Customer Family: {1}", customer.Name, customer.Family); foreach (var order in customer.Orders) { Console.WriteLine("\t Order Date: {0}", order.Date); } } }
در این صورت یک پرس و جو به صورت join اجرا خواهد شد.
اگر دادههای مرتبط در چند سطح باشند، میتوان با دادن مسیر دادههای مرتبط اقدام به بارگذاری آنها کرد. به مثالهای زیر توجه کنید:
context.OrderDetails.Include(o => o.Order.Customer)
context.Orders.Include(o => o.OrderDetail.Select(od => od.Product))
context.Orders.Include(o => o.Customer).Include(o => o.OrderDetail)
روش Explicit Loading: این روش مانند Lazy Loading میباشد که میتوان دادههای مرتبط را جداگانه فراخوانی کرد اما نه به صورت اتوماتیک توسط EF بلکه به صورت صریح توسط خودمان انجام میشود. این روش حتی اگر navigation propertyهای ما virtual نباشند نیز قابل انجام است. برای انجام این روش از متد DbContext.Entry استفاده میشود.
private static void Query14() { using (var context = new StoreDbContext()) { var customer = context.Customers.First(c => c.Family == "Jamshidi"); context.Entry(customer).Collection(c => c.Orders).Load(); foreach (var order in customer.Orders) { Console.WriteLine(order.Date); } } }
private static void Query15() { using (var context = new StoreDbContext()) { var order = context.Orders.First(); context.Entry(order).Reference(o => o.Customer).Load(); Console.WriteLine(order.Customer.FullName); } }
در پرس و جوی بالا Customer یک Order صراحتا و به صورت جداگانه از database گرفته شده است.
با توجه به دو مثال بالا مشخص است که اگر داده مرتبط ما به صورت لیست است از Collection و درغیر این صورت از Reference استفاده میشود.
در صورتیکه بخواهیم ببینیم آیا دادهی مرتبط مان بازگذاری شده است یا خیر، از خصوصیت IsLoaded به صورت زیر استفاده میکنیم:
if (context.Entry(order).Reference(o => o.Customer).IsLoaded) context.Entry(order).Reference(o => o.Customer).Load();
private static void Query16() { using (var context = new StoreDbContext()) { var customer = context.Customers.First(c => c.Family == "Jamshidi"); IQueryable<Order> query = context.Entry(customer).Collection(c => c.Orders).Query(); var order = query.First(); } }
اشتراکها
کتابخانه angular-checkboxes
If you are used to manipulate HTML forms, you probably know that each checkbox is a separate variable (or maybe an ngModel with AngularJS). Demo
Sometimes, it could be usefull to manipulate all these checkboxes as a unique array.
angular.checkboxes
module lets you turn your list of checkboxes into a unique destination array, providing :
- two-way binding: manipulate the destination array will check/uncheck the checkboxes AND check/uncheck the checkboxes will modify the destination array.
- no isolated scope for each checkbox: the directive does not create new child scope.
- a mtCheckboxController: internal controller can be injected to other directives.
اشتراکها
2.Visual Studio 2017 15.6 منتشر شد
These are the customer-reported issues addressed in this release:
- "Specified argument out of the range of valid values, parameter name: count"
git
tags. - Cannot open git commit details.
- VS2017 Installer crashes on Modify when SyncFusion WPF Templates are installed.
- Test Explorer loses position when tests are run.
- Test explorer test hierarchy constantly jumps to top.
- XAML editor always crashes when a change is made to the XAML file.
- Test Explorer keeps scrolling to the top when a new test starts.
- Viewing Git History shows: specified argument was out of range of values.
- Alt+Up/Down does not reposition file in .NET Framework projects.
- VS 15.6 deadlocks on solution load for .NET Core SDK project when a 'None Include' is added to file list.
- 15.6 preview 6 discovers test adapter, but fails to run tests.
- Test Explorer keeps scrolling to the top when a new test starts.
- Microsoft Security Advisories for .NET Core updates.
Microsoft Security Advisories for .NET Core
CVE-2018-0875: Microsoft is aware of a security vulnerability in the public versions of .NET Core where a malicious file or web request could cause a denial of service (DoS) attack.
- System administrators are advised to update their .NET Core runtimes to versions 1.0.10, 1.1.7 or 2.0.6. Developers are advised to update their .NET Core SDK to versions 1.1.8 or 2.1.101.
حجم تقریبی بروزرسانی از نسخه 15.6.1 به 15.6.2 برابر 1.2GB میباشد