DbLinq - проблема с кешем - PullRequest
0 голосов
/ 04 июня 2009

Я использую linq to sql для MySql (используя DbLinq) на веб-сайте ASP.NET MVC. У меня странная проблема с кэшированием. Рассмотрим следующие методы в моем классе репозитория:

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. Я не использую здесь этот текстовый код данных (приведенный выше код выглядит немного глупо, но я хотел быть абсолютно уверенным, что это не какая-то проблема повторного использования datacontext / mysqlconnection).

Что происходит, то, какой бы из двух методов я ни вызывал, с любым идентификатором пользователя, результаты остаются неизменными. Период. Несмотря на то, что я вижу, что repo.Messages имеет более 10 результатов с различными значениями MessageFrom и MessageTo, я получаю только первые запрошенные результаты. Поэтому, если я звоню GetInbox(4374), это дает мне сообщение A и сообщение B. После вызова GetInbox(526) все равно я получаю сообщения A и B, хотя есть сообщения C и D, которые делают ИД пользователя 526. Мне нужно перезапустить приложение, чтобы увидеть изменения.

Что здесь происходит? Я уверен, что я делаю что-то настолько глупое, что мне будет стыдно, когда кто-то указывает мне на это. Если я не делаю что-то очень глупое, тогда я нахожу эту проблему очень странной. Я читал о том, чтобы не использовать DataContext, но это не так. Почему эта проблема с кешированием? Ниже приведен код моего контроллера, но я сомневаюсь, что он имеет значение:

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

Хотя есть и похожие вопросы по SO, я не нашел ответа на этот точный вопрос. Большое спасибо!

UPDATE : изменив код на: return repo.Messages.ToList().Where(m => m.MessageFrom == userId); исправляет это, тогда он работает нормально. Похоже, какая-то проблема с кешем. Тем не менее, я, конечно, не хочу это исправить таким образом. Измените код таким образом, чтобы текстовый текст не располагался после того, как запрос не решил проблему.

Ответы [ 5 ]

1 голос
/ 05 июня 2009

Ну, похоже, это была проблема с DbLinq. Я использовал исходный код с 3-х недельного возраста, и в QueryCache была ошибка apparant (хотя там всегда было всегда ). Вот полная нить, которая покрывает это здесь .

Я обновил источник dblinq. Querycache теперь отключен (подразумевает снижение производительности), и, по крайней мере, теперь он работает. Я должен буду видеть, приемлемо ли выполнение. Должен признаться, что я немного сбит с толку, хотя то, что я пытаюсь сделать, это обычный шаблон linq2sql. Спасибо всем.

1 голос
/ 04 июня 2009

Я написал довольно похожий код, который, кажется, работает нормально. Единственная разница в том, что, как предполагает Марк, я передаю строку подключения и вызываю ToList для метода Where. Моя база данных не генерируется автоматически, а наследуется от 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(); ;
        }
    }
}
1 голос
/ 04 июня 2009

Начало написания теста. Это скажет вам, правильно ли ведёт себя 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.

Еще одна вещь, которая может вызывать проблемы, это то, что вы начинаете перечислять, когда текст данных уже удален. Единственный способ решить эту проблему - не утилизировать его вообще (и полагаться на то, что ГХ очищает его, когда он выходит за пределы области видимости), или придумать собственный объект IDisposable, чтобы вы могли использовать его. Что-то вроде:

using(var inboxMessages = this.messageRepository.GetInbox(userId1))
{
    Assert.That(inboxMessages.All(m => m.MessageTo == userId1);
}
1 голос
/ 04 июня 2009

Кэширование в LINQ-to-SQL связано с DataContext и в основном ограничено кэшированием идентификаторов - в большинстве случаев он будет перезапускать запрос, даже если вы делали это раньше. Есть несколько примеров, например .Single(x=>x.Id == id) (с особой обработкой).

Поскольку вы каждый раз явно получаете новый контекст данных, я не думаю, что это виновник. Тем не менее, я также немного удивлен тем, что код работает ... вы уверены, что это представитель?

Метод LINQ Where откладывается - это означает, что он не будет выполнен, пока вы не выполните итерацию данных (например, с foreach). Но к тому времени вы уже распоряжались контекстом данных! Вы что-то вырезали из примера?

Также - давая ему SqlConnection (чего вы не делаете Dispose()), вы можете повлиять на очистку - может быть предпочтительнее просто дать ему (контексту данных) строку подключения.

0 голосов
/ 05 ноября 2009

Я бы не использовал DBLinq для производственного кода ... многие функции Linq-To-SQL не реализованы, а просмотр исходного кода показывает низкий уровень зрелости ... многие методы не реализованы или помечены как «неопределенные».

... вы были предупреждены!

...