VisualStudio(C#)から「Publish AWS Serverless Application」するとAspNetCoreFunctionRoleがCREATE_FAILEDになる。

2012/03/29から既存のC#で作ったLambdaがAWSにPublishできない現象が発生しました。
Lambda のアイデンティティベースの IAM ポリシーによると
AWSLambdaFullAccess と AWSLambdaReadOnlyAccessは 2021年3月1日に非推奨となったようです。
AspNetCoreFunctionRoleの作成に失敗するのも原因はAWSLambdaFullAccessのようです。
解決方法は
  • publishの際に使用するIAMユーザーにAWSLambda_FullAccessをアタッチする。
  • VisualStudioを起動して「serverless.template」ファイル内の「AWSLambdaFullAccess」をアンダーバー付きの「AWSLambda_FullAccess」に書き換える
  • 既にpublishに失敗し、CloudFormationに失敗のステータスが残っている場合は削除する

これでpublishできるようになります。

ASP.NET MVC 5 OracleのテーブルからEDMを作成するとき、Numerの精度によりint以外にマッピングされる

VisualStudio2017 / ASP.NET MVC 5 / Framework4.6.2 / C# / Oracle.ManagedDataAccess.EntityFramework 12.2.1100


データベースファーストでOracleのテーブルよりEDMを作成すると、Numerの精度により以下のようにマップされます。
Number(1,0)bool
Number(2,0) ~ Number(3,0)byte
Number(4,0)int16
Number(5,0) ~ Number(9,0)int32
Number(10,0) ~ Number(18,0)int64


Numberの精度がNumber(1,0)~Numebre(4,0)の場合に int16 にマップするには、web.config に
<add NETType="int16" MinPrecision="1" MaxPrecision="4" DBType="Number"/>
を追加します。

Web.config
<oracle.manageddataaccess.client>
 <version number="*">
  <edmMappings>
   <edmNumberMapping>
    <add NETType="int16" MinPrecision="1" MaxPrecision="4" DBType="Number"/>
   </edmNumberMapping>
  </edmMappings>
  <dataSources>
   <dataSource alias="XXXXX" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=XXX.XXX.XXX.XXX)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XXXXX))) " />
  </dataSources>
 </version>
</oracle.manageddataaccess.client>

ASP.NET MVC EditorForでhtmlAttributesを指定せずにclassを指定する

VisualStudio2017 / ASP.NET MVC 5 / Framework4.6.2 / C#


EditorForでclass属性を指定するには、htmlAttributes を使って下記のように書きます
@Html.EditorFor(mdl => mdl.ID, new { htmlAttributes = new { @class = "form-control" } })
少しの事なんだけどメンドクサイ…

EditorForを拡張したEditForExを作成し、htmlAttributesを指定せずにclass属性を設定できるようにしたいと思います。
こんな感じで設定できるようにします。
@Html.EditorForEx(mdl => mdl.ID, new { @class = "form-control" } )

カスタムヘルパーの作成

カスタムヘルパーEitorForExを作成します。
htmlAttributes属性はヘルパーの中でつけてあげます。

EitorForExヘルパーを使用したとき何か固定で付けたい属性があれば、指定しておきます。
Bootstrapを使用しているのであれば「form-control」を付けておいてもいいかもしれません。

また、通常のEditorForヘルパーはclass属性に「text-box single-line」を吐き出すので、これを出力しないようにします。

using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

using MyApp.Addon.Attributes;


namespace MyApp.Addon.Extentions
{
    /// 
    /// HTMLヘルパーに対する拡張クラス
    /// 
    public static class HtmlHelperEx
    {

        /// 
        /// EditorForヘルパーを拡張したヘルパー
        /// 機能
        /// htmlAttributesの指定なしにclass属性を指定する
        /// class属性にハードコーディングされる「text-box single-line」を削除する
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static IHtmlString EditorForEx<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, 
                                                                Expression<Func<TModel, TValue>> expression, 
                                                                object viewData)
        {
            //属性をディクショナリに変換
            var dicAttr = new RouteValueDictionary(viewData);
            
      //何か固定で足したい属性があればここで足す
            //属性を追加
            dicAttr.Add("maxlength", 10);

