JsonResult在客户端和服务器上以相反的方向排序

时间:2014-02-25 06:23:52

标签: c# asp.net-mvc

我查询我的数据库并将数据返回给客户端。当我在控制台上记录客户端上的数据时,它按字母顺序排列:

[
   [{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);
    }

这是测试方法

    [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);
    }

3 个答案:

答案 0 :(得分:1)

1.据我所知按密钥库存分组记录应按密钥递减排序。至少你已经设定了你的单元测试期望。但是在你的动作方法查询中,我没有看到按键降序排序。你需要添加它:

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将无法编译。您可以将其替换为IEnumerable<StockRecord>[] allStocks = (IEnumerable<StockRecord>[]) result.Data;

然后它将根据您在单元测试中定义的expcetations行为

答案 1 :(得分: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); 
    }

UNIT TEST

    [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);
    }

答案 2 :(得分:0)

集合(如SQL SELECT查询)不保证按任何特定顺序排列 - 这意味着可能的结果将被排序。

根据我的经验,任何.To___()调用都会撤消之前指定的.OrderBy()方法。因此,当您的代码在 .ToArray()之后调用.OrderBy(g3 => g3.RecordDate) 时,它会重置任何排序。结果在客户端上排序的事实可能只是一个侥幸。

解决方案是稍后在.ToArray()链中调用.OrderBy(),或在转换为数组后再调用.OrderBy()