2013-10-07 4 views
2

세 개의 열이있는 테이블이 있습니다. 두 개의 열이 PK를 구성합니다. 이 테이블은 디렉토리에있는 파일에 대한 정보를 저장합니다.IQueryable 집합간에 차이가 발생합니다.

입력 파일로 디렉토리가 있습니다.

목표는 추가 된 파일 목록과 제거 된 파일 목록을 얻는 것입니다. 결국 newItems에서

string uri = "ftp://ftp.myftpsite.com/files"; 
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(uri); 
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory; 
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse(); 
StreamReader streamReader = new StreamReader(response.GetResponseStream()); 
using (myEntities context = new myEntities()) 
{ 
    IQueryable<ITEM> storedItems = from item in context.ITEMs where item.YEAR == "2013" select item; 
    List<ITEM> currentItemList = new List<ITEM>(); 

    string line = streamReader.ReadLine(); 
    while (!string.IsNullOrEmpty(line) && line.EndsWith(".htm")) 
    { 
     ITEM item = new ITEM(); 
     item.YEAR = line.Substring(0,4); 
     item.NUM = line.Substring(7,5); 
     currentItemList.Add(item);     
     line = streamReader.ReadLine(); 
    } 

    IQueryable<ITEM> currentItems = currentItemList.AsQueryable<ITEM>(); 

    IQueryable<ITEM> newItems = from item in currentItems where !(from storedItem in storedItems select storedItem.YEAR + storedItem.NUM).Contains(item.YEAR + item.NUM) select item; 
    IQueryable<ITEMS> removedItems = from item in storedItems where !(from currentItem in currentItems select currentItem.YEAR + currentItem.NUM).Contains(item.YEAR + item.NUM) select item; 
    List<ITEM> newItemsList = newItems.ToList(); 
    List<ITEM> removedItemsList = removedItems.ToList(); 
} 

는 FTP 사이트의 항목이 아니라에게 데이터베이스를해야하고 removedItems이 항목 FTP 사이트의 데이터베이스에서가 아니라해야한다 :

나는 다음과 같은 코드가 있습니다.

newItems 작동하지만 다음 줄은 오류 반환 :

System.NotSupportedException: Unable to create a constant value of type 'MYProject.ITEM'. Only primitive types or enumeration types are supported in this context.

뭔가 내가 생각하는 나의 두 번째 LINQ 쿼리에 문제가 있습니다,하지만 난 잘 모르겠어요 : List<ITEM> removedItemsList = removedItems.ToList();

오류가이다 뭐.

또한 성능이 중요하므로 성능과 관련된 제안을 환영합니다.

현재 솔루션 :

List<string> criteria = (from item in currentItemList select item.YEAR + item.NUM).ToList(); 
foreach(AMENDMENT a in storedItems) 
{ 
    if(!criteria.Contains(a.YEAR + a.NUM)) 
     //do stuff here 
} 

그래서 기본적으로 대신 LINQ에서 조건문을하고 나는 for 루프의 if 문에 그것을했다. 정직하게 생각하면 꽤 못생긴 데 두 가지 이점이 있습니다.

  1. 그것은 LINQ 쿼리처럼 약 3 초 정도 복용했다 대신 fo를

  2. , 그것은 두 번째의 몇 백분의 소요 작동합니다.

+0

제목을 편집했습니다. "[제목에"태그 "가 포함되어 있어야합니까?] (http://meta.stackexchange.com/questions/19190/)"합의가 "아니오, 그렇지 않아야합니다"로 표시되어야합니다. –

+0

removeItems 쿼리가 아닌 newItems 쿼리가 작동하는 이유는 무엇입니까? 본질적으로 동일한 쿼리입니까? – kralco626

답변

1

먼저 투영 해 보셨습니까? 데이터 크기가 너무 크지 않으면 죽이지 않습니다. 그렇지 않으면 더 창의적이되어야합니다.

IQueryable<ITEMS> removedItems = from item in storedItems.ToList() where !(from currentItem in currentItems select currentItem.YEAR + currentItem.NUM).Contains(item.YEAR + item.NUM) select item; 