            /*
             * EditorForヘルパーでHTML属性を指定するには
             * @Html.EditorFor(mdl => mdl.ID, new { htmlAttributes = new { @class = "form-control", @readonly="readonly" } } )
             * と指定しなければならない。
             * 
             * これをEditorForExヘルパーでは
             * @Html.EditorFor(mdl => mdl.ID, new { @class = "form-control", @readonly="readonly" } )
             * と指定できるようにする。
             */
            dynamic htmlAttr = new { htmlAttributes = dicAttr };
            MvcHtmlString hstr = htmlHelper.EditorFor(expression, (object)htmlAttr);


            /*
             * 吐き出されるHtmlより class=属性の「text-box single-line」を外す
             */
            hstr = MvcHtmlString.Create(hstr.ToString().Replace(" text-box single-line", ""));
            
            return hstr;
        }

    }
}
よく使用するヘルパーであれば、Views/Web.configのnamespace要素に追加すると、各ビューにインポートを書かなくて済みます。
web.configに追加した場合、私の環境ではVisualStudioを再起動しないと、ビューで使用する際にコンパイルエラーになりました。

        
       ・・・省略
        

web.configに追加しない場合は、各ビューの先頭でインポートしてください。
@using MyApp.Addon.Extentions;

通常のEditorFor と 今回作成したEditorForExの出力をみてみます。
EditorFor
@Html.EditorFor(mdl => mdl.ID, new { htmlAttributes = new { @class = "form-control" } })

出力結果:

EditorForEx
@Html.EditorForEx(mdl => mdl.ID, new { @class = "form-control" })
出力結果


ASP.NET MVC 自作カスタム属性を、自作Htmlヘルパーでビューに表示する

VisualStudio2017 / ASP.NET MVC 5 / Framework4.6.2 / C#


ビューモデルのプロパティに指定した「Placeholder」カスタム属性の値を、「PlaceHolderFor」カスタムヘルパーでビューに出力できるようにします。

目指すゴールは
ビューモデルのプロパティにPlaceholder属性を設定し、プレースホルダーに表示する値を指定できるようにします。
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using MyApp.Addon.Attributes;

namespace MyApp.ViewModels
{
    /// 
    /// ログイン ビューモデル
    /// 
    public class Login
    {
        [DisplayName("ID"),
         Placeholder("IDを入力してください")]
        public string ID { get; set; }
    }
} 

次にビューでは @Html.PlaceholderFor ヘルパーを使用して、プレースホルダーの値を表示できるようにします。
@Html.EditorFor(mdl => mdl.ID, new { htmlAttributes = new { @class = "form-control", placeholder = @Html.PlaceholderFor(mdl => mdl.ID) } })

カスタム属性の作成

まずはPlaceHolder属性から作成していきます。
Placeholder属性では、プレースホルダーに表示する値をコンストラクタの引数で指定するようにしています。
モデルのプロパティに対して使用する属性なので、クラスに System.AttributeUsage(AttributeTargets.Property) 属性を指定します。
using System;

namespace MyApp.Addon.Attributes
{
    /// 
    /// プレースホルダー属性
    /// 
    [System.AttributeUsage(AttributeTargets.Property)]
    public class PlaceholderAttribute : System.Attribute 
    {
        /// 
        /// プレースホルダーとして表示値する値
        /// 
        public string DisplayValue { get; set; }

        /// 
        /// コンストラクタ
        /// 
        /// プレースホルダーとして表示する値
        public PlaceholderAttribute(string displayValue)
        {
            DisplayValue = displayValue;
        }
    }
}
次に属性を読み取るモデルメタデータプロバイダーを作成します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;


