星期四, 7月 02, 2020

[VS] 視覺化檢視 - json

練習 [X.Form] FlexLayout 下中斷點時,發現原來 VS 就有把 json 視覺化功能

中斷點內,點選放大鏡,就可以看見 [json 視覺化檢視]

json 視覺化檢視-1

視覺化後的 json 資料

json 視覺化檢視-2

星期三, 7月 01, 2020

[X.Form] FlexLayout

根據 Xamarin.Forms FlexLayout 範例內的 PhotoWrap 來練習,該範例內示範的 url 練習時還是可以活著的,省去找圖片困惱

Xaml 配置

FlexLayout 使用屬性簡易說明
  • Direction="Row":由左往右排列
  • Wrap="Wrap":當擺不下時,往下折行
  • JustifyContent="SpaceAround":延排列方式各物件兩側各平均留邊
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="FlexLayoutDemo.PhotoWrapping">
    <ContentPage.Content>
        <Grid>
            <ScrollView Orientation="Vertical">
                <FlexLayout x:Name="flexLayout"
                        Direction="Row"
                        Wrap="Wrap"
                        JustifyContent="SpaceAround" />
            </ScrollView>

            <ActivityIndicator x:Name="activityIndicator"
                           IsRunning="True"
                           VerticalOptions="Center" />
        </Grid>
    </ContentPage.Content>
</ContentPage>
C# Code
namespace FlexLayoutDemo
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PhotoWrapping : ContentPage
    {
        public PhotoWrapping()
        {
            InitializeComponent();

            ImageFillAsync();
        }

        private async void ImageFillAsync()
        {
            var files = await RecordParseAsync();

            foreach (string filepath in files)
            {
                Image image = new Image
                {
                    Source = ImageSource.FromUri(new Uri(filepath))
                };
                flexLayout.Children.Add(image);
            }

            activityIndicator.IsRunning = false;
            activityIndicator.IsVisible = false;
        }

        private async Task<List<string>> RecordParseAsync()
        {
            string rawJson = await DownloadDataAsync();
            JObject jsonObject = JObject.Parse(rawJson);
            var records = jsonObject["photos"]?.ToString();
            return JsonConvert.DeserializeObject<List<string>>(records);
        }

        private async Task<string> DownloadDataAsync()
        {
            string json = string.Empty;

            string url = "https://raw.githubusercontent.com/xamarin/docs-archive/master/Images/stock/small/stock.json";
            using (HttpClient http = new HttpClient())
            {
                json = await http.GetStringAsync(url);
            }
            return json;
        }
    }
}
拉到最下方觀察到 JustifyContent="SpaceAround" 效果

[X.Form] FlexLayout

星期二, 6月 23, 2020

[SQL] Indexed View

根據 建立索引檢視(Indexed View)來提高查詢效能 內的 TSQL 範例來學習,利用 AdventrueWorks2017 的 Sales.SalesOrderHeader 和 Sales.SalesOrderDetail 來跑彙總統計

未建立 Indexed View 前的 TSQL 執行計畫
-- 建立 IX_SalesOrderDetail_ProductID,讓執行計畫單純一些
CREATE INDEX IX_SalesOrderDetail_ProductID ON Sales.SalesOrderDetail (ProductID)
INCLUDE (OrderQty, UnitPrice, UnitPriceDiscount)
WITH (DROP_EXISTING = ON)

SELECT 
    o.OrderDate , 
    od.ProductID ,
    SUM(od.UnitPrice * od.OrderQty * (1.00 - od.UnitPriceDiscount)) AS Revenue
FROM Sales.SalesOrderHeader AS o 
    JOIN Sales.SalesOrderDetail AS od ON o.SalesOrderID = od.SalesOrderID
WHERE od.ProductID BETWEEN 700 and 800
    AND o.OrderDate >= '20130501'
GROUP BY o.OrderDate, od.ProductID
ORDER BY Revenue DESC;
GO
[SQL] Indexed View-1

星期一, 6月 22, 2020

[SQL] 執行計畫成本

