2014-02-25 3 views
0

데이터베이스에 쿼리하고 클라이언트에 데이터를 반환합니다. console.log에 클라이언트의 데이터가 알파벳 순서대로 있습니다.JsonResult는 클라이언트와 서버에서 반대 방향으로 정렬됩니다.

[ 
    [{key='a',val=123},{key='a',val=666},{key='a',val=420}], 
    [{key='b',val=999},{key='b',val=822},{key='b',val=314}], 
    [{key='c',val=732},{key='c',val=444},{key='c',val=987}], 
] 

그러나 단위 테스트를 실행할 때 데이터가 거꾸로됩니다!

[ 
    [{key='c',val=732},{key='c',val=444},{key='c',val=987}], 
    [{key='b',val=999},{key='b',val=822},{key='b',val=314}], 
    [{key='a',val=123},{key='a',val=666},{key='a',val=420}], 
] 

어쩌면 개체를 잘못 캐스팅 했습니까?

JsonResult result = (JsonResult)target.GetStockHistory(new string[]{"ABCDEFG", "ZYXWVUT"}); 
IGrouping<string, StockRecord>[] allStocks = (IGrouping<string, StockRecord>[])result.Data; 

내가 콘솔로 정렬되고 있다는 긍정적 인 생각은 브라우저에 의해 분류 할 값을 알 수있는 방법이 없기 때문에 나를 위해 그것을 포맷 브라우저의 결과가 아닙니다. 그것은 단지 JSON을 파싱하는 것입니다. (정렬 또는 하위 쿼리 문제에 기여하고 있는지 확실하지 않습니다) 여기

public ActionResult GetStockHistory(string[] symbols) 
    { 
     StockHistory stocks = new StockHistory(); 
     IEnumerable<StockRecord>[] records = repository.StockRecords 
      .Where(r => symbols.Contains(r.Symbol)) 
      .GroupBy(r => r.Symbol) 
      .Select(g => 
       g.OrderByDescending(g2 => g2.RecordDate) 
       .Take(30) 
       .OrderBy(g3 => g3.RecordDate)) 
      .ToArray(); 
     return Json(records, JsonRequestBehavior.AllowGet); 
    } 

내가 키 stock별로 그룹화 것을 이해

[TestMethod] 
    public void Can_Get_Stocks() 
    { 
     // arrange 
     Mock<IStockHistory> mock = new Mock<IStockHistory>(); 
     mock.Setup(m => m.StockRecords).Returns(new StockRecord[] { 
      new StockRecord { 
       Symbol = "ABCDEFG", 
       RecordDate = new DateTime(2000, 1, 1), 
       LowValue = 1, 
       HighValue = 10, 
       AdjustedCloseValue = 8, 
       CloseValue = 9, 
       OpenValue = 7, 
       Volume = 13245 
      }, 
      new StockRecord { 
       Symbol = "LMNOP", 
       RecordDate = new DateTime(2005, 1, 1), 
       LowValue = 1, 
       HighValue = 5, 
       AdjustedCloseValue = 6, 
       CloseValue = 5, 
       OpenValue = 4, 
       Volume = 23456 
      }, 
      new StockRecord { 
       Symbol = "ZYXWVUT", 
       RecordDate = new DateTime(2010, 1, 1), 
       LowValue = 6, 
       HighValue = 60, 
       AdjustedCloseValue = 10, 
       CloseValue = 10, 
       OpenValue = 7, 
       Volume = 67891 
      } 
     }.AsQueryable()); 
     CommonController target = new CommonController(mock.Object); 

     // act 
     JsonResult result = (JsonResult)target.GetStockHistory(new string[]{"ABCDEFG", "ZYXWVUT"}); 
     IGrouping<string, StockRecord>[] allStocks = (IGrouping<string, StockRecord>[])result.Data; 
     // allStocks is backwards!?!?! cats and dogs are getting along! 

     // assert 
     Assert.AreEqual(2, allStocks.Length); 
     Assert.AreEqual("ZYXWVUT", allStocks[0].ToArray()[0].Symbol); 
     Assert.AreEqual("ABCDEFG", allStocks[1].ToArray()[0].Symbol); 
     Assert.AreEqual(10, allStocks[0].ToArray()[0].CloseValue); 
     Assert.AreEqual(9, allStocks[1].ToArray()[0].CloseValue); 
    } 
+0

당신이 있는지 있습니까 IEnumerable을 에서 [] IGrouping에 캐스팅 <문자열 StockRecord> [], IGrouping [] allStocks = (IGrouping []) result.Data; 화내고 있니? – Regfor

