1

注意:您可能不需要阅读整篇文章就知道出了什么问题……如果您愿意,可以跳到关于 3 个场景的部分。如果您想了解有关我如何尝试实现此功能以及发生错误的位置的背景信息,请仅阅读开头。

首先,我试图检索Clients存储在CRM_Clients表中的给定callerId.

SelectLiveClientsForCaller我使用该方法从我的控制器中检索客户端。static Instance然后通过DataProvider 类中的方法将消息传递给 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 并完全跳过它。

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

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

谁能解释为什么我在每种情况下都得到这些结果?

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

谢谢,
马特

4

3 回答 3

1

对 reader.Read() 的每次调用都会读取一行,因此您正在使用行,就像任何 IEnumerable 调用者会使用行一样。

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

于 2010-07-04T02:46:00.480 回答
0

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

请尝试以下操作:

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

您可能需要调整 FillCollection 方法以适应这种变化。

于 2010-07-04T02:33:02.193 回答
0

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

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

或者..

//expecting multiple records
while(reader.Read())
{
     //get reader["values"];
}
于 2010-07-04T02:47:38.140 回答