4

私の C# WCF サービスにはSqlDataReader、クライアントに返したいデータの行を保持する があります。

のすべてを返す方法はSqlDataReader?

今、私は持っています

if (sqlReader != null)
{
    if (sqlReader.HasRows)
    {
        while (sqlReader.Read())
        {
            return sqlReader[0].ToString();
        }
        sqlConn.Close();
    }
    else
    {
        return null;
    }
}

それは最初の結果だけを返します。現時点では、クラスの戻り値の型は文字列です。配列内の配列のようなものを考えていましたが、方法がわかりませんか?

編集:

たくさんの返信ありがとうございます。サービスが「作成」する SQL データ全体を返すことに関心があります。最初の列 ([0]) がオンラインではありません - これはテスト用です。

しかし、サービスからクライアントにすべてを戻す方法がわかりません。

  • 返却方法は?

たとえば。Powershell では、コレクションを作成し、クライアント間で渡す必要がある場合は、そのコレクションにオブジェクトを追加します。

C# と WCF で似たようなものを探しています。

今までありがとうございました:)

編集#2:

とった!:)

新しいクラスを作成しました (例):

public class ObjectNotification
{
    public string AlertDescription;
    public string Servername; 
}

一番上の私の svc.cs ファイルで:

List<ObjectNotification> objlist = new List<ObjectNotification>();

    if (sqlReader.HasRows)
    {
       while (sqlReader.Read())
       {
             ObjectNotification obj = new ObjectNotification();
             obj.AlertDescription = sqlReader["AlertDescription"].ToString();
             obj.Servername = sqlReader["ComputerName"].ToString();
             objlist.Add(obj);
       }
    }
    return objlist;

それはまさに私が欲しかったものを私に与えました:)

よろしくお願いします

4

6 に答える 6

5

DataContract を定義する必要があります。文字列のリストまたは文字列の配列を渡す場合、サービスの利用者は、どのインデックスがどの列のインデックスであるかなどを知る必要があります。将来、サービスに列を追加または削除するときに、そのアプローチは難しくなります。できることは、送信する必要があるすべてのプロパティを持つ DataContract を作成し、それに応じて操作コントラクトを作成することです。サービス コンシューマーは、フィールドを変更した場合にコンパイラ エラーが発生する場合に、サービス参照を更新できるようになりました。それは簡単に識別できます。

public List<MyDataContract>  GetData()
{
    List<MyDataContract> list = new List<MyDataContract>();
    //your code

    if (sqlReader != null)
    {
        if (sqlReader.HasRows)
        {
            while (sqlReader.Read())
            {
                list.Add(new MyDataContract() { 
                    Id = (int)sqlReader["Id"].ToString(), 
                    Name= sqlReader = sqlReader["Name"].ToString() });

            }
            sqlConn.Close();
        }
    }

    //finally return list of data

    return list;
}

サンプル データ コントラクト

[DataContract]
public class MyDataContract
{
    [DataMember]
    public int Id{ get; set; }

    [DataMember]
    public string Name{ get; set; }
}

そして運用契約

     [OperationContract]
     List<MyDataContract> GetData();

私の意見では、より一般的な再利用可能なコードが必要です...

.net Service コンシューマーしかない場合は、サービス メソッドからDaTaSet または DataTableを返すことができます。sqlReader の代わりにSqlDataAdapterを用意し、DataTable または Dataset を埋めてそれを返す必要があります。Service メソッドの定義を変更せずに、任意の数の列を配置できます。を使用して、戻り値の型を文字列として送信することもできますDataSet.GetXml()

DataTable を Json に変換する

string json = JsonConvert.SerializeObject(table, Formatting.Indented);
于 2013-05-15T17:44:06.107 に答える
3
// for instance
List<string> list = new List<string>();