답변

0

컬렉션, SQL SELECT 쿼리와 같은 특정 순서가 보장되지 않습니다 - 월 결과를 의미한다을 정렬 할 수 있습니다.

내 경험에 의하면 .To___() 호출 중 하나는 이전에 지정된 .OrderBy() 메서드를 실행 취소합니다. 따라서 코드가 .ToArray()이면.OrderBy(g3 => g3.RecordDate) 뒤에 정렬되므로 정렬이 재설정됩니다. 결과가 클라이언트에서 정렬된다는 사실은 우연 일뿐입니다.

해결 방법은 .OrderBy() 체인의 앞부분에 .ToArray()을 먼저 호출하거나 배열로 변환 한 후 .OrderBy()을 다시 호출하는 것입니다.

+0

아래의 내용과이 답변의 조합이었습니다. 우연한 일에 대해 아직도 조금 혼란스러워. 나는 그것이 클라이언트에서 바로 정렬되었다는 것을 의미합니다 (서버에서 정렬 한 후에)하지만 어쩌면 그것은 우연입니다. – user1873073

+0

.__ ___() 호출 중 이전에 지정된 .OrderBy() methods_ ==> no를 실행 취소하면 true가 아닙니다. – ken2k

+0

@ ken2k 전 (前) .OrderBy() 호출에 의해 부과 된 정렬을 유지한다고 보장 할 수는 없습니다. 적어도 그것은 제 경험이었습니다. –

1

1.As 시험 방법입니다 여기

내 행동의 방법이다 레코드는 키 내림차순으로 정렬되어야합니다. 적어도 당신은 단위 테스트에 대한 기대치를 설정했습니다. 하지만 당신의 액션 메소드 쿼리에서 키에 의한 내림차순 정렬이 보이지 않습니다. 당신은 그것을 추가해야합니다

IEnumerable<StockRecord>[] records = repository.StockRecords 
    .Where(r => symbols.Contains(r.Symbol)) 
    .GroupBy(r => r.Symbol) 
    .OrderByDescending(p => p.Key)    
    .Select(g => g.OrderByDescending(g2 => g2.RecordDate).Take(30).OrderBy(p => p.RecordDate))       
    .ToArray(); 
return Json(records, JsonRequestBehavior.AllowGet); 

2. 그러한가 IGrouping<string, StockRecord>[] allStocks = (IGrouping<string, StockRecord>[])result.Data가 컴파일되지 않습니다 캐스팅. 당신은 그 다음이 단위 테스트에서 당신에 의해 정의 expcetations에 따라 행동 할 IEnumerable<StockRecord>[] allStocks = (IEnumerable<StockRecord>[]) result.Data;

로 교체 할 수 있습니다

1

나는 바보 같았습니다. 그런 식으로 정렬하는 다른 쿼리로 이동했습니다. 이것은 내가 함께 결국 무엇을 :

의 조치 방법

public ActionResult GetStockHistory(string[] symbols, int maxRows = Int32.MaxValue) 
    { 
     IEnumerable<IEnumerable<StockRecord>> records; 

     records = repository.StockRecords 
      .Where(r => symbols.Contains(r.Symbol)) 
      .GroupBy(r => r.Symbol) 
      .Select(g => g 
       .OrderByDescending(g2 => g2.RecordDate) 
       .Take(maxRows) 
       .OrderBy(g3 => g3.RecordDate)); 

     return Json(records, JsonRequestBehavior.AllowGet); 
    } 

단위 테스트

[TestMethod] 
    public void Can_Get_Stock() 
    { 
     // arrange 
     Mock<IStockHistory> mock = new Mock<IStockHistory>(); 
     mock.Setup(m => m.StockRecords).Returns(new StockRecord[] { 
      new StockRecord { 
       Symbol = "ABCDEFG", 
       RecordDate = new DateTime(2000, 1, 1) 
      } 
     }.AsQueryable()); 
     CommonController target = new CommonController(mock.Object); 

     // act 
     JsonResult result = (JsonResult)target.GetStockHistory(new string[] { "ABCDEFG" }); 
     IEnumerable<IEnumerable<StockRecord>> allStocks = (IEnumerable<IEnumerable<StockRecord>>)result.Data; 

     // assert 
     Assert.AreEqual(1, allStocks.Count()); 
     StockRecord[] record1 = allStocks.ElementAt(0).ToArray(); 
     StockRecord record1_row1 = record1[0]; 

     Assert.AreEqual("ABCDEFG", record1_row1.Symbol); 
    } 
관련 문제