当返回特定数量的记录时,SqlHelper.ExecuteReader结果变化且意外

时间:2010-07-04 02:21:07

标签: asp.net sqldatareader datareader dataprovider sqlhelper

注意:您可能不需要阅读整个内容就知道出了什么问题...如果您愿意,可以跳到有关3个方案的部分。如果你想了解我如何尝试实现这一点以及错误发生的地方的背景信息,请阅读开头。

首先,我正在尝试检索存储在Clients表中的CRM_Clients列表,其中包含给定的callerId

我使用SelectLiveClientsForCaller方法从Controller中检索客户端。然后,消息通过DataProvider类中的static Instance方法传递给DAL:

    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并完全跳过它。

    < / LI>
  2. 如果从存储过程返回1条记录(通过sql server mgmt studio执行),则在调用方法序列reader.Read()时返回 true ,但枚举结果给出一条消息说 IEnumerable没有返回任何结果

  3. 如果从存储过程返回2条记录(通过sql server mgmt studio执行),则在调用方法序列reader.Read()时,返回 true ,但枚举结果< strong>仅返回1条记录而不是2条

  4. 有人可以解释为什么我会为每种情况获得这些结果吗?

    如果您需要更多信息,请询问,我会尽快更新。

    谢谢,
    马特

3 个答案:

答案 0 :(得分:1)

每次调用reader.Read()都会读取一行,所以就像任何IEnumerable调用者使用行一样消耗行。

你需要重新考虑在填充例程之外调用.Read()以检查是否存在行,因为如果在使用当前位于阅读器中的行之前再次在填充例程中调用.Read(),则会丢失第一排。

答案 1 :(得分:0)

Reader.Read()仅检查返回的第一行,并自动将结果集移动到下一条记录。

请尝试以下方法:

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

您可能需要调整FillCollection方法以适应此更改。

答案 2 :(得分:0)

reader.Read会告诉您记录是否可用

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

或..

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