مطالب
مرتب سازی صحیح حروف فارسی در بانک اطلاعاتی SQLite
فرض کنید لیست حروف الفبای فارسی را در یک بانک اطلاعاتی SQLite ذخیره کرده‌اید:
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();

var createCommand = connection.CreateCommand();
createCommand.CommandText =
            @"
                CREATE TABLE persian_letter (
                    value TEXT
                );

                INSERT INTO persian_letter
                VALUES ('ا'),('ب'),('پ'),('ت'),('ث'),('ج'),('چ'),('ح'),('خ'),('د'),('ذ'),('ر'),('ز'),('ژ'),('س'),('ش'),
                       ('ص'),('ض'),('ط'),('ظ'),('ع'),('غ'),('ف'),('ق'),('ک'),('گ'),('ل'),('م'),('ن'),('و'),('ه'),('ی');
            ";
createCommand.ExecuteNonQuery();
اگر از این لیست کوئری گرفته و آن‌ها‌را مرتب کنیم:
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
            @"
                SELECT value
                FROM persian_letter
                order by value
            ";
var reader = queryCommand.ExecuteReader();
var sortedDbItems = new List<string>();
while (reader.Read())
{
    sortedDbItems.Add($"{reader["value"]}");
}
یک چنین خروجی حاصل می‌شود:


همانطور که ملاحظه می‌کنید، مرتب سازی حروف فارسی در اینجا به صورت پیش‌فرض کار نمی‌کند. علت اینجا است که روش پیش‌فرض مرتب سازی حروف در SQLite، بر اساس کد اسکی حروف است و فقط در مورد حروف ASCII از A تا Z درست کار می‌کند.


امکان تعریف Collation سفارشی در SQLite

در بانک‌های اطلاعاتی، قابلیتی که مستقیما بر روی نحوه‌ی جستجو و همچنین مرتب سازی حروف تاثیر می‌گذارد، Collation نام دارد و در SQLite برخلاف بسیاری از بانک‌های اطلاعاتی دیگر، امکان تعریف Collation سفارشی نیز وجود دارد و برای این منظور باید یک function pointer را در اختیار آن قرار داد تا از آن در سمت بانک اطلاعاتی جهت مرتب سازی و جستجوی حروف استفاده کند.
خوشبختانه پروژه‌ی Microsoft.Data.Sqlite امکان تبدیل یک managed delegate دات نتی را به یک function pointer مخصوص SQLite، میسر می‌کند. به عبارتی SQLite کدهای دات نتی را در حین انجام محاسبات خود اجرا خواهد کرد و این اجرا به صورتی نیست که ابتدا کل اطلاعات، به سمت برنامه‌ی کلاینت منتقل شود و سپس در این سمت، در حافظه، عملیاتی بر روی آن صورت گیرد. کل عملیات در سمت بانک اطلاعاتی مدیریت می‌شود.
روش تعریف یک Collation جدید هم در اینجا بسیار ساده‌است:
connection.CreateCollation("PersianCollationNoCase", (x, y) => string.Compare(x, y, ignoreCase: true));
فقط کافی است بر روی اتصال باز شده، متد CreateCollation فراخوانی و نحوه‌ی مقایسه‌ی دو رشته مشخص شود. سپس این Collation نامدار، به صورت زیر در کوئری‌ها قابل استفاده خواهد بود:
SELECT value
FROM persian_letter
order by value COLLATE PersianCollationNoCase
اینبار اگر خروجی برنامه را بررسی کنیم، مشاهده خواهیم کرد که مرتب سازی حروف فارسی در SQLite به درستی کار می‌کند:



تعریف Collation سفارشی غیرحساس به «ی و ک» !

