In this video Anders Hejlsberg spends some time discussing TypeScript. He starts with the reasons behind creating TypeScript (the so called elevator speech) and then moves on to some of the features coming in the next release. He mentions a number of features but spends the time discussing the null (and corresponding undefined) types and how TypeScript 2 makes handling them much easier.
var Id=1; var books = (from b in db.Books where b.bookId == Id select new { //... }).ToList();
حالا اگر شرط من بجای داشتن فقط یک Id لیستی از Id باشد چطور عمل کنم ؟
var booksId= new list<int>(){ 1 , 2 , 6 , 7}; var books = (from b in db.Books where b.bookId == ??? select new { //... }).ToList();
چطور میتونم لیستی رو که دارم بجای مقایسه با یک Id ، با یک لیستی از Idها مقایسه کنم و نتیجه را بگیرم ؟
var citiesContainPerson = context.Cities.Where(city => city.People.Any(person => person.Name == "user-1")).ToList();
SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name] FROM [dbo].[Cities] AS [Extent1] WHERE EXISTS (SELECT 1 AS [C1] FROM [dbo].[People] AS [Extent2] WHERE ([Extent1].[Id] = [Extent2].[BornInCityId]) AND (N'user-1' = [Extent2].[Name]) )
var query = (from list in dbContext.Packages where list.Id == Int32.Parse(Request["Id"].ToString()) select list).FirstOrDefault();
Int32 ID = Int32.Parse(Request["Id"].ToString()); var query = (from list in dbContext.Packages where list.Id == ID select list).FirstOrDefault();
From today most of the Iranian developers who work on free/open-source projects get mail about suspending their accounts because of the U.S sanction over Iran , also they want a non-iranian passport to unlock accounts which means if your Iranian who works for a tech company remotely or using their service for developing free software are banned too!
also, some of Iranian couldn't clone projects from GitHub!
امکانات جدید در فایرفاکس کوانتم
Firefox Quantum is over twice as fast as Firefox from 6 months ago, built on a completely overhauled core engine with brand new technology stolen from our advanced research group, and graced with a beautiful new look designed to get out of the way and let you do what you do best: surf a ton of pages, open a zillion tabs, all guilt free because Firefox Quantum uses less memory than the competition
در طراحی مدل دامین، بیشتر مواقع از نوعهای اولیه مانند int , string,… استفاده میکنیم و به عبارتی میتوانیم بگوییم در استفاده از این نوع داده وسواس داریم. قطعه کد زیر را در نظر بگیرید:
public class UserFactory { public User CreateUser(string email) { return new User(email); } }
اگر به خاطر داشته باشید، در قسمتهای قبلی در مورد مفهومی به نام Honesty صحبت کردیم. به طور ساده باید بتوانیم از روی امضای تابع، کاری را که تابع انجام میدهد و خروجی آن را ببینیم. این تابع Honest نیست؛ شرایطی که string میتواند درست نباشد، خالی باشد، طول غیر مجاز داشته باشد و ... را نمیتوانیم از امضای تابع حدس بزنیم.
جواب خیلی سادهاست؛ شما نیاز دارید تا یک Type اختصاصی را ایجاد کنید. برای مثال بجای استفاده از نوع string برای یک ایمیل، میتوانید یک کلاس را به عنوان Email ایجاد کنید که مشخصهای به نام Value دارد. این کار به روشهای مختلفی قابل انجام است؛ اما پیشنهاد من استفاده از این روش هست:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace ValueOf { public class ValueOf<TValue, TThis> where TThis : ValueOf<TValue, TThis>, new() { private static readonly Func<TThis> Factory; /// <summary> /// WARNING - THIS FEATURE IS EXPERIMENTAL. I may change it to do /// validation in a different way. /// Right now, override this method, and throw any exceptions you need to. /// Access this.Value to check the value /// </summary> protected virtual void Validate() { } static ValueOf() { ConstructorInfo ctor = typeof(TThis) .GetTypeInfo() .DeclaredConstructors .First(); var argsExp = new Expression[0]; NewExpression newExp = Expression.New(ctor, argsExp); LambdaExpression lambda = Expression.Lambda(typeof(Func<TThis>), newExp); Factory = (Func<TThis>)lambda.Compile(); } public TValue Value { get; protected set; } public static TThis From(TValue item) { TThis x = Factory(); x.Value = item; x.Validate(); return x; } protected virtual bool Equals(ValueOf<TValue, TThis> other) { return EqualityComparer<TValue>.Default.Equals(Value, other.Value); } public override bool Equals(object obj) { if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; return obj.GetType() == GetType() && Equals((ValueOf<TValue, TThis>)obj); } public override int GetHashCode() { return EqualityComparer<TValue>.Default.GetHashCode(Value); } public static bool operator ==(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) { if (a is null && b is null) return true; if (a is null || b is null) return false; return a.Equals(b); } public static bool operator !=(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) { return !(a == b); } public override string ToString() { return Value.ToString(); } } }
public class EmailAddress : ValueOf<string, EmailAddress> { }
EmailAddress emailAddress = EmailAddress.From("foo@bar.com");
public class Address : ValueOf<(string firstLine, string secondLine, Postcode postcode), Address> { }
روش معرفی شدهی در این مقاله، صرفا جهت آشنایی بیشتر شما و داشتن کدی تمیزتر از طریق مفاهیم برنامه نویسی تابعی خواهد بود. در دنیای واقعی، احتمالا مسائلی را برای ذخیره سازی این آبجکتها و یا کار با کتابخانههایی مانند Entity Framework خواهید داشت که به سادگی قابل حل است.
در صورتیکه مشکلی در پیاده سازی داشتید، میتوانید مشکل خود را زیر همین مطلب و یا بر روی gist آن کامنت کنید.
AngularJS در سازمانها
ایندکسها در RavenDB
خوب؛ اکنون این سؤال مطرح میشود که RavenDB چگونه اطلاعاتی را در این اسناد بدون اسکیما جستجو میکند؟ اینجا است که مفهوم و کاربرد ایندکسها مطرح میشوند. ما در قسمت قبل که کوئری نویسی مقدماتی را بررسی کردیم، عملا ایندکس خاصی را به صورت دستی جهت انجام جستجوها ایجاد نکردیم؛ از این جهت که خود RavenDB به کمک امکانات dynamic indexing آن، پیشتر اینکار را انجام داده است. برای نمونه به سطر ارسال کوئری به سرور، که در قسمت قبل ارائه شد، دقت کنید. در اینجا ارسال کوئری به indexes/dynamic کاملا مشخص است:
Request # 2: GET - 3,818 ms - <system> - 200 - /indexes/dynamic/Questions?&query=Title%3ARaven*&pageSize=128
Dynamic Indexes یا ایندکسهای پویا
ایندکسهای پویا زمانی ایجاد خواهند شد که ایندکس صریحی توسط برنامه نویس تعریف نگردد. برای مثال زمانیکه یک کوئری LINQ را صادر میکنیم، RavenDB بر این اساس و برای مثال فیلدهای قسمت Where آن، ایندکس پویایی را تولید خواهد کرد. ایجاد ایندکسها در RavenDB از اصل عاقبت یک دست شدن پیروی میکنند. یعنی مدتی طول خواهد کشید تا کل اطلاعات بر اساس ایندکس جدیدی که در حال تهیه است، ایندکس شوند. بنابراین تولید ایندکسهای پویا در زمان اولین بار اجرای کوئری، کوئری اول را اندکی کند جلوه خواهند داد؛ اما کوئریهای بعدی که بر روی یک ایندکس آماده اجرا میشوند، بسیار سریع خواهند بود.
Static indexes یا ایندکسهای ایستا
ایندکسهای پویا به دلیل وقفه ابتدایی که برای تولید آنها وجود خواهد داشت، شاید آنچنان مطلوب به نظر نرسند. اینجا است که مفهوم ایندکسهای ایستا مطرح میشوند. در این حالت ما به RavenDB خواهیم گفت که چه چیزی را ایندکس کند. برای تولید ایندکسهای ایستا، از مفاهیم Map/Reduce که در پیشنیازهای دوره جاری در مورد آن بحث شد، استفاده میگردد. خوشبختانه تهیه Map/Reduceها در RavenDB پیچیده نبوده و کل عملیات آن توسط کوئریهای LINQ قابل پیاده سازی است.
تهیه ایندکسهای پویا نیز در تردهای پسزمینه انجام میشوند. از آنجائیکه RavenDB برای اعمال Read، بهینه سازی شده است، با ارسال یک کوئری به آن، این بانک اطلاعاتی، کلیه اطلاعات آماده را در اختیار شما قرار خواهد داد؛ صرفنظر از اینکه کار تهیه ایندکس تمام شده است یا خیر.
چگونه یک ایندکس ایستا را ایجاد کنیم؟
اگر به کنسول مدیریتی سیلورلایت RavenDB مراجعه کنیم، حاصل کوئریهای LINQ قسمت قبل را در برگهی ایندکسهای آن میتوان مشاهده کرد:
در اینجا بر روی دکمه Edit کلیک نمائید، تا با نحوه تهیه این ایندکس پویا آشنا شویم:
این ایندکس، یک نام داشته به همراه قسمت Map از پروسه Map/Reduce که توسط یک کوئری LINQ تهیه شده است. کاری که در اینجا انجام شده، ایندکس کردن کلیه سؤالات، بر اساس خاصیت عنوان آنها است.
اکنون اگر بخواهیم همین کار را با کدنویسی انجام دهیم، به صورت زیر میتوان عمل کرد:
using System; using System.Linq; using Raven.Client.Document; using RavenDBSample01.Models; using Raven.Client; using Raven.Client.Linq; using Raven.Client.Indexes; namespace RavenDBSample01 { class Program { static void Main(string[] args) { using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { store.DatabaseCommands.PutIndex( name: "Questions/ByTitle", indexDef: new IndexDefinitionBuilder<Question> { Map = questions => questions.Select(question => new { Title = question.Title } ) }); } } } }
برنامه را اجرا کرده و سپس به کنسول مدیریتی تحت وب RavenDB، قسمت ایندکسهای آن مراجعه کنید. در اینجا میتوان ایندکس جدید ایجاد شده را مشاهده کرد:
هرچند همین اعمال را در کنسول مدیریتی نیز میتوان انجام داد، اما مزیت آن در سمت کدها، دسترسی به intellisense و نوشتن کوئریهای strongly typed است.
روش استفاده از store.DatabaseCommands.PutIndex اولین روش تولید Index در RavenDB با کدنویسی است. روش دوم، بر اساس ارث بری از کلاس AbstractIndexCreationTask شروع میشود و مناسب است برای حالتیکه نمیخواهید کدهای تولید ایندکس، با کدهای سایر قسمتهای برنامه مخلوط شوند:
public class QuestionsByTitle : AbstractIndexCreationTask<Question> { public QuestionsByTitle() { Map = questions => questions.Select(question => new { Title = question.Title }); } }
اکنون برای معرفی آن به برنامه باید از متد IndexCreation.CreateIndexes استفاده کرد. این متد، نیاز به دریافت اسمبلی محل تعریف کلاسهای تولید ایندکس را دارد. به این ترتیب تمام کلاسهای مشتق شده از AbstractIndexCreationTask را یافته و ایندکسهای متناظری را تولید میکند.
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { IndexCreation.CreateIndexes(typeof(QuestionsByTitle).Assembly, store); }
استفاده از ایندکسهای ایستای ایجاد شده
تا اینجا موفق شدیم ایندکسهای ایستای خود را با کد نویسی ایجاد کنیم. در ادامه قصد داریم از این ایندکسها در کوئریهای خود استفاده نمائیم.
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { var questions = session.Query<Question>(indexName: "QuestionsByTitle") .Where(x => x.Title.StartsWith("Raven")).Take(128); foreach (var question in questions) { Console.WriteLine(question.Title); } } }
Request # 147: GET - 58 ms - <system> - 200 - /indexes/QuestionsByTitle?&query=Title%3ARaven*&pageSize=128 Query: Title:Raven* Time: 7 ms Index: QuestionsByTitle Results: 2 returned out of 2 total.
var questions = session.Query<Question, QuestionsByTitle>() .Where(x => x.Title.StartsWith("Raven")).Take(128);
ایجاد ایندکسهای پیشرفته با پیاده سازی Map/Reduce
حالتی را در نظر بگیرید که در آن قصد داریم تعداد عنوانهای سؤالات مانند هم را بیابیم (یا تعداد مطالب گروههای مختلف یک وبلاگ را محاسبه کنیم). برای انجام اینکار با سرعت بسیار بالا، میتوانیم از ایندکسهایی با قابلیت محاسباتی در RavenDB استفاده کنیم. کار با ارث بری از کلاس AbstractIndexCreationTask شروع میشود. آرگومان جنریک اول آن، نام کلاسی است که در تهیه ایندکس شرکت خواهد داشت و آرگومان دوم (و اختیاری) ذکر شده، نتیجه عملیات Reduce است:
public class QuestionsCountByTitleReduceResult { public string Title { set; get; } public int Count { set; get; } } public class QuestionsCountByTitle : AbstractIndexCreationTask<Question, QuestionsCountByTitleReduceResult> { public QuestionsCountByTitle() { Map = questions => questions.Select(question => new { Title = question.Title, Count = 1 }); Reduce = results => results.GroupBy(x => x.Title) .Select(g => new { Title = g.Key, Count = g.Sum(x => x.Count) }); } }
اکنون برای استفاده از این ایندکس، ابتدا توسط متد IndexCreation.CreateIndexes، کار معرفی آن به RavenDB صورت گرفته و سپس متد Query سشن باز شده، دو آرگومان جنریگ را خواهد پذیرفت. اولین آرگومان، همان نتیجه Map/Reduce است و دومین آرگومان نام کلاس ایندکس جدید تعریف شده میباشد:
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { IndexCreation.CreateIndexes(typeof(QuestionsCountByTitle).Assembly, store); using (var session = store.OpenSession()) { var result = session.Query<QuestionsCountByTitleReduceResult, QuestionsCountByTitle>() .FirstOrDefault(x => x.Title == "Raven") ?? new QuestionsCountByTitleReduceResult(); Console.WriteLine(result.Count); } }