namespace MyApp.Addon.Attributes
{
    /// 
    /// 拡張したモデルメタデータプロバイダー
    /// 
    /// 
    /// Global.asaxのApplication_Start()で、モデルプロバイダーに指定する。
    /// 
    public class ModelMetadataProvidersEx : DataAnnotationsModelMetadataProvider
    {
        /// 
        /// 基底のCreateMetadataをオーバーライド
        /// 指定したモデルのメタデータを作成します。
        /// 
        /// 属性
        /// コンテナーの型。コンテナーが存在しない場合は null。
        /// モデル アクセサー。
        /// モデルの型。
        /// プロパティ名。モデルがプロパティではない場合は、null。
        /// モデルのメタデータ
        protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        {
            //元のCreateMetadataメソッドを呼び出し
            ModelMetadata metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
            //Placeholder属性を追加する
            PlaceholderAttribute pha = attributes.OfType<PlaceholderAttribute>().FirstOrDefault();
            if (pha != null)
            {
                metadata.AdditionalValues.Add("Placeholder", pha);
            }
            
            return metadata;
        }
    }
}
作成したモデルメタデータプロバイダーを、Grobal.asaxのApplication_Startメソッドで、属性の読み取りに使用する設定を行います。
using System.Web.Mvc;
using System.Web.Routing;

namespace MyApp
{
    /// 
    /// アプリケーションイベント
    /// 
    public class MvcApplication : System.Web.HttpApplication
    {
        /// 
        /// アプリケーション起動時
        /// 
        protected void Application_Start()
        {
            //エリア登録
            AreaRegistration.RegisterAllAreas();
            //ルート登録
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            //データアノテーション属性の読み込みに、カスタマイズしたプロバイダーを使用する
            ModelMetadataProviders.Current = new MyApp.Addon.Attributes.ModelMetadataProvidersEx();
        }
        
    }
}
以上で属性の作成は終了です。
リビルドしたら、ビューモデルのプロパティに対して、プレースホルダーの属性を設定します。
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using MyApp.Addon.Attributes;

namespace MyApp.ViewModels
{
    /// 
    /// ログイン ビューモデル
    /// 
    public class Login
    {
        [DisplayName("ID"),
         Placeholder("IDを入力してください")]
        public string ID { get; set; }
    }
} 

カスタムHtmlヘルパーの作成

次にプレースホルダーの属性値を表示するためのHtmlヘルパーを作成します。
using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Dynamic;

using MyApp.Addon.Attributes;


namespace MyApp.Addon.Extentions
{
    /// 
    /// HTMLヘルパーに対する拡張クラス
    /// 
    public static class HtmlHelperEx
    {
       
        /// 
        /// PlaceholderFor プレースホルダー属性に指定された値を出力するHtmlヘルパー
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static IHtmlString PlaceholderFor<TModel, TValue>(
                             this HtmlHelper<TModel> htmlHelper,
                             Expression<Func<TModel, TValue>> expression)
        {

            var attrList = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, htmlHelper.ViewData);
            //プレースホルダーの属性値を返す
            if (attrList.AdditionalValues.ContainsKey("Placeholder"))
            {
                var plhAttr = (PlaceholderAttribute)attrList.AdditionalValues["Placeholder"];
                return new HtmlString(plhAttr.DisplayValue);
            }
            return new HtmlString("");
        }

        

    }
}

以上でヘルパーの作成は終了です。


よく使用するヘルパーであれば、Views/Web.configのnamespace要素に追加すると、各ビューにインポートを書かなくて済みます。
web.configに追加した場合、私の環境ではVisualStudioを再起動しないと、ビューで使用する際にコンパイルエラーになりました。

        
       ・・・省略
        

web.configに追加しない場合は、各ビューの先頭でインポートしてください。
@using MyApp.Addon.Extentions;
これでビューでは @Html.PlaceholderFor ヘルパーを使用して、プレースホルダーの値を表示できるようになります。
@Html.EditorFor(mdl => mdl.ID, new { htmlAttributes = new { @class = "form-control", placeholder = @Html.PlaceholderFor(mdl => mdl.ID) } })

実行結果

ASP.NET MVC データベースファーストでOracleのテーブルからEDMが作成できない

Visual Studio 2017
Framework 4.6.2
ASP.NET MVC 5

上記の条件でORACLEのテーブルからEDMを作成しようとしたのですが、EDM作成ウィザードが途中で消えてしまう現象が発生しました。

VisualStudio2017でFramework4.6.2を選択し空のASP.NET MVCアプリケーションを作成しました。


