0

ASP.NET MVC Web サイトで (DbLinq を使用して) MySql の linq to sql を使用しています。奇妙なキャッシングの問題があります。私の Repository クラスで次のメソッドを検討してください。

public IEnumerable<Message> GetInbox(int userId)
{
  using(MyDataContext repo = new MyDataContext(new MySqlConnection("[Connectionstring]")))
  {
    return repo.Messages.Where(m => m.MessageTo == userId);
  }
}

public IEnumerable<Message> GetOutbox(int userId)
{
  using (MyDataContext repo = new MyDataContext(new MySqlConnection("[Connectionstring]")))
  {
    return repo.Messages.Where(m => m.MessageFrom == userId);
  }
}

「MyDataContext」は、DbLinq によって生成されたデータベースへのマッピングであり、DataContext から継承されます。ここではデータコンテキストを再利用していません (上記のコードは少しばかげているように見えますが、データコンテキストや mysqlconnection の再利用の問題ではないことを確認したかったのです)。

2 つのメソッドのどちらを呼び出しても、userId が何であれ、結果は同じままです。限目。さまざまなと の値repo.Messagesを使用して 10 を超える結果があることがわかりますが、最初にクエリを実行した結果しか返されません。したがって、呼び出すと、メッセージ A とメッセージ B が返されます。後で呼び出すと、userId が 526 のメッセージ C と Dがあるにもかかわらず、メッセージ A と B が返されます。変更を確認するには、アプリケーションを再起動する必要があります。MessageFromMessageToGetInbox(4374)GetInbox(526)

何が起きてる?きっと誰かに指摘されたら恥ずかしくなるようなバカなことをしているに違いない。私が非常にばかげたことをしていない場合、この問題は非常に奇妙だと思います。DataContext を再利用しないことについて読みましたが、そうではありません。このキャッシュの問題はなぜですか? 以下は私のコントローラコードですが、それが問題になるとは思えません:

[Authorize]
public ActionResult Inbox(int userId)
{
  Mailbox inbox = new Mailbox(userId, this.messageRepository.GetInbox(userId));
  return PartialView("Inbox", inbox);
}

SO にも同様の質問がありますが、この正確な質問に対する答えは見つかりませんでした。どうもありがとう!

更新: コードを次のように変更します:return repo.Messages.ToList().Where(m => m.MessageFrom == userId);修正すると、問題なく動作します。キャッシュの問題のようです。ただし、もちろん、そのように修正したくはありません。クエリの後にデータ コンテキストが破棄されないようにコードを変更しても、問題は解決されませ

4

5 に答える 5

1

テストを書くことから始めます。これにより、Linq2Sqlが正しく動作しているかどうかがわかります。何かのようなもの:

var inboxMessages = this.messageRepository.GetInbox(userId1);
Assert.That(inboxMessages.All(m => m.MessageTo == userId1);

inboxMessages = this.messageRepository.GetInbox(userid2);
Assert.That(inboxMessages.All(m => m.MessageTo = userid2);

それが成功した場合は、問題の原因が実行の延期であるかどうかを実際に確認する必要があります。inboxMessagesをすぐに列挙する必要があります。

問題を引き起こしている可能性のあるもう1つのことは、データコンテキストがすでに破棄されているときに列挙を開始するという事実です。これを解決する唯一の方法は、それをまったく破棄しない(そして、スコープ外になったときにGCがクリーンアップすることに依存する)か、カスタムIDisposableオブジェクトを考え出すことです。これにより、その周りに使用法を置くことができます。何かのようなもの:

using(var inboxMessages = this.messageRepository.GetInbox(userId1))
{
    Assert.That(inboxMessages.All(m => m.MessageTo == userId1);
}
于 2009-06-04T18:00:37.250 に答える
1

私はうまくいくように見えるいくつかの非常によく似たコードを書きました。唯一の違いは、Marcが示唆しているように、接続文字列を渡し、WhereメソッドでToListを呼び出していることです。私のデータベースは自動的に生成されませんが、DataContextから派生します。コードは以下のとおりです。

class Program
{
    static void Main(string[] args)
    {
        List<Item> first = GetItems("F891778E-9C87-4620-8AC6-737F6482CECB").ToList();
        List<Item> second = GetItems("7CA18DD1-E23B-41AA-871B-8DEF6228F96C").ToList();
        Console.WriteLine(first.Count);
        Console.WriteLine(second.Count);
        Console.Read();
    }

    static IEnumerable<Item> GetItems(string vendorId)
    {
        using (Database repo = new Database(@"connection_string_here"))
        {
            return repo.GetTable<Item>().Where(i => i.VendorId.ToString() == vendorId).ToList(); ;
        }
    }
}
于 2009-06-04T17:21:17.090 に答える
1

さて、それはDbLinqの問題のようでした。私は3週間前のソースコードを使用しましたが、QueryCacheに明らかなバグがありました(常にそこにありましたが)。これをカバーする完全なスレッドがここにあります

dblinqソースを更新しました。Querycacheは現在無効になっており(パフォーマンスへの影響を意味します)、少なくとも今は機能しています。パフォーマンスが許容できるかどうかを確認する必要があります。私がやろうとしているのは一般的なlinq2sqlパターンであるため、私は少し困惑していることを告白する必要があります。皆さんありがとう。

于 2009-06-05T11:23:08.623 に答える
1

LINQ-to-SQL でのキャッシングは に関連付けられておりDataContext、主に ID キャッシングに限定されています。ほとんどの場合、以前に実行したことがある場合でも、クエリを再実行します。.Single(x=>x.Id == id)(特別な処理がある)のようないくつかの例があります。

毎回明らかに新しいデータコンテキストを取得しているので、それが原因ではないと思います。ただし、コードが機能することにも少し驚いています...それは代表的なものですか?

LINQ のWhereメソッドは延期されます。つまり、データを反復処理するまで (たとえば を使用してforeach) 実行されません。しかし、その時までに、あなたはすでにデータコンテキストを破棄しています! 例から何かを切り取ったことがありますか?

また、SqlConnection(そうしないとDispose()) を与えると、クリーンアップに影響を与える可能性があります。(データ コンテキスト) に接続文字列を与えるだけの方が望ましい場合があります。

于 2009-06-04T16:55:12.677 に答える
0

実稼働コードにDBLinqを使用することは避けたいと思います...Linq-To-SQLの機能の多くは実装されておらず、ソースコードをウォークスルーすると、成熟度が低いことがわかります...メソッドの多くは実装されていないか、次のようにマークされています「未終了」。

...警告されました!

于 2009-11-05T14:00:39.057 に答える