این مورد شاید یکی از آرزوهای توسعه دهندگان SQL Server باشد! اما با SQLite به سادگی زیر قابل تعریف و مدیریت است:
connection.CreateCollation("PersianCollationNoCaseYekeInsensitive",
(x, y) => string.Compare(x.ApplyCorrectYeKe(), y.ApplyCorrectYeKe(), ignoreCase: true));
متد ApplyCorrectYeKe فوق از بسته‌ی نیوگت DNTPersianUtils.Core دریافت شده و کار آن یک‌دست کردن «ی و ک» فارسی و عربی است.
در یک چنین حالتی اگر اطلاعاتی را به همراه «ی و ک» فارسی و یا عربی ثبت کنیم:
CREATE TABLE persian_letter (
value TEXT
);
INSERT INTO persian_letter
VALUES ('ی'),('ک');
جستجوی بر روی آن‌ها دیگر وابسته‌ی به مقدار «ی و ک» وارد شده نبوده و چه «ی و ک» فارسی وارد شود و چه عربی، این کوئری همواره کار می‌کند:
SELECT count()
FROM persian_letter
WHERE value = 'ی' COLLATE PersianCollationNoCaseYekeInsensitive


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید: SQLitePersianCollation.zip
نظرات اشتراک‌ها
ایجاد یک موتور جستجوی سفارشی جهت search bar فایرفاکس
این موارد هست که توسط افزونه extensions list dumper تهیه شد:
- Adblock Plus 2.1.2
http://adblockplus.org/en/
- Add to Search Bar 2.0
http://firefox.maltekraus.de/extensions/add-to-search-bar
- Calculator 1.1.27
http://code.google.com/p/firefoxcalculator/
- CodeBurner for Firebug 1.6
http://tools.sitepoint.com/codeburner
- ColorZilla 2.8.1
http://www.colorzilla.com/
- Cookies Manager+ 1.5.1
https://addons.mozilla.org/en-US/firefox/addon/cookies-manager-plus/
- CSS Usage 0.2.9
http://spaghetticoder.org/cssusage/
- DOM Inspector 2.0.12
http://www.mozilla.org/projects/inspector/
- Extension List Dumper 1.15.2
http://www.sogame.cat/
- File Title 1.4
http://www.jasnapaka.com/mozilla/filetitle/
- Firebug 1.10.2
http://www.getfirebug.com/
- FireDiff 1.2.0
http://www.incaseofstairs.com/firediff
- Firefinder for Firebug 1.04
http://robertnyman.com/firefinder/
- FireFTP 2.0.7
http://fireftp.mozdev.org
- FireQuery 1.2
http://firequery.binaryage.com
- Forecastfox 2.2.1
http://www.getforecastfox.com/
- Greasemonkey 1.0
http://www.greasespot.net/
- HighlightAll 1.6
http://jgoudey.free.fr/highlightall/
- HttpFox 0.8.11
http://code.google.com/p/httpfox/
- IranianCalendar 3.1.20081222
http://www.alavi.us/jcal/
- Linky 3.0.0
http://gemal.dk/mozilla/linky.html
- MeasureIt 0.4.10
http://frayd.us/
- Open With 5.2.1
http://www.darktrojan.net/software/addons/openwith/
- PDF Download 3.0.0.2
http://www.pdfdownload.org
- Pixel Perfect 1.7.1
http://www.pixelperfectplugin.com/
- Pray Times! 1.1.7
http://praytimes.org/
- Proxy Selector 0.80.7
http://addons.mozilla.org
- Right-Click-Link 1.1.5
http://rickardandersson.com/
- SearchPreview 5.9
http://searchpreview.de/
- Server Spy 0.2.1
http://www.jacquet80.eu/mozilla/exts/ServerSpy/
- Session Manager 0.7.9
http://sessionmanager.mozdev.org/
- Show MyIP 0.8
http://www.tsql.de/download/firefox-addon-ip-adresse-ip-address
- Show Picture 2.7
https://addons.mozilla.org/en-US/firefox/addon/show-picture/?src=api
- Showcase 0.9.5.8
http://showcase.uworks.net/
- Snap Links Plus 2.2.1
http://snaplinks.mozdev.org/
- Sothink Web Video Downloader for Firefox 6.8
http://www.web-video-downloader.com
- Speed Dial 0.9.6.8
http://speeddial.uworks.net/
- SQLite Manager 0.7.7
http://sqlite-manager.googlecode.com/
- Stylish 1.2.6
http://userstyles.org/
- Subtitle Matcher 0.3.4
http://ds6.ovh.org/hashsubtitles/subtitle_matcher_firefox_extensions.php
- Tilt 1.0.1
http://blog.mozilla.com/tilt/
- UnMHT 5.7.5
http://www.unmht.org/unmht/en_index.html
- UnPlug 2.050
http://unplug.dbatley.com/
- User Agent Switcher 0.7.3
http://chrispederick.com/work/user-agent-switcher/
- View Source Chart 3.05
http://zigrat.com
- Viewstate Size 1.0.4
http://www.kirkov.dk/projects/firefox/viewstatesize
- Web Developer 1.2.1
http://chrispederick.com/work/web-developer/firefox/
- YSlow 3.1.4
http://developer.yahoo.com/yslow