討論時常提到 SQL Server 會選擇執行計畫成本較低的來跑,但其實會影響因素很多,本篇筆記以 [資料量] 和 [Key Lookup] 兩者來驗證,抓取過多資料和非叢集索引無法滿足所需資料,而必須透過 key lookup 抓取,兩者都是觀察執行計畫重點

在 AdvenureWork Sales.SalesOrderHeader Table 建立 IX_SalesOrderHeader_OrderDate 來記錄
use AdventureWorks2017
go 

CREATE INDEX IX_SalesOrderHeader_OrderDate ON Sales.SalesOrderHeader (OrderDate)
WITH (DROP_EXISTING = ON);
case1:以單日 (20130701) 資料來觀察執行計畫
SELECT 
    SalesOrderNumber , 
    OrderDate ,
    CustomerID ,
    SubTotal
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '20130701' AND '20130701'
IX_SalesOrderHeader_OrderDate Index Seek 並輸出 43 筆資料後,利用 key lookup 取回 CustomerID 和 SubTotal 資料

[SQL] 執行計畫成本-1

case2:以單月 (201307) 資料來觀察執行計畫
SELECT 
    SalesOrderNumber , 
    OrderDate ,
    CustomerID ,
    SubTotal
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '20130701' AND '20130731'
PK_SalesOrderHeader_SalesOrderID Index Scan 並輸出 31,465 筆資料後,最後透過 Filter 來篩選資料至 1,740 筆

[SQL] 執行計畫成本-2

當日期區間拉長 (單日 => 單月,資料量增加) 時,SQL Server 選擇執行計畫成本較較低的 Clustered Index Scan (PK_SalesOrderHeader_SalesOrderID) + Filter 來跑

接下來透過 case3:以單月 (201307) 並強制跑 IX_SalesOrderHeader_OrderDate 來驗證 SQL Server 會選擇成本較低的執行計畫來跑
SELECT 
    SalesOrderNumber , 
    OrderDate ,
    CustomerID ,
    SubTotal
FROM Sales.SalesOrderHeader WITH (INDEX(IX_SalesOrderHeader_OrderDate))
WHERE OrderDate BETWEEN '20130701' AND '20130731'
因為有 Index Hint,所以用 IX_SalesOrderHeader_OrderDate 並輸出 1,740 筆資料後,利用 key lookup 取回 CustomerID 和 SubTotal 資料

[SQL] 執行計畫成本-3

把 case2 和 case3 TSQL 放在一起跑,就可以很明顯比較出執行計畫成本差異

[SQL] 執行計畫成本-4

星期六, 6月 20, 2020

[X.Form] ResizetizerNT

Cross-platform Images Simplified with ResizetizerNT 介紹才知道的開源套件,基本上就是把 Image 轉為各平台定義格式,設定和使用都很簡易

從 nuget 上安裝 ResizetizerNT

Resizetizer NT-1

Share Project 內放置一張圖片,文件上是說 SVG 或 PNG 圖片都可以,但影片建議是用 SVG,並把該圖片的 Build Action 設定為 SharedImage

Resizetizer NT-2

Project Property 內設定圖片 BaseSize,基本上這就是最小 Size
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <SharedImage Include="Image\Xamarin.svg" BaseSize="60,60"/>
  </ItemGroup>
</Project>
對 project 進行 build 之後,各平台內就可以發現有 Resizetizer 資料夾,資料夾內可以找到不同 Size 的 png 檔案

Resizetizer NT-4

Resizetizer NT-5

寫個簡單 xaml 並把 app 部屬至模擬器來看看效果囉
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="ResizetizerDemo.MainPage">

    <StackLayout>
        <Label Text="Welcome to Resizetizer NT!" 
           HorizontalOptions="Center"
           VerticalOptions="Center" 
           FontSize="Large"
           FontAttributes="Bold"/>
        <Image Source="Xamarin.png" 
               WidthRequest="360" 
               HeightRequest="360" 
               VerticalOptions="CenterAndExpand" />
    </StackLayout>

</ContentPage>
Resizetizer NT-7