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