نظرات مطالب
یک دست سازی ی و ک در برنامه‌های Entity framework 6
اصلاحیه برای SQLite

EF Core یکسری از نوع‌ها را مانند bool و DateTime به صورت رشته‌ای در SQLite ذخیره می‌کند. به همین جهت سطر زیر در PersianYeKeCommandInterceptor فوق، سبب از کار افتادن این نوع‌ها می‌شود؛ چون برای مثال DateTime را هم تبدیل به رشته می‌کند (پیش از موعد و با فرمتی که مدنظر EF Core نیست):
parameter.Value =   parameter.Value is DBNull ? parameter.Value : parameter.Value.ToString().ApplyCorrectYeKe();
روش اصلاح شده‌ی آن به صورت زیر است که رشته‌ای بودن خود Value را هم بررسی می‌کند:
if (!(parameter.Value is DBNull) && parameter.Value is string)
{
   parameter.Value =  Convert.ToString(parameter.Value, CultureInfo.InvariantCulture).ApplyCorrectYeKe();
}
نظرات مطالب
خلاصه‌ای در مورد SQL Server CE
وضعیت SQL Server CE در سال 2018
توسعه‌ی فعال این بانک اطلاعاتی مدت‌ها است که توسط مایکروسافت خاتمه یافته‌است. پشتیبانی رسمی آن در تاریخ 2016 -07-12 پایان یافته و پشتیبانی تمدید شده‌ی آن در تاریخ 2021-07-13 پایان می‌یابد و بجای آن LocalDB برای کارهای سبک توصیه می‌شود. همچنین اگر هدف شما کار با بانک‌های اطلاعاتی Embedded است، بهتر است از SQLite استفاده کنید. جالب است بدانید هرچند EF Core از SQL Server CE پشتیبانی می‌کند، اما پروایدر آن توسط مایکروسافت تهیه نشده‌است. برعکس SQLite پشتیبانی کاملی را توسط مایکروسافت پیدا کرده‌است؛ چه از لحاظ پروایدر EF Core و چه از لحاظ پروایدر ADO.NET.
اشتراک‌ها
پروژه TheIdServer

Aguafrommars/TheIdServer: OpenID/Connect, OAuth2 and WS-Federation server based on Duende IdentityServer with its admin UI 

پروژه TheIdServer
اشتراک‌ها
نگاهی به NET 5.

For now, Microsoft's .NET Core milestones page shows .NET 5.0 about 53 percent complete, with 1,066 issues open and 1,216 issues closed.

Highlights of .NET 5 include:

  • Developers will have more choice on runtime experiences.
  • Java interoperability will be available on all platforms.
  • Objective-C and Swift interoperability will be supported on multiple operating systems.
  • CoreFX will be extended to support static compilation of .NET (ahead-of-time – AOT), smaller footprints and support for more operating systems. 
نگاهی به NET 5.
مطالب
توسعه برنامه‌های Cross Platform با Xamarin Forms & Bit Framework - قسمت یازدهم
در این قسمت قصد بررسی کامپوننت‌های فوق العاده‌ی Syncfusion را داریم. احتمالا Syncfusion را با کتاب‌های Succinctly Series آن می شناسید. این شرکت برای Xamarin Forms نزدیک به 130‌ کامپوننت، شامل موارد کار با دیتا، اعم از فرم‌های Data Entry ،Data Grid و ListView را نوشته که در کنار کنترل‌های کار با فایل‌های Office-PDF و همچنین گزارشات و چارت‌ها و سایر کنترل‌های آن، نیاز هر برنامه‌ای را برآورده می‌کند. یکی از چند ده کتاب Xamarin Forms نیز توسط این شرکت نوشته شده‌است.
ما ضمن استفاده کامپوننت List View آن، هم کار با List View را یاد می‌گیریم و هم کار با Syncfusion را. در نظر داشته باشید که خود Xamarin Forms نیز List View دارد و در نسخه‌ی 4 آن که هم اکنون در مرحله‌ی Preview است، کنترل جدیدی به نام CollectionView نیز ارائه شده که امکانات خیلی خوبی دارد.
توجه: مطالب آموزش زیر، از این لینک آورده شده‌است.

برای شروع، ابتدا Nuget Package مربوطه را در پروژه‌ی XamApp نصب کنید. نیازی به نصب کردن آن در XamApp.Android و XamApp.iOS و XamApp.UWP نیست، ولی باز و بسته کردن ویژوال استودیو بعد از نصب و راست کلیک کردن بر روی Solution و زدن Restore nuget packages ایده‌ی خوبی است!

