指定された型メンバー 'Date'はLINQ to Entities Exceptionではサポートされていません


105

次のステートメントの実装中に例外が発生しました。

 DateTime result;
 if (!DateTime.TryParse(rule.data, out result))
     return jobdescriptions;
 if (result < new DateTime(1754, 1, 1)) // sql can't handle dates before 1-1-1753
     return jobdescriptions;
 return jobdescriptions.Where(j => j.JobDeadline.Date == Convert.ToDateTime(rule.data).Date );

例外

The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

例外の意味はわかりますが、どうすれば取り除くことができるのかわかりません。何か助けは?


これはEF6以下にあります。EFコアがサポートします.Date
Gert Arnold

回答:


102

同等のSQLがないため、LINQ to Entitiesは、ほとんどの.NET Dateメソッド(使用したキャストを含む)をSQLに変換できません。

解決策は、LINQステートメントの外部でDateメソッドを使用し、値を渡すことです。Convert.ToDateTime(rule.data).Dateがエラーの原因であるかのように見えます。

DateTimeプロパティでDateを呼び出すこともSQLに変換できないため、回避策は、整数にすぎないため、LINQに変換できる.Year .Monthプロパティと.Dayプロパティを比較することです。

var ruleDate = Convert.ToDateTime(rule.data).Date;
return jobdescriptions.Where(j => j.Deadline.Year == ruleDate.Year 
                       && j.Deadline.Month == ruleDate.Month 
                       && j.Deadline.Day == ruleDate.Day);

6
j =>はj.JobDeadline.Dateどうですか?
星雲

1
DateはJobDeadlineのプロパティですか?これはそれ自体でエラーを引き起こすべきではありません-おそらく名前の衝突です(しかしこれについては不明です)。それでもエラーが発生する場合は、DeadlineDateまたは同様の名前に変更してください。
柔道

1
日付はJobDeadlineのプロパティです。JobDeadlineは、DateTimeタイプで、Dateを抽出します。
星雲

次に、これをLINQ内で機能させるには、j.JobDeadline> ruleDateのように、JobDeadlineプロパティを比較する必要があります。これには少しテストが必要ですが、機能させることができます。または、.Month .Dayと.Yearの3つのプロパティを比較します(j.Deadline.Year == ruleDate.Year && j j.Deadline.Month == ruleDate.Month && j.Deadline.Day == ruleDate.Day)。エレガントではありませんが、これらは整数のみであるため機能します。
柔道

うーん。このアイデアは機能します。汚れているが動作します。あなたが答えとしてそれを書くならば、私はそれを正しいとマークすることができます。
星雲

230

EntityFunctionsのTruncateTimeメソッドを使用して、プロパティをSQLに正しく変換できます。Date

using System.Data.Objects; // you need this namespace for EntityFunctions

// ...

DateTime ruleData = Convert.ToDateTime(rule.data).Date;
return jobdescriptions
    .Where(j => EntityFunctions.TruncateTime(j.JobDeadline) == ruleData);


更新: EntityFunctions EF6では非推奨、使用DbFunctions.TruncateTime


まあ、私はそれruleDataDateTimeタイプでj.JobDeadlineあり、切り捨てられていることに気付きました。気分が悪い。例外は発生しませんでしたが、期待した結果も得られませんでした。
星雲

@aneal:時刻に関係なくJobDeadline、と同じ日付を持つすべてのレコードを返します。それは質問のクエリで達成したいことではありませんか?なぜそれが正しくないと思いますか?rule.data
スラウマ

1
+1と私は上記に同意します。99%の実装にとっては間違いなく良い答えです
jim tollan 2013年

26
EntityFunctionsEF6では非推奨であることに注意してくださいDbFunctions。現在はを使用する必要があります。
Julien N

2
> EF6でDbFunctionsのための名前空間があるSystem.Data.Entitymsdn.microsoft.com/en-us/library/Dn220142(v=VS.113).aspx
GraehamF


