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

Примечание: Возможно, вам не нужно читать все целиком, чтобы узнать, что не так ... перейдите к части о 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() возвращает тр, но при перечислении результатов выдается сообщение: IEnumerable не возвращает результатов

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

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

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

Спасибо,Matt

Ответы [ 3 ]

1 голос
/ 04 июля 2010

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

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

0 голосов
/ 04 июля 2010

читатель. Читатель сообщает, доступна ли запись

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

или ..

//expecting multiple records
while(reader.Read())
{
     //get reader["values"];
}
0 голосов
/ 04 июля 2010

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

Попробуйте вместо этого:

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

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

...