در پروژه‌ی iOS، در فایل AppDelegate.cs، بعد از Forms.Init، کد زیر را کپی کنید:

SfListViewRenderer.Init();

همین کد را در MainPage.xaml.cs در پروژه UWP، قبل از LoadApplication قرار دهید. نیازی به انجام کاری در Android نیست.

سپس Product Key این محصول را به دست آورده و در پروژه XamApp، فولدر Views در فایل SyncfusionLicense قرار دهید.

حال برای نمایش لیستی از محصولات، ابتدا کلاس Product را ایجاد می‌کنیم. چه در زمانیکه یک Rest api را در سمت سرور فراخوانی می‌کنیم و چه زمانیکه با دیتابیس بر روی گوشی یعنی Sqlite کار می‌کنیم، در نهایت لیستی از یک کلاس را داریم (در اینجا Product).

    public class Product : Bindable
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsActive { get; set; }
        public decimal Price { get; set; }
    }

در یک View Model جدید با نام ProductsViewModel، در OnNavigatedToAsync، دیتا را از سرور یا دیتابیس، بر روی گوشی دریافت می‌کنیم؛ اما در این مثال، برای راحتی بیشتر یک List را New می‌کنیم:

    public class ProductsViewModel : BitViewModelBase
    {
        public List<Product> Products { get; set; }

        public async override Task OnNavigatedToAsync(INavigationParameters parameters)
        {
            Products = new List<Product> // getting products from server or sqlite database
            {
                new Product { Id = 1, IsActive = true, Name = "Product1" , Price = 12.2m /* m => decimal */ },
                new Product { Id = 2, IsActive = false, Name = "Product2" , Price = 14 },
                new Product { Id = 3, IsActive = true, Name = "Product3" , Price = 11 },
            };
            await base.OnNavigatedToAsync(parameters);
        }
    }

حال نوبت به دادن یک Template می‌رسد. مثلا فرض کنید می‌خواهیم نام را درون یک Label نمایش دهیم و بر اساس فعال یا غیر فعال بودن Product، یک Checkbox را تغییر داده، تیک بزنیم یا نزنیم و در نهایت نمایش قیمت را در یک Label دیگر خواهیم داشت.

    <sfListView:SfListView ItemsSource="{Binding Products}">
        <sfListView:SfListView.ItemTemplate>
            <DataTemplate>
                <FlexLayout x:DataType="model:Product" Direction="Row">
                    <Label
                        FlexLayout.Basis="50%"
                        Text="{Binding Name}"
                        VerticalTextAlignment="Center" />
                    <bitControls:BitCheckbox InputTransparent="True" FlexLayout.Basis="25%" IsChecked="{Binding IsActive}" />
                    <Label
                        FlexLayout.Basis="25%"
                        Text="{Binding Price}"
                        VerticalTextAlignment="Center" />
                </FlexLayout>
            </DataTemplate>
        </sfListView:SfListView.ItemTemplate>
    </sfListView:SfListView>

همانطور که می‌بینید، در DataTemplate از Flex Layout استفاده شده است. Flex Layout در کنار Grid, Stack, Relative, Absolute و سایر Layout‌‌های Xamarin Forms در پروژه قابلیت استفاده دارد و مزیت‌های خاص خود را دارد.

این Data Template توسط List View، حداکثر سه بار ساخته می‌شود؛ چون View Model در لیست مثال خود، سه Product دارد. خود List View تکنیک‌های Virtualization و Cell Reuse را بدون نیاز به هیچ کد اضافه‌ای هندل می‌کند و Performance خوبی دارد. در View مربوطه یعنی ProductsView.xaml، هر Binding ای (مثل Binding Products) به View Model اشاره می‌کند، اما درون Data Template، هر Binding به Product ای اشاره می‌کند که آن ردیف List View، دارد نمایش‌اش می‌دهد. برای همین x:DataType را روی Flex Layout درون Data Template به Product وصل کرده‌ایم. در این صورت اگر بنویسیم Binding N_ame، به ما خطا داده می‌شود که کلاس Product هیچ Property با نام N_ame ندارد که خطای درستی است.