NuGetからEntityFrameworkをインストールします。
2018/09/08時点で最新の安定版6.2.0です。

NuGetからOriole.Managed.DataAccess.EntityFrameworkをインストールします。
2018/09/08時点で最新の安定版18.3.0です。


Oracleのサイトから32-bit Oracle Data Access Components (ODAC) with Oracle Developer Tools for Visual Studio をダウンロードしてインストールします。
2018/09/08時点で最新バージョンの12.2.0.1.1です。

EDMを追加します。
適当なフォルダで右クリックし「追加」>「新しい項目」を選択し「ADO .NET Entity Data Model」を選択します。
Entity Data Model ウィザードが起動するので、設定を進めていきます。




本当なら次にデータベースのテーブルを選択する画面が出てくるのですが、ウィザードはここで終了してしまいます。

色々ためしてみましたが、NuGetからインストールしたOriole.Managed.DataAccess.EntityFrameworkを、 最新の安定版18.3.0 から ひとつ前のバージョン12.2.1100に落とすとウィザードが正常に動きました。

同じようにEDM作成ウィザードを起動すると、次はテーブルを選択する画面が出てきました。

簿記 簿記2級で使用した教材

簿記3級で使用した教材に続いて、
私が簿記2級で使用した教材を紹介します。

簿記3級では、TAC出版の「スッキリシリーズ」と「合格トレーニング」を使用したので
とりあえず簿記2級も同じシリーズを購入して勉強を始めました。
スッキリわかる日商簿記2級 商業簿記

スッキリわかる 日商簿記2級 工業簿記

合格トレーニング日商簿記2級商業簿記

合格トレーニング 日商簿記2級 工業簿記


簿記3級の流れで同じシリーズの本を買いましたが、
正直なところ簿記2級からは(ネコはかわいいけど)スッキリシリーズでは少し内容が足りないと思います。
特に工業簿記はスキッリシリーズでは理解が不足しました。

簿記1級の勉強ではネコは卒業して、同じTAC出版の簿記の教科書と簿記の問題集を使っています。
簿記2級の勉強の時は使用していなかったのですが、「スッキリシリーズ + 合格トレーニング」の組み合わせより、「簿記の教科書 + 簿記の問題集」 の組み合わせのほうが、理解が深まるかもしれません。
書店などで内容を確認してから購入することをお勧めします。


テキストと合格トレーニングで一通り勉強が終わってから、過去問と予想問題を買ってみました。
とりあえず同じスッキリシリーズからチョイス
スッキリとける日商簿記2級過去+予想問題集

とりあえず買ってみたけど、これも要らなかったかもしれません。
最後に紹介するネットスクールの過去問だけで良かったかなと思います。
簿記2級からは商業簿記に加え、新たに工業簿記が入ってきます。
過去問や予想問題をすると、どうも工業簿記が弱いことに気が付きました。
少し問題を捻られると、時間がかかったり解けなかったりします。


工業簿記はまだ勉強が足りないな…と思い、下記の本を購入してみました。
検定簿記ワークブック2級工業簿記 日本商工会議所主催簿記検定試験

これは私にはあまり役に立たなかったです。
この本を購入した時はわからなかったのですが、私が知りたいことは工業簿記の効率的な解き方で、計算の下書きの仕方だったようです。
このワークは工業簿記の問題集であり、効率的な解き方を書いている本ではありません。
この時は問題の数をこなせば慣れるかと思って購入しましたが、問題を解いてもあまり効率が上がることはありませんでした。


次に工業簿記のために買った本は、
パブロフ流でみんな合格日商簿記2級工業簿記総仕上げ問題集
これは本当に良かった!
工業簿記のボックス図の書き方が手書きで書かれていて、あ~こう書けば時間短縮できるのね!とかがわかったり
ボックス図だらけで解いているうちに混乱してしまっていたのが、一気にスッと理解できました。
内容はとても易しいものばかりなのですが、これ1冊で苦手だった工業簿記が得意になった1冊でした。
工業簿記が苦手だなと感じる方にはお勧めです。