검색어가 이상합니다. 또 다른 방법은 효과가있을 수 있지만 그것을 조사하지는 않았습니다. 이미 2013 년까지 하위 집합이므로이 작업은 동일합니다. 이 같은

List<int> itemNumbers = currentItems.Where(x=>x.YEAR ==2013).Select(x=>x.NUM).ToList(); 
IQueryable<ITEMS> removedItems = from item in storedItems where !itemNumbers.Contains(item.NUM) select item; 
+0

당신의 대답에서 볼 수있는 유일한 차이점은 LINQ 쿼리의 storedItems 객체에 ToList()를 추가했다는 것입니다. 이렇게하면 다음과 같은 오류가 발생합니다. '암시 적으로'System.Collections.Generic.IEnumerable '형식을'System.Linq.IQueryable '형식으로 변환 할 수 없습니다. 명시 적 전환이 존재합니다 (캐스트가 누락 되었습니까?) '내가 누락 된 대답이 있습니까? – kralco626

+0

두 번째 대답은 효과가있을 수 있다고 생각합니다. 그러나 이제는 한 번만 점검해야하는 필드로 제한됩니다. 이 제한이없는 솔루션을 선호합니다. 예를 들어 나는뿐만 아니라 관심 – kralco626

+0

2013에 대한 확인 있었다면, 난 그냥 currentItems에서 X에서 LIST itemIds의 =을 선택 x.YEAR + x.NUM''말할 수있는 다음 코드 조각 사용 ('itemIds.Contains!을 item.YEAR + item.NUM)'따라서 여러분의 솔루션은 여러 필드를 사용하여 – kralco626

0

시도 뭔가 :

using (myEntities context = new myEntities()) 
{ 
    List<ITEM> storedItems = (
     from item in context.ITEMs 
     where item.YEAR == "2013" 
     select item).ToList(); 

    List<ITEM> currentItemList = new List<ITEM>(); 

    string line = streamReader.ReadLine(); 
    while (!string.IsNullOrEmpty(line) && line.EndsWith(".htm")) 
    { 
     ITEM item = new ITEM(); 
     item.YEAR = line.Substring(0,4); 
     item.NUM = line.Substring(7,5); 
     currentItemList.Add(item);     
     line = streamReader.ReadLine(); 
    } 

    List<ITEM> newItemsList = (
     from cItem in currentItems 
     join sItem in storedItems 
      on (cItem.YEAR + cItem.NUM) equals (sItem.YEAR + sItem.NUM) 
      into g 
     from gItem in g.DefaultIfEmpty() 
     where gItem == null 
     select cItem).ToList(); 

    List<ITEM> removedItemsList = (
     from sItem in storedItems 
     join cItem in currentItems 
      on (sItem.YEAR + sItem.NUM) equals (cItem.YEAR + cItem.NUM) 
      into g 
     from gItem in g.DefaultIfEmpty() 
     where gItem == null 
     select sItem).ToList(); 
} 
+0

는'에 (sItem.YEAR + sItem.NUM는) 동일 (cItem.YEAR + cITEM.NUM)는'동일시겠습니까 cItem.NUM'과 같거나 뭔가 빠졌습니까? – kralco626

+0

분명히 나는 ​​뭔가를 놓쳤다. LINQ는 우리를 싫어하고 우리가 두 분야에 참여하게하지 않을 것이다. LOL :) – kralco626

0

현재 솔루션 : 그래서

List<string> criteria = (from item in currentItemList select item.YEAR + item.NUM).ToList(); 
foreach(AMENDMENT a in storedItems) 
{ 
    if(!criteria.Contains(a.YEAR + a.NUM)) 
     //do stuff here 
} 

기본적으로 대신 LINQ에서 조건문을하고 난에 if 문에 그것을했다 for 루프. 정직하게 생각하면 꽤 못생긴 데 두 가지 이점이 있습니다.

  1. 그것은 LINQ 쿼리처럼 약 3 초 정도 복용했다 대신 fo를

  2. , 그것은 두 번째의 몇 백분의 소요 작동합니다.

다른 제안이 있지만 나는 아직 아이디어가 있습니다.