Why would AccessDataSource return different results to query in Access?

两盒软妹~` 提交于 2020-01-05 23:04:18

问题


I have a query to return random distinct rows from an Access database. Here is the query:

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

When I run this in Access it returns the rows in different order every time, as per the random sort order. When I run it through my web app however the rows return in the same order every time. Here is how I call it in my code-behind:

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

I added in all that stuff about caching because I thought maybe the query was being cached but the result was the same. I put a breakpoint in the code to make sure the query was the same as above and it was.

Any ideas? This is driving me nuts.


回答1:


When executing the ACE/Jet RND function against a new connection the same seed value is used each time. When using MS Access you are using the same connection each time, which explains why you get a different value each time.

Consider these VBA examples: the first uses a new connection on each iteration:

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

Output:

 0.705547511577606 
 0.705547511577606 
 0.705547511577606 

Note the same value each time.

The second example uses the same connection on each iteration (the .Open and .Close statements are relocated outside the loop):

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

Output:

 0.705547511577606 
 0.533424019813538 
 0.579518616199493 

Note different values each time.

In VBA code you can use the Randomize keyword to seed the Rnd() function but I don't think this can be done in ACE/Jet. One workaround is to use the least significant decimal portion of the ACE/Jet the NOW() niladic function e.g. something like:

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



回答2:


I would move the RND into the inner 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



回答3:


You can use time as one argument to the RND field

Dim Now As DateTime = DateTime.Now

Dim millSec As Integer = Now.Millisecond

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

So here from date and time value, millisecond value is taken which will be integer and it is used in sql query by rounding it.

wordInfo is table name ID is the column name in database table

This gives random order every time (since millisecond value is different) be it same connection or new connection.



来源:https://stackoverflow.com/questions/686970/why-would-accessdatasource-return-different-results-to-query-in-access

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!