2010-07-04 1 views
1

Примечание: Возможно, вам не обязательно читать все, чтобы узнать, что не так ... пропустите вниз до части о трех сценариях, если вы как. Только прочитайте начало, если вам нужна некоторая справочная информация о том, как я попытался реализовать это и где произошли ошибки.Результаты SqlHelper.ExecuteReader изменяются и неожиданны, когда возвращается определенное количество записей

Во-первых, я пытаюсь получить список Clients, хранящийся в таблице CRM_Clients, для данного callerId.

Я извлекаю клиентов с моего контроллера с помощью метода SelectLiveClientsForCaller. Затем сообщение передается на DAL с помощью метода static Instance в классе DataProvider:

public List<Client> SelectLiveClientsForCaller(int callerID) 
    { 
     List<Client> results = new List<Client>(); 
     IDataReader reader; 

     reader = DataProvider.Instance().SelectLiveClientsForCaller(callerID); 

     if (reader.Read()) 
     { 
      // If I break here and enumerate the reader, it says that the IEnumerable returned no results 
      results = CBO.FillCollection<Client>(reader); // Always comes out as a count of 0 
     } 

     return results; 
    } 

Мой DataProvider класс является абстрактным классом, в котором изложены все методы SqlDataProvider есть:

public abstract class DataProvider 
{ 
    // singleton reference to the instantiated object 
    static DataProvider objProvider = null; 

    // constructor 
    static DataProvider() 
    { 
     CreateProvider(); 
    } 

    // dynamically create provider 
    private static void CreateProvider() 
    { 
     objProvider = (DataProvider)Reflection.CreateObject("data", "Owu.Modules.CRM", ""); 
    } 

    // return the provider 
    public static DataProvider Instance() 
    { 
     return objProvider; 
    } 

    public abstract IDataReader SelectLiveClientsForCaller(int callerID); 

    /* More abstract methods here... */ 
} 

В подкласс SqlDataProvider метод SelectLiveClientsForCaller фактически обрабатывается и вызывает SqlHelper.ExecuteReader для хранимой процедуры CRM_Clients_SelectLiveForCaller:

public class SqlDataProvider : DataProvider 
{ 
    private const string ProviderType = "data"; 
    private ProviderConfiguration _providerConfiguration = ProviderConfiguration.GetProviderConfiguration(ProviderType); 
    private string _myConnectionString; 
    private string _providerPath; 
    private string _objectQualifier; 
    private string _databaseOwner; 
    private string _moduleQualifier; 

    public SqlDataProvider() 
    { 
     //Read the configuration specific information for this provider 
     Provider objProvider = (Provider)_providerConfiguration.Providers[_providerConfiguration.DefaultProvider]; 

     //Read the attributes for this provider 
     //Get Connection string from web.config 
     _myConnectionString = Config.GetConnectionString(); 
    } 

    public string MyConnectionString 
    { 
     get { return _myConnectionString; } 
    } 

    public override IDataReader SelectLiveClientsForCaller(int callerID) 
    { 
     return (IDataReader)SqlHelper.ExecuteReader(
      myConnectionString, 
      "CRM_Clients_SelectLiveForCaller", 
      callerID); 
    } 

    /* More methods here... */ 
} 

Наконец, хранимая процедура CRM_Clients_SelectLiveForCaller

ALTER PROCEDURE [dbo].[CRM_Clients_SelectLiveForCaller] 
@CallerID int 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF @CallerID = -1 
    BEGIN 
     SELECT * FROM CRM_Clients WHERE IsDeleted = 'false' 
    END 
    ELSE 
    BEGIN 
     SELECT * FROM CRM_Clients WHERE ClientID IN 
      (SELECT ClientID FROM CRM_CallersClients WHERE CallerID = @CallerID) 
     AND IsDeleted = 'false' 
    END 
END 

Возвращает все не удаленные клиенты для данного callerid.

Это должно затем вернуться вверх по линии и возвращать результаты из контроллера ...

Есть 3 сценария я заметил до сих пор

  1. Если нет записей, возвращенных хранимый proc (выполняется через sql server mgmt studio), при вызове последовательности методов reader.Read() возвращает false, и он полностью пропускает его.

  2. Если есть одна запись вернулась из хранимой процедуры (выполняется через SQL сервера Упр студию), при вызове последовательности методов reader.Read() возвращает истинной но перечисляя результаты дает сообщение о том, IEnumerable не дал результатов

  3. Если есть 2 записи, возвращаемая из хранимой процедуры (выполняется через SQL сервер Упр студию), при вызове последовательности методов reader.Read() возвращает истинной но перечисляя результаты возвращает только 1 запись вместо 2

Может кто-нибудь объяснить, почему я получаю эти результаты для каждого сценария?

Если вам нужна дополнительная информация, пожалуйста, спросите меня, и я обновлю это, как только смогу.

Спасибо,
Matt

ответ

1

Каждый вызов reader.Read() читает строку, поэтому вы потребляете строки так же, как любой IEnumerable caller будет потреблять строки.

Вам необходимо пересмотреть вызов .Read() вне вашей процедуры заполнения, чтобы проверить наличие строк, потому что если вы снова вызываете .Read() снова внутри процедуры заполнения, прежде чем использовать строку, расположенную в настоящее время в читателе, вы будете иметь потерял этот первый ряд.

0

Reader.Read() рассматривает только первую строку, которая возвращается, и автоматически перемещает результирующий набор на следующую запись.

Попробуйте следующие вместо:

while (reader.Read()) 
{ 
results = CBO.FillCollection<Client>(reader); 
} 

Вам может понадобиться настроить метод FillCollection для размещения этого изменения.

0

reader.Read говорит вам, если запись доступна

//expecting one record 
if(reader.Read()) 
{ 
    //get reader["values"]; 
} 

или ..

//expecting multiple records 
while(reader.Read()) 
{ 
    //get reader["values"]; 
} 
Смежные вопросы