ASP.NET MVCやC#のあれこれ

自分メモです。

  • カスタムのモデルバインダというのでフォーム等とモデルをバインドはできるが、標準のモデルバインダと同じような挙動をさせないといろいろ限界が出てくるしチームに説明しづらい。
  • ValidateJsonAntiForgeryTokenAttribute, ただし必要性は要検討。
  • IEnumerable<T>yield returnするケース、遅延評価であるため例外も遅延することに注意。(XMLドキュメントコメントはどう書くのがよいのだろう?)
   // 動くか未検証コード
   IEnumerable<string> DoYield()
   {
      yield return "hello";
      throw new Exception("aaa");
      yield return "world";
   }
   void Main()
   {
      // この時点ではまだ例外にならない
      var query = DoYield();
      foreach (var s in query) {
          //例外になるのは、ここの2周目
      }
   }
  • ASP.NET MVCに限った話ではないが、関連をもったエンティティを無理せず登録するには、親エンティティの登録完了画面で、続けて子エンティティの登録を促す画面を挟むのがUXてきに自然な感じになる
  • EntityFrameworkにて関連をナビゲーションプロパティというやつで持たせるときはvirtualで宣言する。(たぶんプロキシをsubclassingするためだろう)
  • EntityFrameworkとシノニムは相性が悪い。Migrationを書き換えてcreate/drop synomymにしたりはできるのだが、DbContextによるテストデータ挿入とか接続文字列をどう持つとかデバッグ構成・リリース構成でそれを変えるとかいろいろ考えることがある。ちなみにシノニム越しでの外部キーが張れないのも、いろいろなじまない。(『SQLアンチパターン』も見よ。)
  • 関連を含めてのSaveChanges()は、もちろん可能。ただし、Migrationのときにはたぶんダメ。よって、MigrationでConfiguration#Seed()によるテストデータ挿入を使うなら、DbContextはDDDでいう集約ルート以外のエンティティに相当するモデルのDbSetもプロパティとして露呈する必要がある。
    • リポジトリを介してアクセスさせるようにすれば、露呈問題はさほど問題にならないか。
// 記憶書きコードなので適当
public interface IAggregateRoot {}
public class Order : IAggregateRoot {}
public class OrderItem {}
public interface IRepository<T> where T : IAggregateRoot {}
public class OrderRepository : IRepository<Order>
{
  private readonly OrderContext context;
  public OrderRepository(OrderContext context)
  {
    this.context = context; // injection via UnityFramework etc.
  }
  public IQueryable<Order> AsQueryable() {...}
  public Optional<Order> Find(int id) {...}
  public void Update(Order order) {...}
  ...
}