اشتراکها
PersianDatePicker یک DatePicker شمسی برای نمایش تاریخ شمسی در صفحات وب است.
مهمترین ویژگیها :
textBox : کنترلی است که DatePicker برای آن نمایش داده میشود.
today : تاریخ روز جاری است.
برای مثال :
در ASP.NET Web Forms :
در مثال بالا برای گرفتن تاریخ روز جاری از PersianDateTime استفاده شده است.
در ASP.NET MVC یا PHP یا هر زبان دیگری کافیست onclick کنترل متنی مورد نظر در سمت سرور مانند مثال بالا مقدار داده شود. یا میتوان image کوچکی کنار textbox مورد نظر قرار داد و onclick آن تنظیم شود.
برای استفاده از PersianDatePicker میتوانید آنرا از NuGet دریافت کنید :
- از تاریخ سرور برای نمایش روز جاری استفاده میکند.
- به زبان جاوااسکریپت است و نیازی به سایر فریمورکها مانند jQuery ندارد.
- سبک و کم حجم است (3.5 کیلوبایت)
- روزها به صورت عمودی لیست شدهاند مانند برنامه هفتگی مدرسه که کاربران فارسیزبان با آن راحتترند.
طرز استفاده :
PersianDatePicker.Show(textBox, today)
today : تاریخ روز جاری است.
برای مثال :
<html> <head> <script type="text/javascript" src="Scripts/PersianDatePicker.min.js"></script> <link type="text/css" rel="stylesheet" href="Content/PersianDatePicker.min.css" /> </head> <body> <input type="text" onclick="PersianDatePicker.Show(this, '1392/03/22');" /> </body> </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="Scripts/PersianDatePicker.min.js"></script> <link href="Content/PersianDatePicker.min.css" rel="stylesheet" /> </head> <body> <form id="form1" runat="server"> <div> <asp:Label runat="server" Text="Label" AssociatedControlID="TextBox1">تاریخ : </asp:Label> <asp:TextBox runat="server" ID="TextBox1"></asp:TextBox> </div> </form> </body> </html>
public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { var now = PersianDateTime.Now; var today = now.ToString(PersianDateTimeFormat.Date); TextBox1.Attributes["onclick"] = "PersianDatePicker.Show(this,'" + today + "');"; } }
در مثال بالا برای گرفتن تاریخ روز جاری از PersianDateTime استفاده شده است.
در ASP.NET MVC یا PHP یا هر زبان دیگری کافیست onclick کنترل متنی مورد نظر در سمت سرور مانند مثال بالا مقدار داده شود. یا میتوان image کوچکی کنار textbox مورد نظر قرار داد و onclick آن تنظیم شود.
برای استفاده از PersianDatePicker میتوانید آنرا از NuGet دریافت کنید :
PM> Install-Package PersianDatePicker
اشتراکها
2.Visual Studio 2019 RC منتشر شد
Top Issues Fixed in Visual Studio 2019 RC.2
- Find in files "Locating next match" UI is annoying.
- Find files keeps defaulting to current document.
- Quick references freezes VS 2019 RC.
- PackageId:MsSqlCmdLnUtils;PackageAction:Install;ReturnCode:1603;.
- Error List does not show errors because it is scoped to "Current Document".
- Cannot use conditional breakpoint on PropertyInfo.Name value.
- Visual Studio crashes when parsing macros at the end of a file.
- Search in Visual Studio 2019 is very slow.
- Visual Studio hangs when starting debugging.
- vdproj not supported in Visual Studio 2019 RC.
- Visual Studio installer welcome image contains offensive element for Chinese.
- VSIX Extension pre-req has been removed in Visual Studio 2019 RC breaking extension compatibility.
- Create Project from Start Screen Ignores Selected Project Folder.
- cpp properties is dialog does not show up when using Project menu item or select "Manage configuration" drop down menu.
- Visual Studio 2019 Build Tools - developer prompt title says "Developer Command Prompt for Visual Studio 2017".
- German tranlation regarding the Feedback Tool: Help > Send Feedback > Report a Problem.
- 自动完成功能,如果双击候选项,会丢失输入焦点,需要单机编辑器才能继续输入-AutoComplete function, if you double-click the candidate, will lose the input focus, need a stand-alone editor to continue to enter.
- Context menus are sometimes placed on the wrong monitor in a multiple monitor configuration.
- Visual Studio 2019 conflict with QQ Pinyin.
- Cannot drag maximized Visual Studio window.
- Fixed slow reload of multiple C# and Visual Basic projects.
- When IntelliSense is present, when a user types Shift + Enter, the active selection will be completed and a new line inserted.
- Fixed a PMA issue where editor tooltips and light bulb doesn't render properly.
- Notifications about crashes caused by extensions now show up again.
- Notifications about performance of Visual Studio have been secured against tampering.
- Fixed an issue with toolbar rendering when dragged across displays.
- Fixed an issue with Tools Options rendering when running with per-monitor awareness enabled.
- Various DpiHelper classes has been deprecated (extensibility).
- Fixed splash screen scaling to better match the primary monitor scale factor.
- Fixed an issue in settings import where warnings/errors were not always reported correctly.
- Fixed an issue where Tools Options reported software rendering regardless of rendering tier.
- Fixed an issue where the name of the open folder was not displayed in the title bar region.
- Fixed an issue with find in files positioning when per-monitor awareness is enabled.
- Fixed an issue with dock adorner rendering when per-monitor awareness is enabled.
پس از آشنایی با نحوهی ایجاد و به روز رسانی جدول مجازی FTS، اکنون قصد داریم با روشهای کوئری گرفتن از آن آشنا شویم. برای این منظور در ابتدا نیاز است تعدادی رکورد را در آن ثبت کنیم:
در اینجا به صورت متداولی، اطلاعات در جدول اصلی Chapters ثبت میشوند و چون SaveChanges را در قسمت قبل جهت به روز رسانی خودکار جدول مجازی Chapters_FTS بازنویسی کردیم، فراخوانی آن، سبب تولید ایندکسهای Full Text هم میشود.
ثبت اطلاعات فوق، چنین رکوردهایی را در جدول Chapters به وجود میآورد که شامل اطلاعات یونیکد، HTML ای و غیره است:
اجرای اولین کوئری بر روی جدول مجازی Chapters_FTS به صورت مستقیم
کوئریهای Full-text در SQLite، چنین شکل کلی را دارند و توسط تابع match انجام میشوند:
که یک چنین خروجی را نیز به همراه دارد:
همانطور که مشاهده میکنید در اینجا تنها دو ستونی که ایندکس شدهاند، در خروجی نهایی ظاهر میشوند؛ اما این جدول به همراه ستونهای مخفی توکار دیگری نیز هست:
در این کوئری اینبار ستونهای مخفی rank و همچنین rowid را نیز میتوانید مشاهده کنید:
- Rowid با توجه به تعریفی که در قسمت قبل انجام دادیم:
به همان primary-key جدول اصلی chapters اشاره میکند. بنابراین اگر نیاز باشد تا این خروجی حاصل از کوئری بر روی جدول مجازی Chapters_FTS را به جدول اصلی chapters متصل کرد، میتوان از مقدار rowid بازگشتی استفاده نمود.
- تمام جداول مجازی FTS، به همراه ستون مخفی rank نیز هستند که میزان نزدیک بودن خروجی حاصل را به کوئری درخواستی مشخص میکنند. این عدد توسط تابعی به نام bm25 تهیه میشود. اگر کوئری FTS به همراه قسمت where نباشد، مقدار rank همواره نال خواهد بود. اما اگر قسمت where به همراه match قید شود، مقدار rank، مقدار از پیش محاسبه شدهی تابع توکار bm25 است. به همین جهت کار با این مقدار از پیش محاسبه شده، سریعتر از فراخوانی مستقیم متد bm25 است. برای مثال دو کوئری زیر اساسا یکی هستند؛ اما دومی سریعتر است:
یک نکته: کوئری FTS فوق بر روی هر دو ستون title و text اجرا میشود (و یا هر ستون موجود دیگری که پیشتر ایندکس شده باشد).
اجرای اولین کوئری بر روی جدول مجازی Chapters_FTS توسط EF Core
پس از آشنایی مقدماتی با کوئری نویسی FTS در SQLite، بر انجام یک چنین کوئری در EF Core میتوان به صورت زیر عمل کرد:
- ابتدا باید یک موجودیت بدون کلید را مطابق ستونهای مخفی و ایندکس شدهی بازگشتی تهیه کنیم:
همانطور که مشاهده میکنید، rank به صورت نال پذیر تعریف شدهاست؛ چون اگر قسمت where ذکر نشود، مقداری نخواهد داشت.
- سپس نیاز است این موجودیت بدون کلید را به EF معرفی کنیم:
در اینجا ChapterFTS تهیه شده، با متد HasNoKey علامتگذاری میشود تا آنرا بتوان بدون مشکل در کوئریهای EF استفاده کرد. همچنین فراخوانی ToView(null) سبب میشود تا EF Core جدولی را در حین Migration از روی این موجودیت ایجاد نکند و آنرا به همین حال رها کند.
- و در آخر روش کوئری گرفتن از جدول مجازی FTS در EF Core به صورت زیر میباشد که توسط متد FromSqlRaw به صورت پارامتری (مقاوم در برابر حملات تزریق اسکیوال)، قابل انجام است:
بررسی قابلیتهای ویژهی کوئریهای FTS در SQLite
اکنون که با روش کلی کوئری گرفتن از جدول مجازی FTS آشنا شدیم، نکات ویژهی آنرا بررسی میکنیم و در اینجا بیشتر پارامتر ذکر شدهی پس از عملگر match تغییر خواهد کرد و مابقی قسمتهای آن ثابت و مانند قبل هستند.
بجای عملگر match میتوان از = نیز استفاده کرد
دو کوئری زیر دقیقا به یک معنا هستند:
و هر دو همانطور که عنوان شد بر روی تمام ستونهای ایندکس شدهی موجود اجرا میشوند و اگر نیاز است نتایج را بر اساس میزان نزدیکی آنها به کوئری انجام شده مرتب کرد، میتوان یک ORDER by rank را نیز به انتهای آنها افزود:
جستجوهایی به همراه واژههایی در کنار هم
از دیدگاه FTS، دو کوئری زیر که در قسمت match آنها، واژهها با فاصله در کنار هم قرار گرفتهاند، یکی هستند:
و هر دو خروجی زیر را تولید میکنند:
علت اینجا است که یک full-text search بر اساس ایندکس شدن واژهها تولید میشود و هر کدام از این واژهها به یک توکن نگاشت خواهند شد. به همین جهت است که در اینجا تفاوتی بین + و فاصله در عبارت جستجو شده وجود ندارد. در این حالت اگر در یکی از ستونهای ایندکس شده، واژهی learn و یا واژهی SQLite بکار رفته باشد، در خروجی نهایی لیست خواهد شد.
امکان جستجو بر اساس پیشوندها
میتوان با استفاده از *، تمام توکنهای ایندکس شده و شروع شدهی با واژهی مشخصی را جستجو کرد:
برای مثال در اینجا رکوردهایی که دارای واژههایی مانند search، searching و غیره هستند، بازگشت داده میشوند:
امکان استفاده از عملگرهای بولی NOT، AND و OR
اگر learn text را جستجو کنیم:
رکوردی با ID مساوی 1 بازگشت داده میشود. اما اگر نیاز باشد رکوردی بازگشت داده شود که حاوی learn باشد، اما text خیر، میتوان از عملگر NOT استفاده کرد:
که اینبار رکوردی با ID مساوی 3 را بازگشت دادهاست.
نکتهی مهم: عملگرهای بولی FTS مانند AND، OR، NOT و غیره باید با حروف بزرگ قید شوند.
در ادامه مثال دیگری از ترکیب عملگرهای بولی را مشاهده میکنید:
که تقدم و تاخر این عملگرها را میتوان توسط پرانتزها به صورت صریحی نیز مشخص کرد:
امکان ذکر صریح ستونهای مدنظر در کوئری
همانطور که عنوان شد، حالت پیشفرض جستجوهای تمام متنی، جستجوی واژهی مدنظر در تمام ستونهای ایندکس شدهاست؛ اما شاید این مورد مدنظر شما نباشد. به همین منظور میتوان ابتدا نام ستون مدنظر را ذکر کرد و پس از آن یک : را قرار داد تا فقط جستجو بر روی آن ستون خاص صورت گیرد:
امکان ترکیب نام ستونها به صورت {col2 col1 col3} نیز وجود دارد.
نکتهی مهم! در جستجوهای FTS در SQLite، ذکر - به معنای قید صریح نام یک ستون خاص است (و یا لیست ستونهایی به صورت {col2 col1 col3}-) که قرار نیست چیزی با آن(ها) انطباق داده شود (- شبیه به عملگر NOT عمل میکند؛ اینبار در مورد ستونها) و این مورد عموما تازهکاران را به اشتباه میاندازد. برای مثال در ابتدای بحث، دو رکورد را که دارای text ای مساوی عبارات زیر هستند، ثبت کردیم:
اکنون فرض کنید میخواهیم 2018-2019 را جستجو کنیم:
خروجی آن خطای زیر است و عنوان میکند که ستون 2019 تعریف نشدهاست؛ چون پس از -، به دنبال نام یک ستون ایندکس شده میگردد:
برای رفع این مشکل میتوان - را حذف کرد:
و یا میتوان عبارت جستجو شده را بین "" قرار داد:
و یا حتی میتوان '"2018 2019"' را نیز جستجو کرد که نتیجهی مشابهی را ارائه میدهد.
امکان جستجوی بر روی عبارات یونیکد
FTS5 و آخرین نگارش SQLite، به همراه tokenizer مخصوص یونیکد نیز هست و با اینگونه جستجوهای تمام متنی، مشکلی ندارد:
توابع کمکی FTS در SQLite برای متمایز سازی عبارات یافت شدهی در متن
فرض کنید میخواهیم واژهی fts5 را جستجو کرده و همچنین در خروجی نهایی، هرجائیکه fts5 قرار دارد، آنرا به صورت bold نمایش دهیم. برای اینکار، تابع توکار highlight قابل استفادهاست. اما اگر در این بین خواستیم فقط قسمت کوتاهی از متن مورد نظر را که به جستجوی ما نزدیک است نمایش دهیم، میتوان از متد توکار snippet استفاده کرد:
نکتهی مهم: چون بر اساس نکات قسمت قبل، متنی که به Chapters_FTS ارسال میشود، نرمال سازی شدهاست، متدهای فوق کارآیی خودشان را از دست میدهند. برای مثال اگر در کوئری فوق، واژهی funny را که به یک رکورد HTML ای اشاره میکند، جستجو کنیم، خروجی زیر را دریافت خواهیم کرد:
خروجی نهایی، چون به جدول اصلی chapters متصل است، اصل متن را بازگشت میدهد، اما چون اطلاعاتی را که به Chapters_FTS ارسال کردهایم، فاقد تگهای HTML هستند، تا خروجی دقیقی حاصل شود، متدهای highlight و snippet دیگر قادر به علامتگذاری خروجی نهایی نبوده و اینکار را باید خودمان به صورت دستی در سمت کلاینت انجام دهیم.
private static void seedDb(ApplicationDbContext context) { if (!context.Chapters.Any()) { var user1 = context.Users.Add(new User { Name = "Test User" }); context.Chapters.Add(new Chapter { Title = "Learn SQlite FTS5", Text = "This tutorial teaches you how to perform full-text search in SQLite using FTS5", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "Advanced SQlite Full-text Search", Text = "Show you some advanced techniques in SQLite full-text searching", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "SQLite Tutorial", Text = "Help you learn SQLite quickly and effectively", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "Handle markup in text", Text = "<p>Isn't this <font face=\"Comic Sans\">funny</font>?", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "آزمایش متن فارسی", Text = "برای نمونه تهیه شدهاست", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "Exclude test 1", Text = "in the years 2018-2019 something happened.", User = user1.Entity }); context.Chapters.Add(new Chapter { Title = "Exclude test 2", Text = "It was 2018 and then it was 2019", User = user1.Entity }); context.SaveChanges(); } }
ثبت اطلاعات فوق، چنین رکوردهایی را در جدول Chapters به وجود میآورد که شامل اطلاعات یونیکد، HTML ای و غیره است:
اجرای اولین کوئری بر روی جدول مجازی Chapters_FTS به صورت مستقیم
کوئریهای Full-text در SQLite، چنین شکل کلی را دارند و توسط تابع match انجام میشوند:
select * from Chapters_FTS where Chapters_FTS match "fts5"
همانطور که مشاهده میکنید در اینجا تنها دو ستونی که ایندکس شدهاند، در خروجی نهایی ظاهر میشوند؛ اما این جدول به همراه ستونهای مخفی توکار دیگری نیز هست:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "fts5"
- Rowid با توجه به تعریفی که در قسمت قبل انجام دادیم:
CREATE VIRTUAL TABLE "Chapters_FTS" USING fts5("Text", "Title", content="Chapters", content_rowid="Id")
- تمام جداول مجازی FTS، به همراه ستون مخفی rank نیز هستند که میزان نزدیک بودن خروجی حاصل را به کوئری درخواستی مشخص میکنند. این عدد توسط تابعی به نام bm25 تهیه میشود. اگر کوئری FTS به همراه قسمت where نباشد، مقدار rank همواره نال خواهد بود. اما اگر قسمت where به همراه match قید شود، مقدار rank، مقدار از پیش محاسبه شدهی تابع توکار bm25 است. به همین جهت کار با این مقدار از پیش محاسبه شده، سریعتر از فراخوانی مستقیم متد bm25 است. برای مثال دو کوئری زیر اساسا یکی هستند؛ اما دومی سریعتر است:
select * from Chapters_FTS where Chapters_FTS match "fts5" ORDER BY bm25(fts); select * from Chapters_FTS where Chapters_FTS match "fts5" ORDER BY rank;
یک نکته: کوئری FTS فوق بر روی هر دو ستون title و text اجرا میشود (و یا هر ستون موجود دیگری که پیشتر ایندکس شده باشد).
اجرای اولین کوئری بر روی جدول مجازی Chapters_FTS توسط EF Core
پس از آشنایی مقدماتی با کوئری نویسی FTS در SQLite، بر انجام یک چنین کوئری در EF Core میتوان به صورت زیر عمل کرد:
- ابتدا باید یک موجودیت بدون کلید را مطابق ستونهای مخفی و ایندکس شدهی بازگشتی تهیه کنیم:
namespace EFCoreSQLiteFTS.Entities { public class ChapterFTS { public int RowId { get; set; } public decimal? Rank { get; set; } public string Title { get; set; } public string Text { get; set; } } }
- سپس نیاز است این موجودیت بدون کلید را به EF معرفی کنیم:
namespace EFCoreSQLiteFTS.DataLayer { public class ApplicationDbContext : DbContext { //... protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.Entity<ChapterFTS>().HasNoKey().ToView(null); } //... } }
- و در آخر روش کوئری گرفتن از جدول مجازی FTS در EF Core به صورت زیر میباشد که توسط متد FromSqlRaw به صورت پارامتری (مقاوم در برابر حملات تزریق اسکیوال)، قابل انجام است:
const string ftsSql = "SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH {0}"; foreach (var chapter in context.Set<ChapterFTS>().FromSqlRaw(ftsSql, "fts5")) { Console.WriteLine($"Title: {chapter.Title}"); Console.WriteLine($"Text: {chapter.Text}"); }
بررسی قابلیتهای ویژهی کوئریهای FTS در SQLite
اکنون که با روش کلی کوئری گرفتن از جدول مجازی FTS آشنا شدیم، نکات ویژهی آنرا بررسی میکنیم و در اینجا بیشتر پارامتر ذکر شدهی پس از عملگر match تغییر خواهد کرد و مابقی قسمتهای آن ثابت و مانند قبل هستند.
بجای عملگر match میتوان از = نیز استفاده کرد
دو کوئری زیر دقیقا به یک معنا هستند:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "fts5"; SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS = "fts5";
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "fts5" ORDER by rank;
جستجوهایی به همراه واژههایی در کنار هم
از دیدگاه FTS، دو کوئری زیر که در قسمت match آنها، واژهها با فاصله در کنار هم قرار گرفتهاند، یکی هستند:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "learn SQLite" ORDER by rank; SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "learn + SQLite" ORDER by rank;
علت اینجا است که یک full-text search بر اساس ایندکس شدن واژهها تولید میشود و هر کدام از این واژهها به یک توکن نگاشت خواهند شد. به همین جهت است که در اینجا تفاوتی بین + و فاصله در عبارت جستجو شده وجود ندارد. در این حالت اگر در یکی از ستونهای ایندکس شده، واژهی learn و یا واژهی SQLite بکار رفته باشد، در خروجی نهایی لیست خواهد شد.
امکان جستجو بر اساس پیشوندها
میتوان با استفاده از *، تمام توکنهای ایندکس شده و شروع شدهی با واژهی مشخصی را جستجو کرد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "search*" ORDER by rank;
امکان استفاده از عملگرهای بولی NOT، AND و OR
اگر learn text را جستجو کنیم:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "learn text" ORDER by rank;
رکوردی با ID مساوی 1 بازگشت داده میشود. اما اگر نیاز باشد رکوردی بازگشت داده شود که حاوی learn باشد، اما text خیر، میتوان از عملگر NOT استفاده کرد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "learn NOT text" ORDER by rank;
که اینبار رکوردی با ID مساوی 3 را بازگشت دادهاست.
نکتهی مهم: عملگرهای بولی FTS مانند AND، OR، NOT و غیره باید با حروف بزرگ قید شوند.
در ادامه مثال دیگری از ترکیب عملگرهای بولی را مشاهده میکنید:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "search AND sqlite OR help" ORDER by rank;
که تقدم و تاخر این عملگرها را میتوان توسط پرانتزها به صورت صریحی نیز مشخص کرد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "search AND (sqlite OR help)" ORDER by rank;
امکان ذکر صریح ستونهای مدنظر در کوئری
همانطور که عنوان شد، حالت پیشفرض جستجوهای تمام متنی، جستجوی واژهی مدنظر در تمام ستونهای ایندکس شدهاست؛ اما شاید این مورد مدنظر شما نباشد. به همین منظور میتوان ابتدا نام ستون مدنظر را ذکر کرد و پس از آن یک : را قرار داد تا فقط جستجو بر روی آن ستون خاص صورت گیرد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "text:some AND title:sqlite" ORDER by rank;
امکان ترکیب نام ستونها به صورت {col2 col1 col3} نیز وجود دارد.
نکتهی مهم! در جستجوهای FTS در SQLite، ذکر - به معنای قید صریح نام یک ستون خاص است (و یا لیست ستونهایی به صورت {col2 col1 col3}-) که قرار نیست چیزی با آن(ها) انطباق داده شود (- شبیه به عملگر NOT عمل میکند؛ اینبار در مورد ستونها) و این مورد عموما تازهکاران را به اشتباه میاندازد. برای مثال در ابتدای بحث، دو رکورد را که دارای text ای مساوی عبارات زیر هستند، ثبت کردیم:
"in the years 2018-2019 something happened" "It was 2018 and then it was 2019"
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "2018-2019" ORDER by rank;
Execution finished with errors. Result: no such column: 2019
و یا میتوان عبارت جستجو شده را بین "" قرار داد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH '"2018-2019"' ORDER by rank;
و یا حتی میتوان '"2018 2019"' را نیز جستجو کرد که نتیجهی مشابهی را ارائه میدهد.
امکان جستجوی بر روی عبارات یونیکد
FTS5 و آخرین نگارش SQLite، به همراه tokenizer مخصوص یونیکد نیز هست و با اینگونه جستجوهای تمام متنی، مشکلی ندارد:
SELECT rowid, title, text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "آزمایش" ORDER by rank;
توابع کمکی FTS در SQLite برای متمایز سازی عبارات یافت شدهی در متن
فرض کنید میخواهیم واژهی fts5 را جستجو کرده و همچنین در خروجی نهایی، هرجائیکه fts5 قرار دارد، آنرا به صورت bold نمایش دهیم. برای اینکار، تابع توکار highlight قابل استفادهاست. اما اگر در این بین خواستیم فقط قسمت کوتاهی از متن مورد نظر را که به جستجوی ما نزدیک است نمایش دهیم، میتوان از متد توکار snippet استفاده کرد:
SELECT rowid, highlight(Chapters_FTS, title, '<b>', '</b>') as title, snippet(Chapters_FTS, text, '<b>', '</b>', '...', 64) as text, rank FROM Chapters_FTS WHERE Chapters_FTS MATCH "fts5" ORDER BY rank
نکتهی مهم: چون بر اساس نکات قسمت قبل، متنی که به Chapters_FTS ارسال میشود، نرمال سازی شدهاست، متدهای فوق کارآیی خودشان را از دست میدهند. برای مثال اگر در کوئری فوق، واژهی funny را که به یک رکورد HTML ای اشاره میکند، جستجو کنیم، خروجی زیر را دریافت خواهیم کرد:
خروجی نهایی، چون به جدول اصلی chapters متصل است، اصل متن را بازگشت میدهد، اما چون اطلاعاتی را که به Chapters_FTS ارسال کردهایم، فاقد تگهای HTML هستند، تا خروجی دقیقی حاصل شود، متدهای highlight و snippet دیگر قادر به علامتگذاری خروجی نهایی نبوده و اینکار را باید خودمان به صورت دستی در سمت کلاینت انجام دهیم.
In short, domain events help you to express, explicitly, the domain rules, based in the ubiquitous language provided by the domain experts. Domain events also enable a better separation of concerns among classes within the same domain.
It's important to ensure that, just like a database transaction, either all the operations related to a domain event finish successfully or none of them do.
Domain events are similar to messaging-style events, with one important difference. With real messaging, message queuing, message brokers, or a service bus using AMQP, a message is always sent asynchronously and communicated across processes and machines. This is useful for integrating multiple Bounded Contexts, microservices, or even different applications. However, with domain events, you want to raise an event from the domain operation you are currently running, but you want any side effects to occur within the same domain.
The domain events and their side effects (the actions triggered afterwards that are managed by event handlers) should occur almost immediately, usually in-process, and within the same domain. Thus, domain events could be synchronous or asynchronous. Integration events, however, should always be asynchronous.
اشتراکها
معرفی Dev Home
اشتراکها
لیستی از NET Core Tools.
نظرات مطالب
EF Code First #4
سلام آقای نصیری؛
منم همین پیام را دریافت میکنم، ولی من EF نسخۀ 5.0 را استفاده میکنم و اونو هم با NuGet به پروژه اضافه کردهم. ویژوال استدیو نسخۀ 2012 هست و با داتنت 4.5 برنامه را ایجاد کردهم. برنامه تا آخر درس قبل کاملاً همونطور که انتظار میرفت اجرا شد و مشکلی هم نداشت.
اما به محض باز کردن package manager console از منوی Tools، بعد از معرفی نسخۀ کنسول
Package Manager Console Host Version 2.6.40627.9000 خطوط زیر را با زمینۀ قرمز مینویسه:
برای دستور enable-migrations هم دقیقاً همون چیزی را مینویسه که در کامنت اول davmszd بیان شده، یعنی اینو:
و هنگامی هم که دستور Get-Packageرا اجرا میکنم، اینو مینویسه:
ضمناً در پوشۀ packages در کنار پروژه، فولدری بنام EntityFramework.5.0.0 و داخل اون هم فولدر tools با این فایلها وجود داره:
ممنون میشم اگر منو راهنمایی بفرمایید.
منم همین پیام را دریافت میکنم، ولی من EF نسخۀ 5.0 را استفاده میکنم و اونو هم با NuGet به پروژه اضافه کردهم. ویژوال استدیو نسخۀ 2012 هست و با داتنت 4.5 برنامه را ایجاد کردهم. برنامه تا آخر درس قبل کاملاً همونطور که انتظار میرفت اجرا شد و مشکلی هم نداشت.
اما به محض باز کردن package manager console از منوی Tools، بعد از معرفی نسخۀ کنسول
Package Manager Console Host Version 2.6.40627.9000 خطوط زیر را با زمینۀ قرمز مینویسه:
Test-ModuleManifest : The specified module 'D:\Entity Framework Samples\EF Sample 02\packages\EntityFramework.5.0.0\tools\EntityFramework.psd1' was not loaded because no valid module file was found in any module directory. At D:\Entity Framework Samples\EF Sample 02\packages\EntityFramework.5.0.0\tools\init.ps1:14 char:34 + $thisModule = Test-ModuleManifest <<<< (Join-Path $toolsPath $thisModuleManifest) + CategoryInfo : ResourceUnavailable: (D:\Entity Framework Samples\E...yFramework.psd1:String) [Test-ModuleManifest], FileNotFoundException + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.TestModuleManifestCommand Import-Module : Cannot bind argument to parameter 'Name' because it is null. At D:\Entity Framework Samples\EF Sample 02\packages\EntityFramework.5.0.0\tools\init.ps1:31 char:18 + Import-Module <<<< $thisModule + CategoryInfo : InvalidData: (:) [Import-Module], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportModuleCommand
The term 'enable-migrations' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:18 + enable-migrations <<<< + CategoryInfo : ObjectNotFound: (enable-migrations:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
Id Version Description/Release Notes -- ------- ------------------------- EntityFramework 5.0.0 Entity Framework is Microsoft's recommended data access technology for new applications.
about_EntityFramework.help.txt EntityFramework.PowerShell.dll EntityFramework.PowerShell.Utility.dll EntityFramework.PS3.psd1 EntityFramework.psd1 EntityFramework.psm1 init.ps1 install.ps1 migrate.exe Redirect.config Redirect.VS11.config
ASP.NET Core applications can be tested with different testing
frameworks and Entity Framework Core makes testing specially easy by
removing different technical problems from our way by using in-memory
data provider. This blog posts shows how to unit test controllers that
use data from Entity Framework Core.