2009-03-26 3 views
1

У меня есть запрос на возврат случайных отдельных строк из базы данных Access. Вот запрос:Почему AccessDataSource возвращает разные результаты для запроса в 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; 
    } 
} 

Я добавил все, что материал о кэшировании, потому что я думал, что, возможно, был задан вопрос в кэше, но результат был тот же. Я поставил точку останова в коде, чтобы убедиться, что запрос был таким же, как и выше, и это было.

Любые идеи? Это сводит меня с ума.

+0

Он возвращается с тем же случайным порядком или есть какой-то интеллект в заказе, который вы видите? –

+0

Кажется, что тот же случайный порядок. – Phill

+0

Я напишу это в комментарии, поскольку идея устранения неполадок у меня есть, а не ответ, но вы попробовали добавить «RND (members.MemberID)» в предложение select в веб-версии, чтобы увидеть, возвращает ли он тот же случайный номер каждый раз? Одна мысль состоит в том, что он оптимизирует RND() из-за кэширования результата. – JohnFx

ответ

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 вы можете использовать рандомизированное ключевое слово, чтобы засеять функцию Rnd(), но я не думаю, что это можно сделать в ACE/Jet. Одним из способов является использование наименее значимой десятичной части функции ACE/Jet NOW() niladic, например. что-то вроде:

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

Вы можете быть здесь кое-что ... Я изменил код, чтобы использовать OleDbConnection, поэтому он создает новый каждый раз, и теперь он работает так, как ожидалось. – Phill

+0

Новый код: используя (OleDbConnection сопп = новый OleDbConnection (ул) { conn.Open(); команда OleDbCommand = conn.CreateCommand(); command.CommandText = GetSQLStatement(); listing.DataSource = command.ExecuteReader(); listing.DataBind(); – Phill

+0

Хорошая уловка на RND, высеваемая на одно и то же для каждого соединения - я собирался предположить, что :-) –

0

Я хотел бы переместить RND во внутренний ВЫБОР

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 
+0

Я пробовал это безрезультатно. Тот же результат. Я получаю результаты в том же порядке (хотя и в другом порядке до этого) на веб-сайте независимо от того, сколько раз загружается страница. В Access результаты по-разному упорядочиваются каждый раз. – Phill

0

Вы можете использовать время в качестве одного из аргументов в поле RND

Dim Теперь, как 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 это имя столбца в таблице базы данных

Это дает случайный порядок каждый раз (так как значение миллисекунды отличается), будь то же соединение или новое соединение.

Смежные вопросы