2012-02-20 2 views
1
private void InsertLinks(IEnumerable<string> urls) 
    { 
     EntityDataModelContext context = DataContext.GetDataContext(); 
     foreach (string url in urls) 
     { 
      string url1 = url; 
      if (context.Links.Any(l => MatchUrlHash(l.UrlHash, url1))) 
      { 
       continue; 
      } 
      Link link = new Link 
      { 
       Url = url, 
      }; 
      context.Links.AddObject(link); 
     } 
     context.SaveChanges(); 
    } 

    private bool MatchUrlHash(long urlHash, string url) 
    { 
     SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); 
     byte[] encoded = Encoding.ASCII.GetBytes(url); 
     byte[] checksum = sha.ComputeHash(encoded); 
     long hash = BitConverter.ToInt64(checksum, 0); 
     return urlHash == hash; 
    } 

가 어떻게 아직도 상당히 수행하고 NotSupportedException의를 포기하지 않는 무언가에이 쿼리를 변환 할 수있는이 간단한 쿼리 작업을 만드는 방법?LINQ는

+1

를 다시 .. 모든 레코드를 끌어 다음 사용자 지정 논리 context.Links.ToList().Any(l=>MatchUrlHash(l.UrlHash, url1))

아니를 실행 중. –

답변

4

EF는 MatchUrlHash으로 SQL 쿼리를 작성하는 방법을 알지 못합니다. 미리 URL 해시를 미리 준비하고 일반 스타일 비교 인 ==을 사용할 수 있습니다.

private long CreateUrlHash(string url) 
{ 
    SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); 
    byte[] encoded = Encoding.ASCII.GetBytes(url); 
    byte[] checksum = sha.ComputeHash(encoded); 
    return BitConverter.ToInt64(checksum, 0); 
} 

// ... 
long urlHash = CreateUrlHash(url); 
if (context.Links.Any(l => l.UrlHash == urlHash)) 
{ 
    continue; 
} 
+0

우연히 훨씬 더 효율적입니다. – BrokenGlass

+0

왜'EF'가 이런 쿼리를 처리 할 수 ​​없습니까? 내가 아는 한'L2SQL'이 가능했다. – bevacqua

+1

@Nico - MatchUrlHash 메서드가 포함 된 SQL 쿼리의 모양은 무엇입니까? L2S 또는 EF는 해당 메소드를 SQL로 변환하는 방법을 알고 있습니까? –

0

SQL 개체 공급자에게 MatchUrlHash를 전달할 수 없습니다. 그래서 당신의 상황에 맞는 예를 들어`using` 문을 폐기하거나보다 효율적으로 사용하는 전화, 그런데 모든 것을

private void InsertLinks(IEnumerable<string> urls) 
    { 
     EntityDataModelContext context = DataContext.GetDataContext(); 

     var withhashes=urls.Select(u=>new {Url=u,Hash= Hash(u)}); 
     withhashes.Where(h=>!context.Links.Any(l=>l.UrlHash==h.Hash)) 
      .ToList() 
      .ForEach(h=> { 
      context.Links.Add(new Link(){ 
        Url = h.Url 
        }); 
       }); 

      context.SaveChanges(); 



    } 

    private bool Hash(string url) 
    { 
     SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); 
     byte[] encoded = Encoding.ASCII.GetBytes(url); 
     byte[] checksum = sha.ComputeHash(encoded); 
     long hash = BitConverter.ToInt64(checksum, 0); 
     return hash; 
    }