2019年2月15日金曜日

[.NET]コード内Enumだけで宣言したデータでドロップダウンの候補をセット

オリジナルのドロップダウンを作成する場合、宣言部だけで使いまわしたい…
ということで以下。

①Enum宣言
----------------------------------------------

public enum enumHito : byte
 {
            [Display(Name = "太郎")]
            Tarou = 12334,
            [Display(Name = "花子")]
            Hanako = 19483,
}

----------------------------------------------
②宣言したEnumから属性:NameをGetする共通関数を作成しておく。

----------------------------------------------

//属性:Nameを取得
public static class GetAttribute
    {
        public static string Name(object obj)
        {
            var fieldInfo = obj.GetType().GetField(obj.ToString());
            var descriptionAttributes = fieldInfo.GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[];
            if (descriptionAttributes != null && descriptionAttributes.Length > 0)
            {
                return descriptionAttributes[0].Name;
            }
            else
            {
                return string.Empty;
            }
        }

    }
----------------------------------------------

③②を使って①情報からドロップダウン候補をデータバインドする。

----------------------------------------------
var data = new List<Tuple<int, string>>();
foreach (enumKenaskuShubetsu row in Enum.GetValues(typeof(enumHito)))
{
  data.Add(new Tuple<int, string>((int)row, GetAttribute.Name(row)));
}
ddlhoge.DataValueField = "item1";
ddlhoge.DataTextField = "item2";
ddlhoge.DataSource = data;

ddlhoge.DataBind();

----------------------------------------------

[.NET]オブジェクト内に同じプロパティがあった場合、同じ値をセットする

①以下のような関数を作成。
------------------------------------------------

/// <summary>
/// 同じプロパティから同じ値をセットします
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="self"></param>
/// <param name="Frommodel"></param>
public static void CopyFromSameProperty<T>(this T self, object Frommodel, List<string> Lstexcept = null)
        {
            PropertyInfo[] propertyInfo = Frommodel.GetType().GetProperties();
            foreach (PropertyInfo p in propertyInfo)
            {
                if (Lstexcept != null && Lstexcept.Contains(p.Name)){ continue; }

                //コピー元
                var arg = p.GetValue(Frommodel, null);
                //コピー先
                PropertyInfo pTo = self.GetType().GetProperty(p.Name);
                if (pTo != null)
                {
                    pTo.SetValue(self, arg);
                }

            }
}
------------------------------------------------
②使い方は以下。
------------------------------------------------
// ベースとなる行
var baseRow = db.T_hoge.Where(d => d.番号 == 1234).FirstOrDefault();
var newRow = new T_hoge();

newRow.CopyFromSameProperty(baseRow); //一度全項目コピーする
------------------------------------------------

※「このプロパティはコピーしたくない!」というものがあるならば
 以下の様にプロパティ名を指定すればOK
newRow.CopyFromSameProperty(baseRow, new List<string> { "番号" }); //一度全項目コピーする



[.NET]EntityFrameWorkのSQLログを好きな箇所で保存する

EntityFrameWorkでSQLログを取りたい時、以下の様に書けばいいが

db.Database.Log = sql => { Debug.Write(sql); };
これだと同じdb内で処理したところすべてのSQLを取ってしまう。
(どうでもいいSELECT文とか…UPDATEだけでいいのに的な)

①Using等でくくったところだけ、SQLログを取るようにしたかったので
 以下のようなクラスを作成。
-----------------------------------------------------------------------------
public partial class EFlogSave : IDisposable
    {
        bool flgWrite = false;

        string tmp = true;  //一時的に採取をやめる場合はここをfalseに
        bool flgConfig;       
        string strSQLLog = string.Empty;
        public EFlogSave(DbContext db, bool flg = true, string strHeadtext = null)
        {
            if (bool.TryParse(tmp, out flgConfig))
            {
                if (flg && flgConfig) { flgWrite = true; }
            };
            if (flgWrite)
            {
                if (strHeadtext != null) { strSQLLog = strHeadtext; }
                db.Database.Log = x => { strSQLLog += x; };              
            }
        }
        public EFlogSave(DbContext db, string strHeadtext )
        {
            if (bool.TryParse(tmp, out flgConfig))
            {
                if (flgConfig) { flgWrite = true; }
            };
            if (flgWrite)
            {
                if (strHeadtext != null) { strSQLLog = strHeadtext; }
                db.Database.Log = x => { strSQLLog += x; };
            }
        }
        //dispose周り---------------
        bool disposed = false;
        SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;
            if (disposing)
            {
                handle.Dispose();
                // Free any other managed objects here.
            }
            //SQLログを吐き出す
            if (flgWrite) { Debug.Write(strSQLLog); }
            disposed = true;
        }
}
--------------------------------------------------------------------------
Usingでくくっておいて、disposeする時にSQL文を吐き出す、という仕組み。

②実際のコードでの使い方は以下。
---------------------------------------------------------------------------
using (var db = new HogeDBEntities())
{
var updRow = db.T_てすと.Where(d => d.番号 == 12345).FirstOrDefault()

using (new EFlogSave(db))   // SQLログを取る時のみ指定
{
updRow.状態区分 = 3;
db.SaveChanges();
}
}
---------------------------------------------------------------------------
EFlogSaveでくくった、UPDATEの箇所だけSQLを吐き出してくれる。