最後に過去問はネットスクールの日商簿記検定模擬試験問題集2級をチョイス。
最後の1~2カ月はこの過去問を何周も回していました。
この過去問は解説に誤記が結構あるのですが、必要最低限の内容で良かったです。
過去問を解く段階までくると、そんなに詳しい解説も必要がないと思いますので、過去問と必要最低限の解説で十分かと思います。


今は商業簿記より工業簿記のほうが得意です。
簿記2級の本試験では商業簿記の問2か問3に超難問が入り、工業簿記は基本に忠実な問題が多く得点源です。
また商業簿記は新論点など過去問にはない問題が出題される可能性があります。
その点、工業簿記は基本に忠実で新論点の出題もありません。
工業簿記は満点を取るつもりでがっつり勉強して、商業簿記で1問捨てる覚悟で本試験に挑みました。

また過去問を解くときも、工業簿記から問5→問4→次に商業簿記の問1→問2か問3の時間が掛からなさそうなほうを解くようにしました。
過去問では3周目ぐらいでも全問解くのにギリギリ2時間。全問満点もなかなか取れなかったのですが
本試験(144回)は簡単な問題だったのか、全問解いてから、見直しに全問もう一度解けるほど、時間が余りました。
点数は96点。商業簿記でどうしても理解できない問題があって(日本語の言い回しがわからなかった)、間違えたのはその1問だけでした。


簿記2級の勉強は、簿記3級の下地があるのでそこまで大変だとは感じませんでした。
ボリュームは工業簿記が増える分だけ簿記3級の倍にはなりますが、単純にボリュームが増えるだけなので、
コツコツ毎日続けていればいつか終わります。
簿記2級では工業簿記をしっかりマスターすることがキモだと思います。

簿記 簿記3級で使用した教材

今日は私が簿記3級で使用した教材を紹介します。

私の仕事はIT系なのですが、新しいプログラム言語を勉強するときには本を購入します。
この本を選ぶ際は以下のマイルールがあります。
  1. まず1冊目は簡単で易しいものを選ぶこと。
  2. 次の1冊はより専門的な難しいものを選ぶこと。
1冊目から調子に乗って専門的な難しい本を読むと、たいがい書いていることが理解できず嫌になります。
でも1冊目に簡単で易しい本を読むと、専門的な難しい本も理解できるようになっています。
簡単で易しい本だけを読んで専門的な本を読まずにいると、プログラムは書けるけれど、なぜそうなっているのかなど本質が理解できません。


そんなわけで簿記も同じだろうと思い、マイルールにのっとりまずは評判の良い易しそうな本を選ぶことにしました。

TAC出版 スッキリわかるシリーズ 
スッキリわかる 日商簿記3級 [テキスト&問題集]

ネコが可愛いです。
易しい文章で、簿記が初めてでも問題なく理解できると思います。
簿記3級であればこの1冊で大丈夫かもしれません。


わたしは問題が少なくてちょっと不安だったので下記の問題集を購入しました。
TAC出版 よくわかる簿記シリーズ
合格トレーニング日商簿記3級

この問題集はテキストの内容の理解を深めるのに役立ちました。
(時間がなければ、この問題集は必要ないかもしれません。余力があれば確実に理解は深まります。)


簿記3級で購入したテキストは以上の2冊です。
過去問などは買わなくても大丈夫でした。

簿記を勉強したきっかけでも書きましたが、
簿記3級の勉強時間は
平日は細切れ時間で通勤時間中もいれて1日30分ぐらいが精一杯。
土日祝の休みの日は早起きして1時間くらい。
基礎が大事だと思っているので、資格を取ることが目的ではなく、しっかり理解することを目的に6カ月かかりました。

勉強方法は簿記の勉強方法に書きましたが、テキスト→問題集→ノートにまとめる方法です。

今は簿記1級を勉強中ですが、簿記3級の勉強は簿記の知識がほぼゼロの状態からのスタートだったので一番キツかったです。
ネットで検索すると簿記3級は最速1カ月、だいたい3カ月で合格できるそうです。
たとえ仕事と家事育児で時間が取れなくても、諦めなければ時間はかかってもいつかは合格できるので、たとえ10分でも毎日続けることが大事だと思います。


次回は簿記2級で使用したテキストを紹介したいと思います。