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 服务使用者,您可以从服务方法返回DaTaSet 或 DataTable 。您需要使用SqlDataAdapter而不是 sqlReader 并填充 DataTable 或 Dataset 并返回它。您可以在服务方法定义中不更改任何数量的列。您甚至可以通过使用将返回类型作为字符串发送DataSet.GetXml()

将数据表转换为 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 旨在最小化工作内存,因此只会一一查询结果。如果您想获得所有结果,您可以在代码周围使用 while 循环来获取行,只要它们可用。通过调用 return 您将中断 while 循环并仅返回第一行。如果您调用 yield return anIEnumerable<string>将由您的方法返回,而不是string.

于 2013-05-15T17:19:13.080 回答
0

您可能可以创建一个数组或列表并使用您的 sqlReader 填充列表。List 和 Array 可以使用 WCF 进行序列化和传输,并且可以互操作。

在while循环内部

listObject.Add(sqlReader[0].ToString());
于 2013-05-15T17:20:22.043 回答
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

古老的线程,但我会添加我的两个:

        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 回答