9

ef6の「EntityFunctions.TruncateTime」または「DbFunctions.TruncateTime」は機能していますが、ビッグデータでパフォーマンスの問題が発生します。

私は最善の方法はこのように行動することだと思います:

DateTime ruleDate = Convert.ToDateTime(rule.data);

DateTime  startDate = SearchDate.Date;

DateTime  endDate = SearchDate.Date.AddDay(1);

return jobdescriptions.Where(j.Deadline >= startDate 
                       && j.Deadline < endDate );

それは日付の一部を使用するよりも優れています。大規模なデータではクエリがより高速に実行されるためです。


この回答の+1。EntityFunctions.TruncateTime(後でに置き換えられますDbFunctions.TruncateTime)は、日時が文字列に変換され、切り捨てられるSQLに変換することで実装されます。これにより、処理されたレコードの数に比例して、クエリの実行が大幅に遅くなります。
urig 2017年

3

含める必要がありますusing System.Data.Entity;。でもうまくいくProjectTo<>

var ruleDate = rule.data.Date;
return jobdescriptions.Where(j => DbFunctions.TruncateTime(j.Deadline) == ruleDate);


1

つまり、LINQ to SQLでは、DateプロパティをSQL式に変換する方法がわかりません。これは、SQLでは構造のDateプロパティにDateTime類似点がないためです。


1

それは私のために働いた。

DateTime dt = DateTime.Now.Date;
var ord = db.Orders.Where
      (p => p.UserID == User && p.ValidityExpiry <= dt);

出典:Asp.netフォーラム


0

同じ問題がありますが、DateTime-Rangesを使用しています。私の解決策は、(任意の日付の)開始時刻を00:00:00に、終了時刻を23:59:59に操作することです。そのため、DateTimeをDateに変換する必要はなく、DateTimeのままです。

DateTimeが1つしかない場合は、(任意の日付の)開始時刻を00:00:00に設定し、終了時刻を23:59:59に設定することもできます。次に、それがタイムスパンであるかのように検索します。

var from = this.setStartTime(yourDateTime);
var to = this.setEndTime(yourDateTime);

yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);

あなたはDateTime-Rangeでもそれを行うことができます:

var from = this.setStartTime(yourStartDateTime);
var to = this.setEndTime(yourEndDateTime);

yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);

0

次のようにEnumを取得できます。

DateTime todayDate = DateTime.Now.Date; var check = db.tableName.AsEnumerable().Select(x => new
        {
            Date = x.TodayDate.Date
        }).Where(x => x.Date == todayDate).FirstOrDefault();

これは、日付フィルターを適用するために、テーブルの内容全体を事前に効果的に列挙しています... 非常に悪い考えのようです!
Javier Rapoport

0

ここで多くの人が指摘したように、TruncateTime関数の使用は低速です。

できれば、EF Coreを使用するのが最も簡単なオプションです。それができます。それができない場合は、切り捨ての代わりに、クエリされたフィールドをまったく変更せず、境界を変更することをお勧めします。下限と上限がオプションである通常の「between」タイプのクエリを実行している場合は、次の方法でうまくいきます。

    public Expression<Func<PurchaseOrder, bool>> GetDateFilter(DateTime? StartDate, DateTime? EndDate)
    {
        var dtMinDate = (StartDate ?? SqlDateTime.MinValue.Value).Date;
        var dtMaxDate = (EndDate == null || EndDate.Value == SqlDateTime.MaxValue.Value) ? SqlDateTime.MaxValue.Value : EndDate.Value.Date.AddDays(1);
        return x => x.PoDate != null && x.PoDate.Value >= dtMinDate && x.PoDate.Value < dtMaxDate;
    }

基本的に、PoDateをトリミングして日付部分だけに戻すのではなく、クエリの上限とユーザー<の代わりに<をインクリメントします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.