为什么AccessDataSource会在Access中向查询返回不同的结果?

时间:2009-03-26 18:16:47

标签: ms-access

我有一个查询从Access数据库返回随机不同的行。这是查询:

SELECT * FROM 
(SELECT DISTINCT m.MemberID, m.Title, m.FullName, m.Address, 
        m.Phone, m.EmailAddress, m.WebsiteAddress FROM Members AS m INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID WHERE 
(Category = 'MemberType1' OR Category = 'MemberType2')) as Members 
ORDER BY RND(members.MemberID) DESC

当我在Access中运行它时,它会按照随机排序顺序每次以不同的顺序返回行。当我通过我的网络应用程序运行它时,行每次都以相同的顺序返回。以下是我在代码隐藏中调用它的方法:

private void BindData()
{
    using (AccessDataSource ds = new AccessDataSource("~/App_Data/mydb.mdb", GetSQLStatement()))
    {
        ds.DataSourceMode = SqlDataSourceMode.DataReader;
        ds.CacheDuration = 0;
        ds.CacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
        ds.EnableCaching = false;            
        listing.DataSource = ds.Select(new DataSourceSelectArguments());
        listing.DataBind();
        if (listing.Items.Count == 0)
            noResults.Visible = true;
        else
            noResults.Visible = false;
    }
}

我添加了有关缓存的所有内容,因为我认为可能正在缓存查询但结果是相同的。我在代码中放了一个断点,以确保查询与上面相同,并且它是。

有什么想法吗?这让我疯了。

3 个答案:

答案 0 :(得分:2)

对新连接执行ACE / Jet RND功能时,每次都使用相同的种子值。使用MS Access时,每次都使用相同的连接,这解释了为什么每次都获得不同的值。

考虑这些VBA示例:第一个在每次迭代时使用新连接:

Sub TestDiff()

  Dim con As Object
  Set con = CreateObject("ADODB.Connection")
  With con
    .ConnectionString = _
        "Provider=MSDataShape;Data " & _
        "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Tempo\Test_Access2007.accdb"
    .CursorLocation = 3

    Dim i As Long
    For i = 0 To 2

      .Open
      Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
      .Close
    Next
  End With

End Sub

输出:

 0.705547511577606 
 0.705547511577606 
 0.705547511577606 

每次都注意相同的值。

第二个示例在每次迭代时使用相同的连接(.Open和.Close语句在循环外重定位):

Sub TestSame()

  Dim con As Object
  Set con = CreateObject("ADODB.Connection")
  With con
    .ConnectionString = _
        "Provider=MSDataShape;Data " & _
        "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Tempo\Test_Access2007.accdb"
    .CursorLocation = 3

    .Open

    Dim i As Long
    For i = 0 To 2
      Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
    Next

    .Close

  End With

End Sub

输出:

 0.705547511577606 
 0.533424019813538 
 0.579518616199493 

每次注意不同的值。

在VBA代码中,您可以使用Randomize关键字为Rnd()函数设定种子,但我不认为这可以在ACE / Jet中完成。一种解决方法是使用ACE / Jet的最低有效小数部分NOW()niladic函数,例如:类似的东西:

SELECT CDBL(NOW()) - ROUND(CDBL(NOW()), 4) FROM OneRowTable

答案 1 :(得分:0)

我会将RND移动到内部SELECT

SELECT * FROM 
    (SELECT DISTINCT m.MemberID, RND(m.MemberID) as SortOrder, m.Title, 
    m.FullName, m.Address, m.Phone, m.EmailAddress, m.WebsiteAddress 
    FROM Members AS m 
    INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID 
    WHERE 
        (Category = 'MemberType1' OR Category = 'MemberType2')) as Members 
ORDER BY 
    Members.SortOrder DESC

答案 2 :(得分:0)

您可以将时间用作RND字段的一个参数

现在变暗为DateTime = DateTime.Now

Dim millSec As Integer = Now.Millisecond

finalQuery =“SELECT * FROM wordInfo ORDER BY Rnd( - (1000 * ROUND(”+ millSec.ToString(“N”)+“,0))* [ID])”

所以这里从日期和时间值开始,取毫秒值,它将是整数,并通过舍入它在sql查询中使用。

wordInfo是表名 ID是数据库表中的列名

每次都给出随机顺序(因为毫秒值不同)是相同的连接或新连接。