如何在C#WCF中返回SqlDataReader?

时间:2013-05-15 17:14:30

标签: c# visual-studio-2010 wcf

在我的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;

这给了我我想要的东西:)

祝你好运

6 个答案:

答案 0 :(得分:4)

您需要定义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.GetXml()

将返回类型作为字符串发送

将DataTable转换为Json

string json = JsonConvert.SerializeObject(table, Formatting.Indented);

答案 1 :(得分: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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

在while循环中

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

答案 4 :(得分:0)

您需要实际读取所有datareader行,方法是将它们加载到数据表中,datareader是一个惰性加载对象,不能通过网络发送,因为它从未完全填充在那里:

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

然后,由于您使用的是wcf,因此可能需要将该数据表加载到与您的合同接口匹配的对象中。看看下面的snipet,它通过使用反射将任意数据表转换为匹配属性的行为良好的对象。

代码段用法

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

答案 5 :(得分: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>>