2009-06-04 3 views
0

ASP.NET MVC 웹 사이트에서 DbLinq를 사용하여 MySQL 용 SQL에 linq를 사용하고 있습니다. 이상한 캐싱 문제가 있습니다. 내 저장소 클래스에서 다음과 같은 방법을 고려하십시오DbLinq - 캐시 문제

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.MessagesMessageFromMessageTo 값이 변화하는 10 개 이상의 결과를 가지고 있음에도 불구하고, 나는 단지 첫 번째로 쿼리 된 결과만을 반환합니다. 그래서 GetInbox(4374)으로 전화하면 메시지 A와 메시지 B가 나옵니다. 나중에 GetInbox(526)을 호출하면 메시지 A와 B가 나타납니다. 메시지 C와 D는 입니다.의 사용자 ID는 526입니다. 응용 프로그램을 사용하여 변경 사항을 확인하십시오.

여기 무슨 일 이니? 나는 누군가가 나에게 그것을 지적 할 때 내가 부끄러워 할 정도로 어리석은 뭔가를하고 있다고 확신한다. 내가 아주 바보 같은 짓을하지 않는다면, 나는이 문제가 매우 이상하다는 것을 알게된다. 나는 DataContext를 재사용하지 않는다는 것에 대해 읽었지 만 나는 그렇지 않다. 왜이 캐싱 문제입니까? 다음은 내 컨트롤러 코드입니다,하지만 난 그게 중요한 의심 :

SO에 비슷한 질문이 있지만
[Authorize] 
public ActionResult Inbox(int userId) 
{ 
    Mailbox inbox = new Mailbox(userId, this.messageRepository.GetInbox(userId)); 
    return PartialView("Inbox", inbox); 
} 

, 나는이 정확한 질문에 대한 답을 발견하지 않았습니다. 많은 감사합니다! 그것은, 그 다음 잘 작동 return repo.Messages.ToList().Where(m => m.MessageFrom == userId); 수정 :에 코드를 변경 :

UPDATE. 캐시 문제 같은데. 그러나 물론 나는 그런 식으로 고치고 싶지 않습니다. 쿼리 후 datacontext가 삭제되지 않도록 코드를 변경하면 이 아닌이 문제를 해결합니다.

+0

이것은 바보 같지만, Asp.Net 캐싱 메커니즘과 관련이 없습니다. – Micah

+0

글쎄, 나는 처음에는 그것을 두려워했다. 하지만 내 MailBox 클래스 내에서 명확하게 전달할 빈 IEnumberable 을 볼 수 있습니다. 또는 그 문제에 대한 이전 데이터가 있습니다. 그래서 그게 문제가 아닙니다. – Razzie

+0

DbLinq (의견에서) 경우 태그의 제목을 변경하고 태그를 변경해야합니다. DbLinq는 거의 공유하지 않을 수 있습니다 ... LINQ-to-SQL에 대해 묻는 것은 당신을 도울 것입니다 ;-p –

답변

1

글쎄, DbLinq에 문제가있는 것으로 보입니다. 3 주 전의 소스 코드를 사용했고 QueryCache에 apparant 버그가있었습니다 (비록 이 항상이었습니다). 이 here을 다루는 완전한 스레드가 있습니다.

dblinq 소스를 업데이트했습니다. 이제 Querycache가 비활성화되어 (성능에 영향을 미친다는 것을 의미 함) 적어도 이제는 작동합니다. 성능이 받아 들여 지는지 확인해야합니다. 내가해야 할 일은 일반적인 linq2sql 패턴이므로 약간 당황 스럽다는 것을 고백해야합니다. 모두에게 감사드립니다.

1

LINQ-to-SQL의 캐싱은 주로 DataContext과 관련이 있으며 주로 ID 캐싱으로 제한됩니다. 대부분의 경우 이전에 쿼리를 다시 실행하더라도 대부분 쿼리가 다시 실행됩니다. .Single(x=>x.Id == id) (특수 처리 기능)과 같은 몇 가지 예가 있습니다.

매번 새로운 데이터 컨텍스트를 얻고 있으므로 분명히 그 원인을 생각하지 않습니다. 그러나 코드가 작동한다는 사실에 약간 놀랐습니다 ... 그게 확실한가요?

LINQ의 Where 메서드는 지연됩니다. 즉, 데이터를 반복 할 때까지는 실행되지 않습니다 (예 : foreach). 하지만 그때까지 이미 데이터 컨텍스트를 폐기했습니다! 이 예제에서 뭔가를 잘라 냈습니까?

또한 SqlConnection (사용자가 Dispose()이 아님)을 지정하면 정리에 영향을 줄 수 있습니다. 연결 문자열에 데이터 컨텍스트를 지정하는 것이 좋습니다.

+0

그것을 생각해 보니, 그것은 정말로 이상합니다. 이 코드는 대표적인 것으로, 새로운 SqlConnection을 반환 한 도우미 클래스에 정적 속성이 있다는 사소한 예외가 있습니다. SqlMetal (또는 제 경우 DbMetal)에 의해 생성 된 DataContext 클래스는 IDbConnection을 사용하는 생성자를 제공하므로 많은 생각을하지 않았습니다. 어쩌면 문제는 DbLinq의 IQueryable 구현에 있습니다. 하나는 실행을 지연시키지 않습니다 (Func )? 나는 내일 일할 때 그것을 들여다 볼 것이다. – Razzie

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(); ; 
     } 
    } 
} 
+0

고마워, 내일은 ToList를 사용해도 좋을거야. 코드에는 많은 차이가 없습니다. – Razzie

+0

ToList()는 이후의 모든 linq 작업이 SQL 문으로 변환되는 대신 객체에 대한 linq로 실행되게합니다.좋은 이유가있을 때까지는 ToList()를 사용하지 않는 것이 좋습니다. –

+0

알아,하지만 내 상황에서는 괜찮아. 어떻게 든 내 문제가 어떻게 든 고칠 수 있다면 적어도 테스트해볼 수 있습니다. 생각해 보면 좋겠지 만 : – Razzie

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를 열거해야합니다.

문제를 일으킬 수있는 또 다른 사항은 datacontext가 이미 삭제되었을 때 열거하기 시작한다는 사실입니다. 이 문제를 해결할 수있는 유일한 방법은 전혀 처리하지 말고 GC가 범위를 벗어날 때 정리하는 것입니다. 또는 사용자 지정 IDisposable 개체를 만들어내어 사용할 수 있습니다. 예 :

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

프로덕션 코드에 DBLinq를 사용하지 마십시오 ... Linq-To-SQL의 기능 중 상당수가 구현되지 않았기 때문에 소스 코드를 살펴보면 낮은 수준의 성숙도를 보여줍니다. 구현되거나 "종단되지 않은"것으로 표시됩니다.

... 경고되었습니다.

+0

맞습니다. DBLinq와 실제로 구현되지 않은 많은 메소드를 사용하면서 많은 버그를 발견했습니다. 이 질문을 한 직후에, 나는 DBLinq에서 MySql을위한 Devart Linq2Sql 프레임 워크로 바꾼다. 훨씬 더 좋다. 나는 그 문제에 별다른 문제가 없었다. 불행히도, 그것은 무료는 아니지만, 결국 그것은 나를 훨씬 더 구해 냈습니다! – Razzie