20210726のC#に関する記事は4件です。

C#における、LINQと配列操作

LINQとは、コレクションの操作をするために用意された機能のことである。 ちなみに、LINQとは「Language Integrated Query」の略。 LINQを使う LINQを使うには、名前空間で using System.Ling; のようにusingディレクティブで指定する。 なお、以降使用するリストを var arrayData1 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var arrayData2 = new List<int>() { 2, 3, 1, 4, 9, 6, 5, 10, 7, 8 }; var arrayData3 = = new List<Pokemon>() { new Pokemon("リザードン", new string[]{ "ほのお", "ひこう" }, true }), new Pokemon("ピカチュウ", new string[]{ "でんき" }, true }, new Pokemon("メタグロス", new string[]{ "はがね", "エスパー" }, false }, new Pokemon("ゲッコウガ", new string[]{ "みず", "あく" }, true }, new Pokemon("ドラパルト", new string[]{ "ドラゴン", "ゴースト" }, false }, new Pokemon( "エルレイド", new string[]{ "エスパー", "かくとう" }, false }, new Pokemon("ミュウツー", new string[]{ "エスパー" }, true }, new Pokemon("パルキア", new string[]{ "みず", "ドラゴン" }, true }, new Pokemon("マリルリ", new string[]{ "みず", "フェアリー" }, true }, new Pokemon("ゲンガー", new string[]{ "ゴースト", "どく" }, false }, new Pokemon("ボルケニオン", new string[]{ "ほのお", "みず" }, true }, }; とする。 また、 Pokemonクラス class Pokemon { public string Name { get; set; } public string[] Types { get; set; } public bool IsGet { get; set; } public Pokemon(string name, string[] types, bool isGet) { Name = name; Types = types; IsGet = isGet; } } とする。 LINQで使えるメソッド LINQでできるコレクションを操作するメソッドは以下の通り Where Whereメソッドは、条件に一致した要素を取得する。 (例1)arrayData1から5以上の数字だけを表示したい時 var arrayDataByWhere = arrayData1.Where(el => el > 4); foreach(var item in arrayDataByWhere) { Console.WriteLine(item); } 出力結果 5 6 7 8 9 10 (例2)arrayData3の各要素のNameが4文字のデータを表示したい時 var PokemonData = arrayData3.Where(el => el.Name.Length == 4); foreach(var item in PokemonData) { Console.WriteLine(item.Name); } 出力結果 パルキア マリルリ ゲンガー Select Selectメソッドは、コレクションの各要素を別の値に変換する。 (例)arrayDataの各要素に2をかけた配列を新たに作りたい時 var arrayDataBySelect = arrayData1.Select(el => el * 2); foreach(var item in arrayDataBySelect) { Console.WriteLine(item); } 出力結果 2 4 6 8 10 12 14 16 18 20 OrderBy OrderByメソッドは、昇順に並び替えるメソッド。 (例)arrayData2を照準に並び替えたい時 var arrayDataBySelect = arrayData2.OrderBy(el => el); foreach(var item in arrayDataBySelect) { Console.WriteLine(item); } 出力結果 1 2 3 4 5 6 7 8 9 10 OrderByDecending OrderByメソッドは、降順に並び替えるメソッド。 (例1)arrayData2を降順に並び替えたい時 var arrayDataBySelect = arrayData2.OrderBy(el => el); foreach(var item in arrayDataBySelect) { Console.WriteLine(item); } 出力結果 10 9 8 7 6 5 4 3 2 1 (例2)arrayData3の要素の名前がカナ順になるように並び替えたい時 var arrayDataBySelect = arrayData3.OrderBy(el => el.Name); foreach(var item in arrayDataBySelect) { Console.WriteLine(item.Name); } 出力結果 エルレイド ゲッコウガ ゲンガー ドラパルト パルキア ピカチュウ ボルケニオン マリルリ ミュウツー メタグロス リザードン Enumerable Repeat 要素が1というint型の値を何個も持つコレクションもしくはListを作りたい場合などに使用する。 (例1)10個の1をListを作成する時 var data = Enumerable.Repeat(1, 10).ToList(); foreach (int i in data) { Console.WriteLine(i); } 出力結果 1 1 1 1 1 1 1 1 1 1 (例2)5個の1を配列で作成する時 var data = Enumerable.Repeat(1, 5).ToArray(); foreach (int i in data) { Console.WriteLine(i); } 出力結果 1 1 1 1 1 空の配列を定義して、forやforeachのループでやるより遥かに楽である。 Range コレクションに1,2,3...nと連続した値をセットしたい場合に使用する。 (例) var data11 = Enumerable.Range(1, 20).ToArray(); foreach (int i in data11) { Console.WriteLine(i); } Average コレクションの平均値を求める。 ちなみに、 ・要素がint型の数値だけがまとまったものの平均値を求める(A) ・オブジェクトの要素の数値だけを参照して平均値を求める(B) で使い方が異なるので注意。 (A)の求め方 var list = new List<int> { 1,2,3,4,5 }; Console.WriteLine(list.Average()); (B)の求め方の場合、 Personクラス public class Person { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public Person(string fn, string ln, int age) { FirstName = fn; LastName = ln; Age = age; } } があったとする。 (B)の求め方 List<Person> list2 = new List<Person>() { new Person("ジョルノ", "ジョバーナ", 15), new Person("ナルト", "うずまき", 17), new Person("一護", "黒崎", 17), new Person("義勇", "富岡", 21), new Person("月", "夜神", 20), new Person("リョーマ", "越前", 12), new Person("一馬", "桐生", 53), new Person("クラウド", "ストライフ", 24), new Person("葉", "麻倉", 13), new Person("威", "浅倉", 25), }; var ave = list2.Average(el => el.Age); Console.WriteLine(ave); 出力結果 21.7 この場合はラムダ式を使う。 Sum コレクションの合計を求める。 Averageと同じような記法で使用する (A)の求め方 list.Sum(); (B)の求め方 list2.Sum(el => el.Age); Min・Max コレクションの最大・最小値を求める。 Averageと同じような記法で使用する (A)の求め方 list.Max(); (B)の求め方 list2.Min(el => el.Age); Contains 変数に指定した文字があるかどうかを判定する string name = "竈門炭治郎"; bool check1 = name.Contains("竈門"); // True bool check2 = name.Contains("水柱"); // False Any 変数の中に条件に一致しているデータがあるかどうかをチェックする。 bool check = arrayData3.Any(el => el.IsGet); // True All 変数の中のデータが全て条件を満たすかどうかをチェックする bool check = arrayData3.All(el => el.IsGet); // False SequenceEqual 2つのコレクションの要素が完全一致しているかどうかをチェックする。 例えば、 var pokemons = new List<Pokemon>() { new Pokemon("カメックス", new string[]{ "みず" }、 true), new Pokemon("ミミッキュ", new string[]{ "ゴースト", "フェアリー" }, false), new Pokemon("ガブリアス", new string[]{ "ドラゴン", "じめん" }, true), new Pokemon("ヤドキング", new string[]{ "みず", "エスパー" }, false), new Pokemon("キングドラ", new string[]{ "みず", "ドラゴン" }, true), new Pokemon("マフォクシー", new string[]{ "ほのお", "エスパー" }, true), new Pokemon("ドリュウズ", new string[]{ "じめん", "はがね" }, false), new Pokemon("エレキブル", new string[]{ "でんき" }, true), new Pokemon("ブーバーン", new string[]{ "ほのお" }, true), new Pokemon("ベトベトン", new string[]{ "どく" }, false), new Pokemon("ハッサム", new string[]{ "むし", "はがね" }, true), }; という値とarrayData3を比較するなどの場合に使える arrayData3.SequenceEqual(pokemons); //False Distinct コレクションから重複を削除する (例) var array = new List<int>() {1,1,2,2,3,3,4,4,5,5,6,6,7,7}; array.Distinct(); Concat 2つのコレクションを連結する。 (例) List<Pokemon> sumPokemon = pokemons.Concat(pokemons2).ToList(); ラムダ式 LINQで用意されているメソッドでは、「el => el > 4」というような、 「(変数) => (条件)」 の形式で書かれた部分のことをラムダ式といい、ラムダ式における「=>」をラムダ演算子という。 (変数)の名前は自由に決めていい。 elやres,req,valなど。 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker上で動かしたASP.NET Coreアプリで"no such table: テーブル名"となる場合の対処法

