web-dev-qa-db-ja.com

値の型をnullに対応する同等のものに変換する

私はその場限りの報告システムを持っています。クエリのソースタイプや必須フィールドについて、コンパイル時の知識がありません。 System.Linq.Expressions.Expressionファクトリメソッドを使用して実行時に式ツリーを記述し、リフレクションを使用してLINQメソッドを呼び出すこともできますが、動的LINQの方が簡単なソリューションです。

レポートシステムは、LEFT JOINの結果を返すクエリを許可します。結合されたテーブルには、データベースのNOT NULLであるフィールドがあります。ただし、これはLEFT JOINであるため、これらのフィールドには特定のレコードのNULLが含まれます。 EF6で生成された式はこれに該当します。これは、式がnull可能ではない値の型に投影されるためです。

コンパイル時のLINQでこれを行っている場合は、null許容型に明示的にキャストします。

enum Color { Red, Green,  Blue }

// using System;
// using static System.Linq.Enumerable;
// using System.Linq;

var range = Range(0, 3).Select(x => (Color)x).AsQueryable();
var qry = range.Select(x => (Color?)x);

動的LINQは明示的な変換をサポートしています。

// using static System.Linq.Dynamic.Core

var qry1 = range.Select("int?(it)");

ただし、クエリで参照できるのは 特定のタイプのセット のみです。クエリでColorを使用しようとすると、次のようになります。

var qry2 = range.Select("Color(it)");

次のエラーが発生します。

タイプ 'Color'に該当するメソッド 'Color'がありません

明示的にColor?にキャストしようとした場合:

var qry3 = range.Select("Color?(it)");

私は得ます:

要求された値「色」が見つかりませんでした。

動的LINQライブラリを使用してこれを行うにはどうすればよいですか?

5
Zev Spitz

次のスニペットを使用して、入力番号が列挙型の一部であるかどうかを識別できることをお勧めします。

public static bool IsValuePresent<T>(int number) where T : Enum
{
    return !Enum.GetValues(typeof(T)).Cast<int>().Contains(number);
}

以下は、入力値が列挙に存在するかどうかを確認するための呼び出しである可能性があります

EnumerationConverter.IsValuePresent<Color>(99); //returns False
EnumerationConverter.IsValuePresent<Color>(2); //returns True

上記のステートメントでFalseが取得されたら、値をnullに設定するか、以下のコードのように整数から列挙型への単純なジェネリック型コンバーターを実行できます。

public static T GetAsEnum<T>(int number) where T : Enum
{
    if (Enum.IsDefined(typeof(T), number))
    {
        return (T)Enum.ToObject(typeof(T), number);
    }
    return default(T);
}

有効な列挙値を確認してから変換する必要があるという理解に基づいて、上記の解決策を試すことができます。他の側面がある場合は、ここに投稿して更新してください。

0
Saravanan