web-dev-qa-db-ja.com

ドメインモデルのlinqクエリを介して返されるオブジェクトのプロパティと値を反復処理する

ドメインモデルを介してCLRにマップしたリレーショナルデータベースにカスタムエンティティがあります。そのため、次のステートメントを使用することで、ドメインモデルでのLINQクエリを介して、データベースからメモリにエンティティを取り込むことができます。

var inspection = (from i in dbContext.New_testinspectionExtensionBases
              where i.New_testinspectionId == currentInspection   
              select i).First();                         

このエンティティには、アクセスする必要のあるプロパティ/フィールドがあります。プロパティ/フィールド名とその値を決定できる必要があります。メモリ内のこれらのアイテムをループし、それらの名前と値をコンソールに書き出したいと思います。

私はこのアプローチを使用しようとしましたが、構文を修正する方法を理解できませんでした(または、GetPropertiesが使用する正しいメソッドであると確信しています。しかし、私が必要とするのは値への読み取りアクセスだけなので、それは本当に重要ではありません。

var inspectionReportFields = inspection.GetType().GetProperties(); 
// I called this inspectionReportfields because the entity properties correspond to 
// form/report fields I'm generating from this data.

foreach (var reportField in inspectionReportFields)
{
    var value = reportField.GetValue();
    Console.WriteLine(reportField.Name);
    Console.WriteLine(value);
}

EFやopenaccessのようなドメインモデルを利用する場合、プロパティ/フィールド値を取得する簡単な方法はありますか?そうでない場合、私はそれを正しい方法で行っていますか?そして最後に、もしそうなら、どのようにして値変数宣言の構文を修正しますか?

参照用に、ドメインモデルによって生成されたコードからのサンプルフィールド/プロパティを次に示します。

    private int? _new_systemGauges;
    public virtual int? New_systemGauges 
    { 
        get
        {
            return this._new_systemGauges;
        }
        set
        {
            this._new_systemGauges = value;
        }
    }

    private int? _new_systemAlarm ;
    public virtual int? New_systemAlarm 
    { 
        get
        {
            return this._new_systemAlarm;
        }
        set
        {
            this._new_systemAlarm = value;
        }
    }
38
bdemartino

オブジェクトの構造について何も知らずにオブジェクトを「ダンプ」する汎用的な方法を定義しようとしていると思います。もしそうなら、あなたは物事を正しい方法で進めています。リフレクション(GetType()および関連するTypeクラスメソッド)を使用して、オブジェクトを検査し、その情報を返します。

GetFields()が何も返さなかった理由は、おそらく正しいバインディングフラグを提供しなかったからです。特に、パラメーターを取らないオーバーロードを呼び出すと、publicフィールドのみが返されます。プライベートフィールドが必要な場合は、具体的に尋ねる必要があります。

あなたの場合、GetFields(BindingFlags.NonPublic)は__new_systemGauges_および__new_systemAlarm_フィールドを返し、GetProperties()は_New_systemAlarm_および_New_systemAlarm_プロパティを返します。

見逃したもう1つの重要な要素は、取得するデータがtypeメタデータであることです。特定のインスタンスではなく、classの構造を定義します。特定のインスタンスのプロパティの値が何かを知りたい場合は、それを要求する必要があります。

_foreach (var prop in obj.GetType().GetProperties())
{
  Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}
_

タイプのメタデータからPropertyInfo要素の1つを持っている場合、そのタイプの任意のインスタンスでそのプロパティ値を要求できます。最初に使用したインスタンスと同じである必要はありません。例えば:

_var objs = somelist.Where(x => x.Id == 1);
foreach (var prop in objs.First().GetType().GetProperties())
{
  int x = 0;
  foreach (var obj in objs)
  {        
    if (prop.PropertyType.Name.Equals("Int32"))
    {
      int val = (int)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = 0x{2:x8}", x++, prop.Name, val);
    }
    else if (prop.PropertyType.Name.Equals("Decimal"))
    {
      int val = (decimal)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = {2:c2}", x++, prop.Name, val);
    }
    else
    {
      Console.WriteLine("Obj #{0}: {1} = '{2}'", x++, prop.Name, prop.GetValue(obj, null));
    }
  }
}
_

技術的には、GetIndexParametersの結果をチェックして、プロパティにインデックスが付けられているかどうかを確認する必要があります。 nullGetValueパラメーターは、実際にはインデックス値の配列です。

返される値を変換するには、タイプキャストを使用するか、もう少し柔軟にしたい場合は、Convertクラスのメソッドを使用します。違いは、たとえば、shortプロパティがある場合、GetValue()intとして型キャストできないボックス化されたshortを返します。最初にshortに展開する必要があります。 Convert.ToInt32()を使用すると、convertible(であるプロパティからint値を取得するために必要なすべてのステップが実行されます。 )整数。

参照タイプ間の変換は、そのためにisasを使用できるだけなので簡単です。これらは、「反映された」プロパティ値で期待するように機能します。

74

GetPropertiesは確かに正しい方法です。

コンパイラエラーを取り除くには、コードを次のように変更します。

var value = reportField.GetValue(inspection, null);

PropertyInfoオブジェクトは特定のクラスインスタンスにバインドされていないため、値を取得するインスタンスを渡す必要があります。


標準の.NET命名規則に従うことを検討してください。

これは、次のことにつながります。

New_systemAlarmの代わりにNewSystemAlarm
newSystemAlarmまたは_newSystemAlarmの代わりに_new_systemAlarm
NewTestInspectionExtensionBasesの代わりにNew_testinspectionExtensionBases
NewTestInspectionIdの代わりにNew_testinspectionId

2
Daniel Hilgarth

OpenAccessを使用している場合、モデルクラスに関する完全な情報をいつでも入手できます。マッピングから情報が取得されるため、クラスを反映する必要はありません(オーバーヘッドなし)。

すべてのクラスマッピング情報について、context.Metadata.PersistentTypesを参照するだけです。

0
sovanesyan