2015-11-02 56 views
0

我有一个数据表我用作中继器的数据源,并希望每次调用它时都会按随机顺序显示结果。c#Randomize DataTable rows

我已经能够在检索数据时做到这一点,但希望在绑定之前缓存结果集。

是否有人在绑定到中继器之前将数据表的行进行随机播放?

CODE:

 TreeProvider tp = new TreeProvider(); 
    DataSet ds = new DataSet(); 
    string sKey = "KEY"; 
    using (CachedSection<DataSet> cs = new CachedSection<DataSet>(ref ds, 5, true, null, sKey)) 
    { 
     if (cs.LoadData) 
     { 
     ds = tp.SelectNodes("", "URL", "", true, "DOCTYPE", "", "NewID()", -1, true, 5); 
     cs.Data = ds; 
     } 
    } 
    if (!DataHelper.DataSourceIsEmpty(ds)) 
    { 
     rprItems.DataSource = ds.Tables[0].DefaultView; 
     rprItems.DataBind(); 
    } 

任何指导被理解。

+1

你可以添加你到目前为止问题的代码吗? – Sybren

+0

感觉没有必要,因为它是通用的。现在加入... – Spitfire2k6

+1

这里有一个可能对你有帮助的链接https://social.msdn.microsoft.com/Forums/en-US/b832b9ff-5e1a-490f-bcf6-3e72070b5879/shuffle-datatable-rows – Sybren

回答

0

我最终采取的表的副本,添加一个字段,每个分配一个随机数然后按该行排序。

 DataTable dt = ds.Tables[0].Copy(); 
     if (!dt.Columns.Contains("SortBy")) 
      dt.Columns.Add("SortBy", typeof (Int32)); 

     foreach (DataColumn col in dt.Columns) 
      col.ReadOnly = false; 

     Random rnd = new Random(); 
     foreach (DataRow row in dt.Rows) 
     { 
      row["SortBy"] = rnd.Next(1, 100); 
     } 
     DataView dv = dt.DefaultView; 
     dv.Sort = "SortBy"; 
     DataTable sortedDT = dv.ToTable(); 

     rprItems.DataSource = sortedDT; 
     rprItems.DataBind(); 
0

你可以尝试这样的事情,我知道这是不是漂亮,但:

