7

注意してください:私はこれを回避する方法を知っています。私は解決策を探しているのではなく、問題自体の明確さを求めています。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new TestDbContext())
        {
            var eventsFound = context.Events
                .Where(e => 
                    e.EventDate >= DateTime.Now.AddDays(-1) && 
                    e.EventDate <= DateTime.Now.AddDays(+1)
                )
                .ToList();
        }
    }
}

public class TestDbContext : DbContext
{
    public DbSet<Event> Events { get; set; }
}

public class Event
{
    public int EventId { get; set; }
    public DateTime EventDate { get; set; }
}

わかりましたので、上記のプログラムは次のエラーで失敗します。

LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)'
method, and this method cannot be translated into a store expression.

LINQ がデータベース関数とオブジェクト関数の違いを認識できないのはなぜですか。システムは、AddDays 関数が DateTime オブジェクトの一部であることを認識できるほど賢くある必要があります。次に、まずその関数を解決し、クエリ内のすべての関数が解決されたら、SQL に変換してデータベースに対して実行します。

それよりもはるかに複雑だと確信していますが、その理由を理解したいと思います。

=========編集==============

したがって、「AddDays」は .NET と SQL の両方に存在する関数であるため、上記は実際には良い例ではありませんでした。あいまいさが存在しない自己定義関数に変更するとどうなりますか。

すなわち:

public class Event
{
    public int EventId { get; set; }
    public DateTime EventDate { get; set; }

    public DateTime ReturnDateNowExample()
    {
        return DateTime.Now;
    }
}

static void Main(string[] args)
{
    var myEvent = new Event {EventDate = new DateTime(2013, 08, 28)};
    using (var context = new TestDbContext())
    {
        var eventsFound = context.Events
            .Where(e =>
                e.EventDate >= myEvent.ReturnDateNowExample()
            )
            .ToList();
    }
}

あいまいな DateTime オブジェクトの場合は、string/int オブジェクトに置き換えます。

4

4 に答える 4

6

クエリで直接使用する場合、LINQ-to-SQL と Entity Framework によって異なるクエリが生成されることに注意してくださいDateTime.Now

LINQ-to-SQL:

WHERE ([t0].[EventDate] >= @p0) AND ([t0].[EventDate] <= @p1)

エンティティ フレームワーク

WHERE ([Extent1].[EventDate] >= CAST( SysDateTime() AS datetime2)) AND ([Extent1].[EventDate] <= CAST( SysDateTime() AS datetime2))

ここでの違いは、LINQ-to-SQL はDateTime.Now.NET 側で計算してクエリのパラメーターとして送信する必要があるものを考慮するのに対し、EF はDateTime.NowSQL 側で計算できるものを考慮することです。このことから明らかなように、LINQ-to-SQL ではDateTime.Now.AddDays()"動作" します (式のその部分が .NET 側で完全に評価されるため) が、EF では動作しません。SQL にはAddDays()動作する " .NET と同じですAddDays()(DATEADD浮動小数点ではなく整数で動作します)。

LINQ-to-SQL の機能と EF の機能のどちらが正しいですか? EFが行うことはより正しいと言えます(たとえそれがより「奇妙」であっても)...

例: .NET アプリと SQL アプリが 2 つの異なるタイムゾーン (つまり、異なる時間) にある場合はDateTime.Nowどうなりますか? .NET 時間または SQL 時間のほうが正しいでしょうか? 2 つ目だと思います (ただし繰り返しますが、これが自分のアプリの「バグ」であるとわかっていたとしても、大きな ooooooh を作っていたでしょう)。

補足として (あまり重要ではありません)、同じ場所で日付を 2 回計算して、それらが等しいと考えるべきではありません。今回は完全な日付を使用したので問題ありませんがDateTime.Now.Date、. 59.9999999 で、もう一方は翌日の 00:00:00.0000000 で計算されます。

于 2013-08-28T08:56:18.463 に答える
4

問題は、EF がSQL側でクエリを変換して実行しようとしていることです。そしてそこにはSystem.DateTime.AddDays同等のものはありません。

そのDateTime.AddDaysため、メソッドは正規関数でもデータベース関数でもなく、さらに実行するために適切なコマンド ツリー ノードに変換できません。通常、クエリではSqlFunctionsまたはEntityFunctionsを使用する必要があります。ただし、カスタム データベース関数を.edmxファイル で定義することによって呼び出す方法があります。また、 LINQ to Entitiesでは、 、 などの標準的なクエリ メソッドと、 などの多くのオーバーロードがサポートされていない

ことも考慮してください。サポートされている演算子の完全なリストは AggregateLastSelect<TSource, TResult>(IQueryable<TSource>, Expression<Func<TSource, Int32, TResult>>)
ここに


これを修正するには、次のものを使用する必要がありますEntityFunctions.AddDays:DateTime.Now.AddDays(+1)EntityFunctions.AddDays(DateTime.Now, 1);

于 2013-08-28T07:59:54.070 に答える
0

これらの日を変数に格納することもできます。

DateTime yesterday = DateTime.Now.AddDays(-1);
DateTime tomorrow = DateTime.Now.AddDays(+1);

どこで:

.Where(e => 
    e.EventDate >= yesterday  && 
    e.EventDate <= tomorrow 
)
于 2013-08-28T08:03:04.500 に答える