はじめに ASP.NET Core + SQLiteで自作したアプリをDocker上で動かした際に"no such table:テーブル名"と出た際の対処方法を備忘録として記載します。 エラー内容 Dockerfileをビルドし、docker run ~ でコンテナを作成していざアクセスした時でした。 fail: Microsoft.EntityFrameworkCore.Database.Command[20102] Failed executing DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT "t"."TestId", "t"."CreatedTime", "t"."Number", "t"."Title", "t"."UpdatedTime", "t"."UserId" FROM "Tests" AS "t" fail: Microsoft.EntityFrameworkCore.Query[10100] An exception occurred while iterating over the results of a query for context type 'DDD.Domain.Data.TestMakerContext'. Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Tests'. at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext() at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext() at Microsoft.Data.Sqlite.SqliteDataReader.NextResult() at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() ・・・以下いっぱいのエラーログ 「Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Tests'.」とありますので、どうやら対象のテーブルができていないようです。 対処法 以下のstackoverflowにも記載されていますが、DbContextのコンストラクタへ「Database.EnsureCreated();」を追記するとテーブルが作成されるとのことでした。 https://stackoverflow.com/questions/33455041/asp-net-5-ef-7-and-sqlite-sqlite-error-1-no-such-table-blog/47751630 ソースコードは以下のような感じになります。 TestMakerContext.cs public class TestMakerContext : DbContext { public TestMakerContext (DbContextOptions<TestMakerContext> options) : base(options) { Database.EnsureCreated(); // <-- 追記 } public DbSet<Test> Tests { get; set; } public DbSet<Question> Questions { get; set; } public DbSet<Choice> Choices { get; set; } public DbSet<User> Users { get; set; } } Database.EnsureCreated()とは? データベースが存在しない場合は、EnsureCreated によって作成され、データベーススキーマが初期化されます。 テーブルが存在する場合 (別の DbContext クラスのテーブルを含む)、スキーマは初期化されません。 データベースが存在しない場合に良い感じに作ってくれるみたいです。 https://docs.microsoft.com/ja-jp/ef/core/managing-schemas/ensure-created#ensurecreated デメリット この記事を書くにあたり、色々と調べていたらどうやらこの方法だとデータベースの移行(Migrate)には対応しないようですね・・・(;´∀`) https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.entityframeworkcore.infrastructure.databasefacade.ensurecreated?view=efcore-5.0 移行を考慮している際は上記の記事によると「Database.Migrate ()」を使用することを推奨しているので、そちらもいずれ動作確認してみようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NET(VB.NET C#) の配列変数 ← JSON → PHP

