2016年04月02日

Microsoft MVP アワード再受賞しました  



本年も、Microsoft MVP アワードを無事、再受賞することができました。 
おかげさまで 2005年4月からの連続受賞で今回で12回目となりました。やはり何回頂いても嬉しくそして、ありがたいものです。

カテゴリーは、「Visual Studio and Development Technologies」です。 これまでは、C# → .NET でしたが、今回カテゴリーが変更になりました。

以下受賞メールの一部抜粋です。
34


この時期になると毎年思いますが、いやーほんとに長い期間良く続けられたなーと思います。
一昨年に終了したC#メールマガジンのバックナンバーのダウンロードページには、未だにそれなりのアクセスがありますので、C#プログラマーの方々のスキルアップにそれなりに貢献できたのかなと思います。


今年に入りブログが放置状態ですが、開発者としてはまだまだ現役ですので、また何かアップできればと思っています。


  

Posted by gushwell at 11:20Comments(0)TrackBack(0)雑談

2016年02月07日

2015年12月20日

EntityFramework(24):落穂ひろい


今回が、このシリーズ最後です。

説明し忘れたものをいくつかピックアップしました。

■Configuration.ValidateOnSaveEnabled

検証済みのデータを使ってデータを更新する際には、Configuration.ValidateOnSaveEnabled プロパティの 価をfalseにすることで、SaveChanges時のデータ検証を省くことができます。
これにより、パフォーマンスを向上させることができます。 デフォルト値は、trueです。

using (var db = new NorthwindContext()) {
    db.Configuration.ValidateOnSaveEnabled = false;
    ...
}


■Configuration.AutoDetectChangesEnabled

AutoDetectChangesEnabled プロパティの値を false に設定することで、パフォーマンスが 向上する場合があります。
もし、データベースへの更新処理が、INSERT か DELETE しかない場合は、このプロパティを false にすることでパフォーマンスを向上できます。
UPDATEがある場合には、プロパティの変更を検知できなくなるので、このプロパティを false にしたままだと、更新できなくなるので、注意が必要です。

using (var db = new NorthwindContext()) {
    db.Configuration.AutoDetectChangesEnabled = false;
    ...
}


■Database.CommandTimeout

データベースの操作に対するタイムアウト値の秒数を設定できます。
既定値は null 値で、null は基になるプロバイダーの既定値が使用されることを示します。

using (var db = new NorthwindContext()) {
    db.Database.CommandTimeout = 180;
    ...
}


■AsNoTracking

メソッド データベースからデータを読み出すだけならば、AsNoTrackingメソッドを使うことで、 パフォーマンスを向上できます。

using (var db = new NorthwindContext()) {
    var query = db.Products.AsNoTracking()
                  .Where(p => p.UnitPrice < 10);
    foreach (var p in query) {
        Console.WriteLine(p.ProductName);
    }
}

ほかにも、いろいろありそうだけど、僕の知識の範囲を超えるので、この辺りで当シリーズを終わりにします。


多分、これが今年最後の投稿かな。
すこし早いですが、皆さん良いお年を!





   
Posted by gushwell at 22:00Comments(0)TrackBack(0)EntityFramework

2015年12月13日

EntityFramework(23):IValidatableObjectによる検証


これまで見てきたデータ検証は、一つのフィールドに対しての検証でしたが、 IValidatableObjectインターフェースを実装することにより、 複数のフィールドに対する検証を行うこともできます。
以下の例は、Customerクラスに、IValidatableObject を実装した例です。

public partial class Customer : IValidatableObject {
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        if (!string.IsNullOrWhiteSpace(ContactTitle) && string.IsNullOrWhiteSpace(ContactName) ) {
            var msg = "ContactTitleに値が設定されている時は、ContactNameにも値を設定する必要があります。";
            var members = new[] { "ContactName" }; 
            yield return new ValidationResult(msg,members);

        }
    }
}

自動生成されたEntityクラスに追加するのではなく、別途 Partialクラスを定義しています。
この検証が正しく動作するかを確認するコードも書いてみます。

using (var db = new NorthwindContext()) {
    try {
        Customer cust = new Customer {
            CustomerID = "CSFM",
            CompanyName = "CSharp Food Market",
            ContactTitle = "Manager"
        };
        db.Customers.Add(cust);
        db.SaveChanges();
    } catch (DbEntityValidationException ex) {
        PrintEntityValidationErrors(ex.EntityValidationErrors);
    }
}

デバッグ実行すると、SaveChangesメソッド呼び出し時に、Validateメソッドが走り、 検証が行われているのが確認できます。
   
Posted by gushwell at 21:00Comments(0)TrackBack(0)EntityFramework

2015年12月09日

EntityFramework(22):独自の検証用属性を定義する


EntityFrameworkの検証機能の続きです。