روی BitCheckbox مقدار InputTransparent را برابر با True داده‌ایم که باعث می‌شود کلیک روی Checkbox عملا در نظر گرفته نشود. این منطقی است، زیرا عوض کردن مقدار Checkbox در این مثال ما ذخیره نمی‌شود و کاربرد نمایشی دارد و فقط باعث گیج شدن کاربر می‌شود.

کنترل BitCheckbox از مجموعه کنترل‌های Bit است که اخیرا با BitDatePicker آن آشنا شده‌اید. برای آشنایی با نحوه افزودن این کنترل‌ها به یک پروژه، به مستندات Bit Framework مراجعه کنید. خود Syncfusion نیز Checkbox دارد.

حال فرض کنید که قرار است دکمه‌ای برای هر ردیف List View داشته باشیم که با زدن روی آن، اطلاعات Product به سرور ارسال شود و جزئیات بیشتری دریافت و در قالب یک Alert نمایش داده شود.  برای این کار، ابتدا به Data Template که Flex Layout است، یک دکمه اضافه می‌کنیم. سپس Command آن دکمه را به View Model بایند می‌کنیم. در آن Command البته احتیاج داریم بدانیم درخواست نمایش جزئیات بیشتر، برای کدام Product داده شده. این مهم با Command Parameter شدنی است.

برای پیاده سازی این مثال، در سمت View Model داریم:

 
public BitDelegateCommand<Product> ShowProductDetailsCommand { get; set; }
public IUserDialogs UserDialogs { get; set; } async Task ShowProductDetails(Product product) { string productDetail = $"Product: {product.Name}'s more info: ..."; // get more info from server. await UserDialogs.AlertAsync(productDetail, "Product Detail"); }

کامند ShowProductDetailCommand یک پارامتر را از جنس Product می‌گیرد و آن Product ای است که روی دکمه آن کلیک شده‌است. با Clone کردن آخرین نسخه XamApp و درخواست نمایش صفحه‌ی Products در App.xaml.cs به صورت زیر و اجرای برنامه، می‌توانید درک بهتری از عملکرد آن داشته باشید:

await NavigationService.NavigateAsync("/Nav/Products", animated: false);

سپس در View مربوطه داریم:

 
...
<Button Command="{Binding ShowProductDetailsCommand}" CommandParameter="{Binding .}" Text="Detail..." /> </FlexLayout> </DataTemplate>

CommandParameter اگر برابر با Binding Id می‌بود، به Command در سمت View Model، بجای کل Product، فقط Id آن ارسال می‌شد. ولی Show Product Detail Command منتظر یک Product کامل است، نه فقط Id آن. با نوشتن 

CommandParameter="{Binding .}"

کل Product با کلیک روی دکمه به Command ارسال می‌شود.

اکنون اگر پروژه را Build کنید، خطایی را از x:DataType خواهید گرفت که منطقی است. اگر Binding Name و Binding Price دو Property با نام‌های Name و Price را از کلاس Product جستجو می‌کنند، پس قاعدتا ShowProductDetailCommand نیز در همان کلاس مدل، یعنی Product جستجو می‌شود! ولی می‌دانیم که این Command در View Model ما یعنی ProductsViewModel است. برای حل این مشکل، به جای Binding از bit:ViewModelBinding استفاده می‌کنیم:

Command="{bit:ViewModelBinding ShowProductDetailsCommand}"

در این صورت، بجای جستجو کردن ShowProductDetailCommand در کلاس Product، این را در ProductsViewModel جستجو می‌کند که منجر به خروجی درست می‌شود.

این List View دارای امکاناتی چون Infinite loading، Pull to refresh و Grouping-Sorting-Filtering و ... است که می‌توانید از روی مستندات خوب Syncfusion، آنها را راه اندازی کنید و اگر به مشکلی برخوردید نیز اینجا بپرسید. همچنین نگاهی به لیست 129 کنترل دیگر بیاندازید و ببینید که در برنامه‌های خود از کدام یک از آنها می‌توانید استفاده کنید.

اشتراک‌ها
NET. چه چیزی است؟ پلتفرم یا فریم ورک؟

You'll often hear the terms framework and platform used interchangeably. This can be very confusing. You'll hear that .NET Core is a platform. Then you'll read that .NET Core is cross-platform. Next, you'll learn that .NET Core is a framework. And it doesn't help that framework is part of the name of the original full .NET Framework.

In this post, I explain the difference between frameworks and platforms and explain why sometimes you'll see .NET being referred to as a framework and other times see it referred to as a platform. 

NET. چه چیزی است؟ پلتفرم یا فریم ورک؟