if (sqlReader != null)
    {
        if (sqlReader.HasRows)
        {
            while (sqlReader.Read())
            {
                //return sqlReader[0].ToString();
                list.Add(sqlReader[0].ToString());
            }
            sqlConn.Close();
        }
        else
        {
            return null;
        }
    }
return list; // ta-da
于 2013-05-15T17:20:20.257 に答える
1

SqlReader は作業メモリを最小化することを目的としているため、結果を 1 つずつクエリするだけです。すべての結果を取得したい場合は、コードの周りで while ループを使用して、利用可能な限り行をフェッチできます。return を呼び出すと、while ループが中断され、最初の行のみが返されます。yield return を呼び出すとIEnumerable<string>、 メソッドによって ではなく an が返されますstring

于 2013-05-15T17:19:13.080 に答える
0

古いスレッドですが、2 つ追加します。

        string sqltext = @"select a.columnown, a.columntwo, a.columnthreee from blahblah as a";
        List<List<string>> toReturn = new List<List<string>>();
        using (SqlConnection con = new SqlConnection("YourConnectionString"))
        {
            con.Open();
            SqlCommand cmd = con.CreateCommand();
            cmd.CommandText = sqlTest;

            using (SqlDataReader sqlReader = cmd.ExecuteReader())
            {
                if (sqlReader != null)
                {
                    if (sqlReader.HasRows)
                    {
                        while (sqlReader.Read())
                        {
                            List<string> innerList = new List<string>();
                            for (int i = 0; i < sqlReader.FieldCount; i++)
                            {
                                innerList.Add(sqlReader[i].ToString());
                            }
                            toReturn.Add(innerList);
                        }
                        con.Close();
                    }
                }
            }
        }

その後、あなたは単にあなたを返すだけですList<List<string>>

于 2013-12-18T11:01:21.913 に答える
0

データテーブルにロードして、すべてのデータリーダー行を実際に読み取る必要があります。データリーダーは遅延読み込みオブジェクトであり、最初に完全に読み込まれることはないため、ネットワーク経由で送信できません。

DataTable dt=new DataTable();     
dt.Load(dr);

次に、wcf を使用しているため、そのデータテーブルをコントラクト インターフェイスに一致するオブジェクトにロードする必要がある可能性があります。リフレクションを使用して、任意のデータテーブルをプロパティに一致する適切に動作するオブジェクトに変換する以下のスニペットを見てください。

スニペットの使用

List<myType> r = (List<myType>) dt.ToList<myType>();

スニペット

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;

namespace xxxx.Sql.Extensions
{
    public static class DataTableExtensions
    {
        /// <summary>
        /// Gets a list of objects  based on a generic datatable
        /// </summary>
        /// <typeparam name="T">List of objects</typeparam>
        /// <param name="table">Existing datatable</param>
        /// <returns></returns>
        public static IList<T> ToList<T>(this DataTable table) where T : new()
        {
            IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            IList<T> result = new List<T>();

            foreach (var row in table.Rows)
            {
                var item = CreateItemFromRow<T>((DataRow)row, properties);
                result.Add(item);
            }

            return result;
        }

        private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
        {
            T item = new T();

            foreach (var property in properties)
            {
                if (row.Table.Columns.Contains(property.Name))
                {
                    var prop = row[property.Name] == System.DBNull.Value ? null : row[property.Name];
                    property.SetValue(item, prop, null);
                }
            }
            return item;
        }
        /// <summary>
        /// Creat a generic string list on the first field of a dataTable
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public static List<string> ToStringList(this DataTable table)
        {
            List<string> result = new List<string>();

            foreach (DataRow dr in table.Rows)
                result.Add(dr[0].ToString());

            return result;
        }
    }
}
于 2013-05-15T17:42:02.463 に答える
0

おそらく、配列またはリストを作成し、リストに sqlReader を設定できます。List と Array は、WCF を使用してシリアル化および転送でき、相互運用も可能です。

while ループの内部

listObject.Add(sqlReader[0].ToString());
于 2013-05-15T17:20:22.043 に答える