如何在c# WCF中返回SqlDataReader

本文关键字:返回 SqlDataReader WCF | 更新日期: 2023-09-27 18:13:38

在我的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文件top:

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;

这正是我想要的

如何在c# WCF中返回SqlDataReader

您需要定义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并填充数据表或数据集并返回它。您可以在不更改Service方法定义的情况下配置任意数量的列。您甚至可以通过使用DataSet.GetXml()

将返回类型发送为字符串

将数据表转换为Json

string json = JsonConvert.SerializeObject(table, Formatting.Indented);
// 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

SqlReader旨在将工作内存最小化,因此只会逐个查询结果。如果您想获得所有结果,可以在代码周围使用while循环来获取行,只要它们可用。通过调用return,您将中断while循环并只返回第一行。如果您调用yield return,则您的方法将返回IEnumerable<string>而不是string

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

在while循环内

listObject.Add(sqlReader[0].ToString());

您需要通过将所有数据读取器行加载到数据表中来实际读取它们,数据读取器是一个lazyload对象,由于它在开始时从未完全填充,因此无法通过网络发送:

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;
        }
    }
}

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

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