標準で用意されている検証用属性では不足している場合は、ValidationAttribute を継承したクラスを定義する ことで、独自の検証用属性を定義することもできます。

以下、そのサンプルを示します。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 public sealed class HiraganaAttribute : ValidationAttribute {
     private static Regex _regex = new Regex(@"^[\p{IsHiragana}\u30FC]+$");

     public override bool IsValid(object value) {
         if (value == null) {
             return true;
         }

         string valueAsString = value as string;
         if (valueAsString != null) {
             var m = _regex.Match(valueAsString);
             return m.Success;
         } else {
             return true;
         }
     }

     public override string FormatErrorMessage(string name) {
         return $"{name}はひらがなを指定してください";
     }
 }

このサンプルは、ひらがなと長音記号だけで成り立つ文字列の時だけ、検証を成功させます。 プロパティに以下のようにHiraganaAttribute を付加するだけです。

[Hiragana]
public string KanaName { get; set; }

なお、自動生成されたEntityクラスに手を入れたくないという場合は、 「楽観的同時実行制御 (Timestamp列なし)」で示した、MetadataType属性を付加したPartial クラスを定義することで、対応できます。

[MetadataType(typeof(Category.Metadata))]
public partial class Category {
    class Metadata {
        [ConcurrencyCheck]
        public string CategoryName { get; set; }

        [ConcurrencyCheck]
        [Hiragana]
        public string Description { get; set; }

        [ConcurrencyCheck]
        public byte[] Picture { get; set; }
    }
}

これは、DescriptionプロパティににHiragana属性を付加した例です。
実際に、Descriptionの値がひらがなだけというのは、UI的にどうかを思いますが... まあ例ということでお許しを。
   
Posted by gushwell at 22:30Comments(0)TrackBack(0)EntityFramework

2015年12月02日

EntityFramework(21):DataAnnotationsによるデータの検証


「データベースからCode First」でPOCOクラスを自動生成すると、テーブル定義にしたがって 以下のような属性が付加されます。

        [Required]
        [StringLength(40)]
        public string ProductName { get; set; }


Required、StringLength は、System.ComponentModel.DataAnnotations 名前空間に 定義されている属性で、これをデータ注釈と呼んでいます。
このデータ注釈は、SaveChangesメソッドを呼び出した時の検証として利用される ものがあります。
代表的な検証用属性としては以下のようなものがあります。

Required
そのフィールドに値が設定されているかを検証

StringLength
文字列の長さが指定文字数以内かを検証

RegularExpression
文字列が正規表現パターンpatternにマッチするかを検証

Range
指定した最小値と最大値の範囲内にあるかを検証

Compare
指定したプロパティと同じ値かを検証

EmailAddress
電子メールアドレスかどうかを化粧


▪️実際の定義例

        [Required]
        [StringLength(40)]
        public string CompanyName { get; set; }

        [Range(1,9999)]
        public int ProductType { get; set; }

        [RegularExpression(@"\d{3}\-\d{4}")]
        public string PostalCode { get; set; }

        [Required]
        [EmailAddress()]
        public string EmailAddress { get; set; }

        [Compare("EmailAddress")]
        public string  VerifiedEmailAddress { get; set; }
 


では、実際に検証エラーを起こしてみましょう。

            using (var db = new NorthwindContext()) {
                Category cat = new Category {
                    CategoryName = "longest Category Name",
                    Description = "salad, croquette, tempura, cooked beans",
                };
                db.Categories.Add(cat);
                db.SaveChanges();
            }

CategoryNameには、 [StringLength(15)] と検証属性が付加されているので、 上のコードを実行すると、検証例外 System.Data.Entity.Validation.DbEntityValidationException が発生します。
では、どのプロパティでどんな検証エラーが発生したのかはどうやって知るのか?

この例外オブジェクトのMessageプロパティには

”1 つ以上のエンティティで検証が失敗しました。詳細については 'EntityValidationErrors' プロパティを参照してください。”

というメッセージが設定されています。でも、このEntityValidationErrorsの値って、Visual Studioのデバッガーでは 中身を確認することができません。(僕の確認の方法が悪いのかな?)

以下のようなコードを書けば、中身を確認できます。


     try {
         ...
         db.SaveChanges();
     } catch (DbEntityValidationException ex) {
         PrintEntityValidationErrors(ex.EntityValidationErrors);
     }
 ...
 
 private static void   PrintEntityValidationErrors(IEnumerable<DbEntityValidationResult> entityValidationErrors) {
     foreach (var er in entityValidationErrors) {
         foreach (var item in er.ValidationErrors) {
             Console.WriteLine("{0}:{1}", item.PropertyName, item.ErrorMessage);
         }
     }
 }


  
Posted by gushwell at 22:30Comments(0)TrackBack(0)EntityFramework