Form -> 継承
Visual C#: 16.2.5(2019C)
フォームの継承は、めんどいルールがあった気がする。
勉強したときに、メモし忘れたらしい。
とりあえず、久しぶりにフォームを継承してみて
ルールを忘れていたせいで、エライことになった。
強制終了 -> フォームの継承
継承ルールを再度勉強しないと。。。
フォームの継承は、めんどいルールがあった気がする。
勉強したときに、メモし忘れたらしい。
とりあえず、久しぶりにフォームを継承してみて
ルールを忘れていたせいで、エライことになった。
強制終了 -> フォームの継承
継承ルールを再度勉強しないと。。。
Language INtegrated Query(統合言語クエリー)。
本日勉強を始めたばかりなので、
これから!
とにかく、SQL 専用なわけではない。
LINQは、アクセスするデータの種類に応じてLINQ to Objects、LINQ to SQL、LINQ to XML、LINQ to DataSetなどに分類できます
これらはLINQプロバイダーと呼ばれます。
プロバイダーはアクセスするデータソースに応じて動的に切り替わりますので、
アプリケーション開発者がプロバイダーを意識する必要はほとんどありません。BuildINSIDER:LINQとは?[C#](2014-11-11)
おー よかった。
いっぱい出てきてわけがわからなくなってきていた。
クエリー式とメソッド式がある。
Qiita:LINQチートシート的なもの(2017-12-08)
→ありがたや~。ちゃんと読みましょう!
netplanetes log:BindingSource.DataSource に LINQ to Entity の ObjectQuery を指定してはいけない(2009-10-10)
→まだ意味がよくわからないけど、試行錯誤の途中で、この問題に直面したような気がする。。。
MSDN:コントロールへのオブジェクトのバインド (Entity Framework)
EntityFramwork の実践 をする中で
Where 部の条件分岐をする必要が出た。
その際、参考サイトの手法のまま、メソッド式 LING を利用しており
条件分岐の方法が分からなくて、あれこれ探し回った。
参考サイトの記述は下記の通り。
この記事用に不要部を削除して進行。
var user02 = db.Users.Where((u) => u.Name == "User02").Include("KptBoards").First();
var user02 = db.Users.Where((u) => u.Name == "User02").First();
現状は User02 を取得することになっているけど
条件によって、User02, User03 を分けたい。
実際の稼働確認は、他のコードで行ったので
この記事内のコードの稼働確認は行っていない。
三項演算子による条件分岐は
式形式では成功。
ステートメント形式では失敗。
成功。 😎
bool flg = true;
var user02 = db.Users.Where((u) => (flg) ? u.Name == "User02" : u.Name == "User03").First();
失敗。 😥
bool flg = true;
var user02 = db.Users.Where((u) => { (flg) ? u.Name == "User02" : u.Name == "User03"; }).First();
プログラミング C# – 翔ソフトウェア (Sho’s):[C#][ラムダ式][式木] Expression として扱えるラムダ式と扱えないラムダ式
まずはメソッドを利用する方法を体験するために
条件分岐なしパターン。
var user02 = db.Users.Where(IsTarget).First();
private bool IsTarget(User u)
{
return u.Name == "User02";
}
こういう書き方で、引数 u は自動でメソッドへ送られる。
上記のまま、条件を足してみた。
bool flg = true;
var user02 = db.Users.Where(IsTarget(flg)).First();
private bool IsTarget(User u, bool flg)
{
if (flg) return u.Name == "User03";
return u.Name == "User02";
}
こういう書き方はできないらしい。
下記のように記述したら上手くいった。
bool flg = true;
var user02 = db.Users.Where((u) => IsTarget(u, flg)).First();
private bool IsTarget(User u, bool flg)
{
if (flg) return u.Name == "User03";
return u.Name == "User02";
}
デリゲートも含めて、理屈を理解できていないので
まだまだ挙動を掴めない。
しばらくは勉強ですね。。。
話には聞いていた「ラムダ式」。
無名関数のことだったのね~。
MSDN?:ラムダ式 (C# プログラミング ガイド)
Wikipedia:C#の無名関数
といいつつ、無名関数のことも、まだ良く理解できていない。。。
いつもの如く、習うより慣れろ!で頑張るぞ~!
ラムダ式とはメソッド定義を式として扱える機能のこと
Qiita:関数型プログラミングって何、ラムダってなんだよ ラムダ式(2016-10-23)
本日、初対面の「ラムダ式」の情報に目を通してきたけど
この一言で、それなりにまとまった気がする。
ありがとうございます。
私なりに解釈すると、今まで1つ1つメソッドを実装してきたけど
ラムダ式なら、わざわざメソッドとして切り出さなくても、式の中に入れ込めるよ!
ってことかしらね~。
直感では「三項演算子」とイメージが似ていると思う。
// if で真面目に書く
if (a) { return b; }
else { return c; }
// 三項演算子を用いる
(a) ? b : c;
// 真面目にメソッドを実装する
string result = GetResult(value);
private string GetResult(string value)
{
return "result : " + value;
}
// ラムダ式で書く
string result = (value) => "result : " + value;
// 式形式
(引数) => 処理// ステートメント形式
(引数) => {処理}// 非同期ラムダ
MSDN?:ラムダ式 (C# プログラミング ガイド) 参照// 標準クエリ演算子でのラムダ
MSDN?:ラムダ式 (C# プログラミング ガイド) 参照
右辺は、式ツリーとなるらしい。
(value) => "result : " + value
右辺の行末 ;(セミコロン)は不要
もちろん、行全体の行末 ;(セミコロン)は必要
右辺は、デリゲートとなるらしい。
(value) => { return "result : " + value; }
value => "result : " + value
() => "result : OK"
このときの () は省略できない
(a, b) => "result : " + a + ", " + b
ラムダ式では、型推論によって、型を解決できるので
型の指定は不要だけど、指定することも可能。
(string value) => "result : " + value
MSDN?:ラムダ式 (C# プログラミング ガイド)
=> を「ラムダ演算子」という。
ザックリ理解するとこんな感じ?
正確な情報は下記の通り。
MSDN?:ラムダ式 (C# プログラミング ガイド)
Qiita:はじめての LINQ(2018-01-16)
→LINQ 全体だけど、ひとまずこちらへ。勉強!
Qiita:関数型プログラミングって何、ラムダってなんだよ ラムダ式とスコープ(2016-10-23)
Qiita:C# 今更ですが、ラムダ式(2017-10-27)
→何度も読み返して勉強しましょう!
Qiita:【LINQの前に】ラムダ式?デリゲート?Func
→何度も読み返して勉強しましょう!
Qiita:C#のExpressionで動的コード生成(2017-12-19)
→式形式(式木、式ツリー)の勉強に!
Qiita:LINQとラムダ式ってなにができるの?(2015-10-04)
→こちらのおかげで、メソッドへ引数を渡す方法に気がついた
@IT:C#ラムダ式 基礎文法最速マスター(2010-03-09)
→ここも分かりやすかった
iPentec:デリゲートとラムダ式の書き換え =>演算子の利用 (C#プログラミング)
→デリゲートと比較しながら勉強するのによさそう
MSDN:DataGridView コントロール (Windows フォーム)
MSDN:DataGridView クラス
データを一覧表示するコントロール。
MSDN:DataGridView クラス
一覧はこちらにあるので、逆引きで!
MSDN:AlternatingRowsDefaultCellStyle
RowHeadersVisible
@IT:DateTimePickerコントロールでDBNullを扱うには?[C#、VB](2008-01-31)
MSDN:DateTimePicker コントロール (Windows フォーム)
MSDN:DateTimePicker クラス
DateTimePicker を使いたい。
だけど、null のときに日付が入ってしまうと
空欄にしておきたいユーザが、誤入力をしてしまう。
むぅ。
Google 先生に聞いてみると、色々とあるみたいだけど
ほとんどの情報が古い。。。
何で改善されないんだろう。
どこかにも書いてあったけど、DateTime 型を利用するのに
null は普通に使うと思うんだけどな~。
私の設計が悪いのかしらね。
それでも、DateTimePicker が null を許容できないことは
当時?みなさんが試行錯誤されたようで、下記のような記事を見つけた。
codeguru:Yet Another Nullable DateTimePicker Control(2005-04-25)
CodeZine:Nullを許容するDateTimePickerコントロール(2005-05-13、日本語訳記事)
現時点では、よい方針を思いつかないので
DbDateTimePicker を使ってみた。
@IT:DateTimePickerコントロールでDBNullを扱うには?[C#、VB](2008-01-31)
おおお、奇しくも後1週間で10周年w
カスタム コントロールを追加 して
自動生成ソースに、参考サイトのソースを、ちみっと調整してコピペ。
public partial class DbDateTimePicker : DateTimePicker
{
public DbDateTimePicker()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
[Bindable(true), Browsable(false)]
public new object Value
{
get
{
if (base.Checked)
return base.Value;
else
return DBNull.Value;
}
set
{
try
{
if (Convert.IsDBNull(value))
{
base.Checked = false;
}
else
{
base.Value = Convert.ToDateTime(value);
base.Checked = true;
}
}
catch (Exception ex)
{
base.Value = Convert.ToDateTime(value);
base.Checked = true;
}
}
}
}
アプリ側にコントロールを追加 して
フォーム上へ配置。
dbdtpDate
コントロールのプロパティから
ShowCheckBox を True
php フレームワークみたいに、
命名規則を守って記述すれば
自動で外部キー設定をしてもらえる。
public class Municipality
{
[Key]
[MaxLength(6)]
public string Code { get; set; }
[MaxLength(5)]
public string PrefectureCode { get; set; }
public Prefecture Prefecture { get; set; } // 追加分
}
こちらは、参考サイトのものを一部頂戴してきたソース。
命名規則からハズレた場合には
手動で外部キーを設定してやる。
public class Municipality
{
[Key]
[MaxLength(6)]
public string Code { get; set; }
[MaxLength(5)]
public string PCD { get; set; } // これを変更
[ForeignKey("PCD")]
public Prefecture Prefecture { get; set; } // ナビゲーションプロパティ
}
こちらも参考サイトのものを一部頂戴。
おそらく、この先で Eager-loding, Lazy-loading の勉強をする必要があると思う。
外部キー
参考スライドの通り
[Key]
[Column(Order=1)]
public string Value1 { get; set; }
[Key]
[Column(Order=2)]
public string Value2 { get; set; }
としたところ、Add-Migration で、下記エラーが出た。
そこで、参考サイトのように、Entity でのキー設定をやめ
DbContext 側で設定したところ、設定できた。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasKey(paidHoliday => new { HogeEntity.Value1, HogeEntity.Value2 });
}
Qiita:[EntityFrameworkCore]CodeFirstでテーブルに複合主キーを付ける(2017-08-31)
→参考スライドの [Column(Order=1)] では設定できなかったので、大変助かりました
上記のように設定しておけば、Join しなくても
オブジェクトチェーンで取得可能。
Municipality.Code
Municipality.Prefecture.Code
インクリメンタルなカイハツにっき
実践 Entity Framework ~ 外部キーを設定する(2015-07-28)
実践 Entity Framework ~ ForeignKey 属性(2015-08-03)
お試し で大分理解できたので
実際に挑戦!
お試し との変更点は
メインをフォームアプリにしたこと。
フォームアプリプロジェクトへ、NuGet パッケージ管理から、下記をインストール。
上記3つのプロジェクトについて、何をするかによって
スタートアッププロジェクトを切り替えないければならない。
Add-Migration Initial
More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for PowerShell commands and the '--context' parameter for dotnet commands.
DbContext クラスが複数あったため。
対象 DbContext クラスを指定してコマンド実行。
Add-Migration Initial -Context MyAppSystem.EmployeeModel
To undo this action, use Remove-Migration.
Update-Database -Context MyAppSystem.EmployeeModel
Applying migration '20180121111141_Initial'.
Done.
Add-Migration Initial -Context MyAppSystem.EmployeeModel
Could not load assembly 'MyApp'. Ensure it is referenced by the startup project 'MyAppSystem'.
パッケージ マネージャー コンソール上部にある
「既定のプロジェクト」が、MyApp になっていた。
「既定のプロジェクト」を、MyAppSystem に変更。
今回は、フォームロード時に走らせる処理として Main_Load メソッドとした。
Main の部分は、フォームクラス名を入れるのが通例らしい。
フォームプロパティのイベント一覧(雷マーク)において
Load => Main_Load
と設定するだけ。
Entity の中から、特定のプロパティを取得する=表示カラムを絞る。
このことを「射影」というらしい。
var arrayEmployees = db.Employees
.Select(record => new {
record.EmployeeCode,
Name = record.FamilyName + " " + record.FirstName
})
.ToArray();
という風に、計算や加工も含めて自由に取得できる。
この部分の表記方法を勉強中。
LINQ の考え方としては「配列の要素」を指していると思う。
foreach (var value in array) の value に当たる感じ?
今回は、DB から抽出したレコード群が要素なので
record としてみたけど、何でもよさそう。
データの個数。
db.Employees.Count()
上記例に合わせると、こうなる。
dgvEmployees.Columns[nameof(Employee.EmployeeCode)].HeaderText = "従業員コード";
dgvEmployees.Columns[nameof(Name)].HeaderText = "氏名";
ここで面白いのが
Employee.EmployeeCode を EmployeeCode とするとエラー。
record.EmployeeCode としてもエラー。
Name は、何も付けなくてもエラーにならないどころか、想定通りに動く。
まだまだ意味がわかっていない。
Qiita:Entity Framework6で単純なデータ表示フォームを作成(2015-09-08)
→DataGridView へのデータの登録の仕方。DataGridView のカラム名の変更の仕方
Keibalight プログラミングを淡々と:【LINQ】要素の個数を取得するには(Count集計演算子)(2011-07-19)
→LINQ による、データ個数の数え方
今ひとつピンとこないので
勉強のため、テストプロジェクトを作成。
EntityFramework なるものを見つけて
ぜひ挑戦したいと思った。
ただ、慣れない VS 環境であることもあり
なかなかピンとこない。
そこで、参考サイトをそのまま実践してみることにした。
SlideShare:「Entity Framework Coreを使ってみる」 公開用(2017-03-07)
プロジェクトコンテキストメニューから [NuGet パッケージの管理]
Microsoft.EntityframeworkCore で検索
Microsoft.EntityframeworkCore.Sqlite 2.0.1
Microsoft.EntityframeworkCore.Tools 2.0.1
ソリューションのコンテキストメニューから [追加]-[新しいプロジェクト] 後は前述同様に KptBoardSystemTest プロジェクトを作成。
前述同様に、下記を設定。
Microsoft.EntityframeworkCore 2.0.1
xunit 2.3.1
xunit.runner.visualstudio 2.3.1
Moq 4.8.1
P.12 User
P.13 KptBoardModel
Enable-Migrations
Enable-Migrations is obsolete. Use Add-Migration to start using Migrations.
Add-Migration setp00
To undo this action, use Remove-Migration.
こんな感じで2ファイルが自動生成された。
KptBoardSystem
┗ Migrations
┣ 20180120074120_setp00.cs
┗ KptBoardModelModelSnapshot.cs
Update-Database
Applying migration '20180120074120_setp00'.
Done.
参考サイト P.15 のように処理がズラズラ並ぶのではなく
とても簡素なリアクションでしたw
参考サイトには「ソリューション直下に「kpt.db」が作成される」とあったけど
実際には、ソリューションの2つ上に作成された。
後述の試行錯誤に見られた、テストとの階層の差分があるということは
コマンドを打つ際に、階層を設定するべきなのではないかと思うけど
現在は手法不明。
そこで、
のパスを下記のように変更したところ、ソリューション直下に作成された。
- var connectionString = new SqliteConnectionStringBuilder { DataSource = "../../../kpt.db" }.ToString();
+ var connectionString = new SqliteConnectionStringBuilder { DataSource = "../kpt.db" }.ToString();
この件には、大きな落とし穴が。。。
詳細は、後述の「試行錯誤」コーナーにて。
コマンドを打つ際に、パッケージ マネージャー コンソールにおいて
「既定のプロジェクト」で何を選択しているかでファイル出力場所が変わる。
“kpt.db” というパスの場合は
プロジェクト直下へ生成されるので
KptBoardSystem を選択していれば、
KptBoardSystemTest を選択していれば、
となる。
この場合、テストではファイルが見つからないエラーになってしまうので
「既定のプロジェクト」は注意。
後述の如く、コマンドと実行でファイルパスの意味合いが変わるので
コマンドで生成された DB ファイルを手動で配置換えをした。
テストと本番で DB を分けることも考え
ソリューション直下ではなく、プロジェクト直下としてみる。
つまり、最終的な配置とファイルパスの指定は下記の通り。
var connectionString = new SqliteConnectionStringBuilder { DataSource = "../../kpt.db" }.ToString();
このようなやり方にすることで
コマンドを打つ度に
ファイルの移動が必要。
P.18
KptBoardSystemTest プロジェクト内「参照」のコンテキストメニュー [参照の追加]
「参照マネージャー」
左ペイン [プロジェクト]-[ソリューション]
中央ペイン [KptBoardSystem] にチェック
[OK]
P.19 KptBoardModelTest
using Xunit;
namespace KptBoardSystem.Test
{
public class KptBoardModelTest
{
[Fact]
public void TestInsertUser()
{
using (var db = new KptBoardModel())
{
var user = new User
{
Name = "User01"
};
db.Add(user);
db.SaveChanges();
}
}
}
}
私の記述ミスのせいで、
var kptBoard = db.KptBoards.Where(b => b.Problem.Contains("続ける")).First();
こちらが空になってしまった。
その際、下記のエラーが出た。
まだ使い方はよくわからない。
P.34 では、u が括弧書きだったのに
今回は括弧がつかない理由がわからない。
var user02 = db.Users.Where((u) => u.Name == "User02").Include("KptBoards").First();
var kptBoard = db.KptBoards.Where(b => b.Problem.Contains("続ける")).First();
LINQ を勉強すべし。
テスト初回実行時、下記のエラーが出た。
Google 先生に質問したところ、どうやら下記パッケージが不足していることらしい。
テストプロジェクトへインストール。
Install-Package SQLitePCLRaw.bundle_e_sqlite3 -Version 1.1.9
Install-Package SQLitePCLRaw.bundle_sqlcipher -Version 1.1.9
Install-Package SQLitePCL.bundle_green -Version 0.9.3
NuGet パッケージ管理からインストールしても OK だと思う。
stackoverflow:Cannot run SQLite.net PCL in ASP.NET MVC(2017-02-09)
上記エラーが取れてホッとしつつテストを行うと
次は下記エラーが出た。
Users テーブルが見つからないってさ。。。
kpt.db の中には、確かに Users テーブルがある。
上で、DB ファイルへのパスを変えたからかもしれないと思い
パスを戻すと、エラーが出ないときもあるけど、確実ではないし
値は書き込まれない。
そもそも DB 接続に失敗しているのかと思って
ファイルパスを存在しないパスにしてみたら
エラー内容が下記の通り変わったので、接続には成功しているみたい。
途方に暮れて、ソリューションディレクトリをあちこち見ていたら
想定外の場所に kpt.db ファイルが!!!
コマンドで作成した kpt.db のファイルパスと
テストコードが参照する kpt.db のファイルパスが
異なることが原因だった。
と言っても、何かがおかしいので
いずれわかる日が来ると信じたい。
ともかく、下記のような検証結果だった。
GrandMother
┣ Mother
┃ ┣ KptBoardSystem
┃ ┃ ┣ KptBoardSystem
┃ ┃ ┣ KptBoardSystemTest
┃ ┃ ┃ ┣ bin
┃ ┃ ┃ ┃ ┣ Debug
┃ ┃ ┃ ┃ ┃ ┗ kpt.db // テスト "kpt.db"
┃ ┃ ┃ ┃ ┣ Release
┃ ┃ ┃ ┃ ┗ kpt.db // テスト "../kpt.db"
┃ ┃ ┃ ┗ kpt.db // コマンド "kpt.db"、テスト "../../kpt.db"
┃ ┃ ┗ kpt.db // コマンド "../kpt.db"、テスト "../../../kpt.db"
┃ ┗ kpt.db // コマンド "../../kpt.db"
┗ kpt.db // コマンド "../../../kpt.db"
つまり
コマンドは、プロジェクトディレクトリがルート。
テスト(実行)は、アセンブリ(.dll)本体のある場所がルート?
curl -sS https://getcomposer.org/installer | php
All settings correct for using Composer
Downloading...
Composer (version 1.6.2) successfully installed to: /root/composer.phar
Use it: php composer.phar
php composer.phar
Do not run Composer as root/super user! See https://getcomposer.org/root for details
______
/ ____/___ ____ ___ ____ ____ ________ _____
/ / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
/_/
Composer version 1.6.2 2018-01-05 15:28:41
Usage:
command [options] [arguments]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
--profile Display timing and memory usage information
--no-plugins Whether to disable plugins.
-d, --working-dir=WORKING-DIR If specified, use the given directory as working directory.
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
about Shows the short information about Composer.
archive Creates an archive of this composer package.
browse Opens the package's repository URL or homepage in your browser.
check-platform-reqs Check that platform requirements are satisfied.
clear-cache Clears composer's internal package cache.
clearcache Clears composer's internal package cache.
config Sets config options.
create-project Creates new project from a package into given directory.
depends Shows which packages cause the given package to be installed.
diagnose Diagnoses the system to identify common errors.
dump-autoload Dumps the autoloader.
dumpautoload Dumps the autoloader.
exec Executes a vendored binary/script.
global Allows running commands in the global composer dir ($COMPOSER_HOME).
help Displays help for a command
home Opens the package's repository URL or homepage in your browser.
info Shows information about packages.
init Creates a basic composer.json file in current directory.
install Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
licenses Shows information about licenses of dependencies.
list Lists commands
outdated Shows a list of installed packages that have updates available, including their latest version.
prohibits Shows which packages prevent the given package from being installed.
remove Removes a package from the require or require-dev.
require Adds required packages to your composer.json and installs them.
run-script Runs the scripts defined in composer.json.
search Searches for packages.
self-update Updates composer.phar to the latest version.
selfupdate Updates composer.phar to the latest version.
show Shows information about packages.
status Shows a list of locally modified packages.
suggests Shows package suggestions.
update Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
upgrade Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
validate Validates a composer.json and composer.lock.
why Shows which packages cause the given package to be installed.
why-not Shows which packages prevent the given package from being installed.
mv composer.phar /usr/local/bin/composer
これで、直接 composer で利用できる。
念の為、アップデート。
composer self-update
実は上記インストール時に、下記2行目の警告が出ていた。
curl -sS https://getcomposer.org/installer | php
PHP Warning: Module 'intl' already loaded in Unknown on line 0
All settings correct for using Composer
Downloading...
Composer (version 1.6.2) successfully installed to: /root/composer.phar
Use it: php composer.phar
これは、php.ini で extension=intl.so をコメントアウトすることで消えたけど
CakePHP3 をインストールする際に intl は必要なはずなので、後ほど試す。
実は上記起動時に、下記2行目の警告が出ていた。
php composer.phar
Do not run Composer as root/super user! See https://getcomposer.org/root for details
あら、Composer って、root で利用してはいけないのね~。
実行ファイルを移動させて、一般ユーザに戻って利用したら
上記警告は出なくなった。
ちなみに、インストールを root でしたせいか
実行ファイルを移動しておかないと、php composer.phar では、実行できず
php composer.phar
Could not open input file: composer.phar
このように怒られた。。。
WinRoad徒然草:さくらのVPSサーバーにLaravelのインストール(2015-03-23)