DataTable newTable = new DataTable(); 
newTable.TableName = "<NewTableName>"; 
//Make a new Random generator 
Random rnd = new Random(); 
while (<new table length> != <old table length>) 
{ 
    //We'll use this to make sure we don't have a duplicate row 
    bool rowFound = false; 
    //index generation 
    int index = rnd.Next(0, <max number of rows in old data>); 
    //use the index on the old table to get the random data, then put it into the new table. 
    foreach (DataRow row in newTable.Rows) 
    { 
     if (oldTable.Rows[index] == row) 
     { 
      //Oops, there's duplicate data already in the new table. We don't want this. 
      rowFound = true; 
      break; 
     } 
    } 
    if (!rowFound) 
    { 
     //add the row to newTable 
     newTable.Rows.Add(oldTable.Rows[index]; 
    } 
} 

你将不得不使用,当然你自己的表,名称,长度,但是这应该是确定使用。如果有很多数据,这可能需要一段时间。这是我能想到的最好的,而且没有经过测试。我很想知道它是否有效。

+0

随机类是伪随机数发生器,它永远不会创建真随机数 –

+0

我不知道有任何其他方式做随机。到目前为止,每个答案都有类似的建议。 –

+0

检查我的答案,它没有,它参考了使用System.Cryptography –

0

你可以尝试:

 DataTable dt = new DataTable(); 
     dt.Columns.Add("Name"); 
     dt.Columns.Add("Sort"); 
     dt.Rows.Add("TEST"); 
     dt.Rows.Add("TEST1"); 
     dt.Rows.Add("TEST2"); 

     var rnd = new Random(DateTime.Now.Millisecond); 
     foreach (DataRow row in dt.Rows) 
     { 
      row["Sort"] = rnd.Next(dt.Rows.Count); 
     } 


     var dv = new DataView(dt); 
     dv.Sort = "Sort"; 
     foreach (DataRowView row in dv) 
     { 
      Console.WriteLine(row[0]); 
     } 

如果你的数据表是不是太大,它应该这样做。

+0

随机类是伪随机数发生器,它永远不会创建真随机数 –

+0

您可以替换任何你想要的。将排序列更改为guid并生成新的Guid将执行与SQL相同的技巧。请记住,到目前为止,我们不需要生成唯一的随机数,这个想法就是随机排序结果。保持简单,除非你需要复杂的解决方案 – user1965927

0

这应是直线前进,据我能理解,让我把它分解成部分:

  • 获得一个包含DataTable用于直放站
  • 存储原始DataSetDataSetCache
  • 取两个索引,beginIndex as 0endIndex as DataSet.Tables[0].Rows.Count,beginIndex是包含的,endIndex是唯一的
  • 现在创建一系列随机索引,使用以下Article,还检查以下由Jon Skeet编制的detail,这使用System.Cryptography - RNGCryptoServiceProvider
  • 逻辑应该是这样的,每次选择一个新数字时,它被排除,直到所有数字串联被选择,检查下面的代码,其中一部分是从链接复制的上方设置:

    void Main() 
    { 
    List<int> newList = new List<int>(); 
    
    DataTable dt = new DataTable(); 
    
    int beginIndex = 0; 
    
    int endIndex = dt.Rows.Count; 
    
    int numberIndex = 0; 
    
    CustomRandom cr = new CustomRandom(); 
    
    while(numberIndex < dt.Rows.Count) 
    { 
        int randomNumber = cr.Next(beginIndex, endIndex);  
    
        if(newList.Contains(randomNumber)) 
        continue; 
        else 
        { 
         newList.Add(randomNumber); 
         numberIndex ++; 
        } 
    } 
    } 
    
    public class CustomRandom 
    { 
        private const int BufferSize = 1024; // must be a multiple of 4 
        private byte[] RandomBuffer; 
        private int BufferOffset; 
        private RNGCryptoServiceProvider rng; 
    
    public CustomRandom() 
    { 
        RandomBuffer = new byte[BufferSize]; 
        rng = new RNGCryptoServiceProvider(); 
        BufferOffset = RandomBuffer.Length; 
    } 
    
        private void FillBuffer() 
        { 
        rng.GetBytes(RandomBuffer); 
        BufferOffset = 0; 
        } 
    
        public int Next() 
        { 
        if (BufferOffset >= RandomBuffer.Length) 
        { 
         FillBuffer(); 
        } 
        int val = BitConverter.ToInt32(RandomBuffer, BufferOffset) & 
        0x7fffffff; 
        BufferOffset += sizeof(int); 
        return val; 
    } 
    public int Next(int maxValue) 
    { 
        return Next() % maxValue; 
    } 
    public int Next(int minValue, int maxValue) 
    { 
        if (maxValue < minValue) 
        { 
         throw new ArgumentOutOfRangeException("maxValue must be greater than or equal to minValue"); 
        } 
        int range = maxValue - minValue; 
        return minValue + Next(range); 
    } 
    public double NextDouble() 
    { 
        int val = Next(); 
        return (double)val/int.MaxValue; 
    } 
    public void GetBytes(byte[] buff) 
    { 
        rng.GetBytes(buff); 
    } 
    } 
    
    • 现在基于在列表newList产生的索引,创建一个新的DataTable,其可用于作为的如下:

      DataTable randomTable = new DataTable(); 
      
          foreach(int randomIndex in newList) 
          { 
          randomTable.Rows.Add(dt.Rows[randomIndex]; 
          } 
      

    现在randomTable可以用作源Repeater

+0

不要使用随机类,因为它永远不会生成真随机数,总是使用True我已经在上面的代码中建议的随机数 –

+0

修改了代码,现在CustomRandom仅初始化一次,而不是每一次while循环迭代,只需要一次初始化,就可以生成真正的随机数 –