1

注:何が問題なのかを知るためにすべてを読む必要はないかもしれません...必要に応じて、3 つのシナリオに関する部分までスキップしてください。これを実装しようとした方法とエラーが発生した場所に関する背景情報が必要な場合にのみ、最初をお読みください。

まず、特定の のテーブルにClients格納されている のリストを取得しようとしています。CRM_ClientscallerId

メソッドを使用して、コントローラーからクライアントを取得しますSelectLiveClientsForCaller。次に、メッセージはstatic InstanceDataProvider クラスのメソッドを介して 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 を介して実行)、一連のメソッドを呼び出すとtruereader.Read()が返されますが、結果を列挙すると、IEnumerable が結果を返さなかったことを示すメッセージが表示されます。

  3. ストアド プロシージャから返されるレコードが 2 つある場合 (SQL Server mgmt studio を介して実行)、一連のメソッドを呼び出すとtruereader.Read()が返されますが、結果を列挙すると 2 つではなく 1 つのレコードしか返されません。

各シナリオでこれらの結果が得られる理由を誰か説明できますか?

さらに情報が必要な場合はお問い合わせください。できるだけ早くこれを更新します。

ありがとう、
マット

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 に答える