Результаты SqlHelper.ExecuteReader могут быть разными и неожиданными, когда возвращается определенное количество записей.

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

Для начала я пытаюсь получить список 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. Если нет записей, возвращаемых из хранимого процесса (выполняется через sql server mgmt studio), при вызове последовательности методов reader.Read() возвращает false и полностью пропускает

  2. Если из хранимого процесса возвращается 1 запись (выполняется через sql server mgmt studio), при вызове последовательности методов reader.Read() возвращает true, но перечисление результатов дает сообщение о том, что IEnumerable не дал результатов

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

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

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

Спасибо,
Matt

3 ответа

Решение

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

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

Reader сообщает вам, если запись доступна

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

или же..

//expecting multiple records
while(reader.Read())
{
     //get reader["values"];
}

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

Вместо этого попробуйте следующее:

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

Возможно, вам придется настроить метод FillCollection, чтобы учесть это изменение.

Другие вопросы по тегам