2012-02-14 3 views
5

私はいつかこの問題に頭を悩ましています。いくつかの同様のケースがありますが、解決策は私の場合には適用されませんでした。動的LINQ(エンティティへの)null可能なDateTime列のある場所

フィルタクエリを文字列形式で返すメソッドがあります。この方法は、異なるデータタイプのロジック、正しい値を設定し、列名など

string filterQuery = GetFilterQuery(params); 
rows = rows.Where(filterQuery); 

を有する私の問題は、私は、データベース内Nullable DateTimeを有し、Iはコード側でString表現を有することです。

私が試してみました次のクエリは、(String表現が間違っている現在、かもしれません):

"BirthDate.ToString() = \"16.2.2012 22:00:00\"" 

結果: '?のDateTime' メソッドタイプにエンティティへのLINQは方法「可能System.StringのToString()」メソッドを認識しない、そしてこの方法は、ストア式に変換することができません:アクセス

"BirthDate.Value.ToString() = \"16.2.2012 22:00:00\"" 

結果されていません。

"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\"" 

結果: '' または「(」問題を解決する方法

に任意のアイデアを期待?

アップデート(複数のソースコードは、クエリ生成についての追加)

var filterQueries = query.GridFilteringOptions.filters 
    // remove filters that doesn't have all the required information 
    .Where(o => o.name != string.Empty && o.value != string.Empty && !string.IsNullOrEmpty(o.type)) 
    // remove filters that are filtering other tables than current 
    .Where(o => o.table == tableName) 
    .Select(filter => filter.ResolveQuery()).ToList(); 

if (filterQuery.Any()) 
{ 
    var filterQuery = string.Join(" And ", filterQueries); 
    rows = rows.Where(filterQuery); 
} 

そしてここでは、クラスフィルタおよび方法がされていますこのコンテキストに関連する

public string ResolveQuery() 
{ 
    if (type == "Int64") 
    { 
     return ResolveInteger(); 
    } 
    else if(type == "String") 
    { 
     return ResolveString(); 
    } 
    else if(type == "DateTime") 
    { 
     return ResolveDateTime(); 
    } 
    else 
    { 
     return string.Empty; 
    } 
} 

private string ResolveDateTime() 
{ 
    DateTime result = new DateTime(); 
    if (DateTime.TryParse(this.value, out result)) 
    { 
     return string.Format("{0}.ToString() = \"{1}\"", this.name, result.ToUniversalTime()); 
    } 
    return string.Empty; 
} 

private string ResolveString() 
{ 
    switch (@operator) 
    { 
     default: 
      return string.Format(@"{0}.StartsWith(""{1}"")", this.name, this.value); 
    }    
} 

private string ResolveInteger() 
{ 
    string tmp = this.name; 
    switch (@operator) 
    { 
     case -1: 
      return string.Empty; 
     case 0: 
      tmp += "<"; 
      break; 
     case 1: 
      tmp += "="; 
      break; 
     case 2: 
      tmp += ">"; 
      break; 
     default: 
      return string.Empty; 
    } 
    tmp += value; 
    return tmp; 
} 

答えて

2

LINQ to Entitiesはを認識しません方法。結果の文字列をクエリに挿入する前に評価する必要があります。

は、あなたの質問の例を作成するには、このようにそれを扱うかもしれません:EFへのLINQは、三項演算子を認識しないため

おそらく
// "BirthDate.ToString() = \"16.2.2012 22:00:00\"" 
string birthdate = BirthDate.ToString(); 
string query = String.Format("{0} = \"16.2.2012 22:00:00\"", birthdate); 

// "BirthDate.Value.ToString() = \"16.2.2012 22:00:00\"" 
string birthdate = BirthDate.Value.ToString(); 
string query = String.Format("{0} = \"16.2.2012 22:00:00\"", birthdate); 

"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\""が動作しない(? :

編集:私はあなたのコメントからBirthDateが変数ではなく、テーブルの列であることを理解しています。(あなたがそれに応じてfilterQueryを変更する必要がありますが)この場合、あなたは、すべてのエントリを取得し、リストに変換し、このようなオブジェクトにLINQを使用してフィルタを適用することができます。

string filterQuery = GetFilterQuery(params); 
var filteredRows = rows.ToList().Where(filterQuery); 

未テスト:それは可能性がありますデータベースのCONVERT機能を使用することが可能である:

string query = "CONVERT(varchar(20), BirthDate) = \"16.2.2012 22:00:00\""; 
+0

BirthDate.ToString() - このコンテキストでBirthDateとは何ですか?私の場合は単に列名なので、コードコンテキストには存在しません。 – Tx3

+0

私は参照してください。私の更新された答えを見てください。 –

+0

ありがとう、私はまた、 – Tx3

0

私の問題は、私は、データベース内のNullableのDateTimeを持っていると私は コード側の文字列表現を持っているということです。

なぜですか?

コード側を変更し、文字列表現を解析し、LINQクエリで適切なオブジェクトを指定します。

"BirthDate.ToString()= \" 2012年2月16日22:00:00 \ ""

BAD - あなたは、文字列manipulatzionをしなければならない場合は、AWLWAYSはにInvariantCultureを使用しています。このコードは壊れやすく、他の国でも破壊されます。

+0

日付文字列形式は、この質問には関係ありません。はい、サンプルコードで正しくフォーマットされていません。 UTC整数に変更される可能性があります。私が達成しようとしているのは、有効な "検索基準"を文字列形式で返し、あらゆる種類の日付タイプに簡単に使用できるようにする方法があるということです。必要に応じて、null可能DateTimeの例外を作成することはできますが、むしろそれを回避します。 – Tx3

+0

あなたはInvariantCultureについて、そして現在コードが脆弱であることについては当然です。 – Tx3

+0

できません。これは、SQLの日付時間で "between"以外の検索を効率的に行う方法ではなく、LINQのできることはここで制限されています。あなたの一般的なアプローチは、LINQの奇形を考慮に入れています。 – TomTom

0

私は現在try/catchブロックでこれを解決しています。それは、私はむしろのための代替手段を見つけるだろうが、それは非常にしっかりと機能しないいくつかのオーバーヘッドと醜さを追加します。

try 
{ 
    // for strings and other non-nullables 
    records = records.Where(rule.field + ".ToString().Contains(@0)", rule.data); 
} 
catch (System.Linq.Dynamic.ParseException) 
{ 
    // null types 
    records = records.Where(rule.field + ".Value.ToString().Contains(@0)", rule.data); 
} 

注:入力変数からこれらのフィールドを受け入れ(rule.fieldrule.data)は危険である、とあなたを開くこと最大(難しい)ブラインドSQLインジェクション。最初の値(rule.field)はホワイトリストの値と照合してこれを防ぐことができます。

関連する問題