PHP (Webサーバ)と .NET アプリでデータをやりとりしたい場合、バイナリのやりとりはできません。ですのでデータをテキストに変換し HTTP POST するやりかたになります。 何に変換するかは任意ですが、古くは XML、こんにちは JSON に変換されることが多いようです。 PHPの場合、少なくともPHP7 では標準で JSON エンコード・デコード関数があります。 .NET の場合、いろいろとあるようですが、「JSON.NET」というのがお勧めです。( VS2013, VS2019 で動確) 早速ですが、PHP ← (JSON) → .NET  なサンプルを示します。 $dat1=json_decode($_POST['POSTdat1']); //1.配列全体を返す場合 echo json_encode($dat1, JSON_UNESCAPED_UNICODE); //2.配列の要素を出力する場合 //echo $dat1[0]; '配列をPOST変数として送りたい場合の処理について 'HTTPのWebリクエストでは電文(str)しか送れません。なので配列を送りたいときはJSONとして文字にして, 'そのJSON文字を受け取ったPHP側はデコードすることで配列化するのです。1次元のみならず多次元配列も可能です Dim dat1 As Object = {123, "aaa"} Dim Dat1str As String = Newtonsoft.Json.JsonConvert.SerializeObject(dat1) '送りたい配列をJSON文字列化 Dim url As String = "http://localhost/display.php" Dim wc As New System.Net.WebClient Dim ps As New System.Collections.Specialized.NameValueCollection ps.Add("POSTdat1", Dat1str) '配列などオブジェクトをJSON文字列化して送る ' wc.Credentials = New NetworkCredential("user", "pass") 'BASIC認証がかけられている場合 Dim resData As Byte() = wc.UploadValues(url, ps) wc.Dispose() Dim echoback As String = System.Text.Encoding.UTF8.GetString(resData) '実際にはこのあとHTML文章のうちデータ相当を抜き出す処理が必要(PHPはHTML文章のため意図しない文字が含まれているため) '1.PHPからJSONが出力される場合の処理 Dim resdat1 As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(echoback) '受け取ったJSON文字列をオブジェクトにデコード Console.WriteLine(resdat1(0)) 'エコーバック表示(配列0) '2.PHPから配列要素0が出力される場合 ' Console.WriteLine(echoback) 'ただの文字列なのでデータではない。だから唯の要素がPHPから帰ってくる場合もデシリアライズすること Console.WriteLine(resdat1(0)) 'データ '注意:PHPが echo するときHTML文章全体がこちらに帰ってきます。DeserializeObjectを実行するとき 'スペースやタブ、改行ぐらいなら除いてくれますが、その他のゴミのデータが入っていたら正常になりません。 'なので前にも述べたとおり、実用的には帰ってきた文字列から意図する文字列を抽出してからデシリアライズするべきでしょう。 PHP から VB へ受け取る場合、 PHPはページ全体を出力しますので、余計なゴミが含まれていたら正しくデシリアライズできません。 なのでこんな感じで、 echo 'PREJSON'.json_encode($dat1, JSON_UNESCAPED_UNICODE).'POSTJSON'; エンコードする部分を、任意の文字(例では PRESON, POSTJSON) で囲ってあげて、 VB側では正規表現で抽出してあげるとよいでしょう。 Dim echoback As String = System.Text.Encoding.UTF8.GetString(resData) echoback= Regex.Matches(echoback, "PREJSON(.*?)POSTJSON")(0).Groups(1)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reflection オーバーロードされているメソッドの呼び出し --メモ--

Reflectionでメソッドを呼び出したい。 StringクラスのRemoveメソッド呼び出し 引数に(int,int)タイプのものを使う。 string str = "HelloWorld"; Type type = str.GetType(); MethodInfo mi1 = type.GetMethod("Remove",new Type[] { typeof(int), typeof(int) }); Console.WriteLine(mi1.Invoke(str, new object[] { 0, 5 })); GetMethodsのリストから該当するメソッドを選択 GetMethodsでStringクラスのメソッドをすべて呼び出す。 そのうちRemoveメソッドを名前で選択。さらに引数が2つのものを選択 string str = "HelloWorld"; Type type = str.GetType(); MethodInfo[] methodInfos = type.GetMethods(); foreach (var mi in methodInfos) if (mi.Name == "Remove") { ParameterInfo[] pi = mi.GetParameters(); if (pi.Length == 2) { Console.WriteLine(mi.Invoke(str, new object[] { 0, 5 })); } }; 参考 文字列で指定したメソッドを呼び出すサンプル・プログラム C#のリフレクションについて、思いつくままにコードを書く
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む