【问题标题】:Using IEnumerable<IDataRecord> to return data使用 IEnumerable<IDataRecord> 返回数据
【发布时间】:2016-10-31 12:50:23
【问题描述】:

我正在尝试使用带有给定字段的 IEnumerable 返回数据,我正在调用我想要引用带有给定字段名称的数据的方法并返回它。

例子,这里是函数

    public IEnumerable<IDataRecord> GetSomeData(string fields, string table, string where = null, int count = 0)
    {
        string sql = "SELECT @Fields FROM @Table WHERE @Where";

        using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
        using (SqlCommand cmd = new SqlCommand(sql, cn))
        {
            cmd.Parameters.Add("@Fields", SqlDbType.NVarChar, 255).Value = where;

            cn.Open();

            using (IDataReader rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                    yield return (IDataRecord)rdr;
                }
            }
        }
    }

调用:

IEnumerable<IDataRecord> data = bw.GetSomeData("StaffCode, Perms", "BW_Staff", "StaffCode = 'KAA'");

我必须怎么做才能以这种方式或以什么方式返回数据?

string staffCode = data["StaffCode"].ToString();
string perms = data["Perms"].ToString();

感谢您的帮助

【问题讨论】:

  • "fields" 需要是字符串数组或在分隔符上拆分的分隔字符串。然后循环该字段数组以构建您的 cmd.Parameters.Add 行。

标签: c# sql string ienumerable reader


【解决方案1】:

您的数据变量是行的集合。您需要遍历集合以对每一行做一些有趣的事情。

foreach (var row in data)
{
    string staffCode = row["StaffCode"].ToString();
    string perms = row["Perms"].ToString();
}

更新:

根据您只希望 GetSomeData(...) 返回单行的评论,我建议两件事中的一件。

更改 GetSomeData 的签名以返回 IDataRecord。并从实现中删除“yield”。

public IDataRecord GetSomeData(string fields, string table, string where = null, int count = 0)
    {
        string sql = "SELECT @Fields FROM @Table WHERE @Where";

        using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
        using (SqlCommand cmd = new SqlCommand(sql, cn))
        {
            cmd.Parameters.Add("@Fields", SqlDbType.NVarChar, 255).Value = where;

            cn.Open();

            using (IDataReader rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                    return (IDataRecord)rdr;
                }
            }
        }
    }
}

或者

var row = data.FirstOrDefault();
if (row != null)
{
    string staffCode = row["StaffCode"].ToString();
    string perms = row["Perms"].ToString();
}

备注:

您的 GetSomeData 实现不完整。您甚至没有使用几个参数,最重要的是 fields 参数。从概念上讲,在 SQL 中,您不能参数化返回哪些字段或使用哪个表(等等),而是需要构造一个动态查询并执行它。

更新 2

这是构造正确查询的 GetSomeData 实现(在 C# 6 中,如果您在早期版本中需要它,请告诉我)。

public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0)
{
    var predicate = string.IsNullOrWhiteSpace(where) ? "" : " WHERE " + where;
    string sql = $"SELECT { string.Join(",", fields) } FROM {table} {predicate}";

    using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
    using (SqlCommand cmd = new SqlCommand(sql, cn))
    {
        cn.Open();

        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return (IDataRecord)rdr;
            }
        }
    }
}

这就是你将如何使用它。

IEnumerable<IDataRecord> data = bw.GetSomeData(new[] { "StaffCode", "Perms" }, "BW_Staff", "StaffCode = 'KAA'");

您可以枚举它或调用 .FirstOrDefault,这是您的选择。每次调用 GetSomeData 时,它都会运行查询。

更新 3

GetSomeData 使用早期版本的 C# 实现

public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0)
{
    var predicate = string.IsNullOrEmpty(where) ? "" : " WHERE " + where;
    string sql = string.Format("SELECT {0} FROM {1} {2}", string.Join(",", fields), table, predicate);

    using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug)))
    using (SqlCommand cmd = new SqlCommand(sql, cn))
    {
        cn.Open();

        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return (IDataRecord)rdr;
            }
        }
    }
}

【讨论】:

  • 这是否意味着它一次又一次地调用查询?有什么办法不使用循环?谢谢
  • 也许我不理解你原来的问题。你能准确描述你想要达到的目标吗?
  • 虽然我可以理解字段必须是一个字符串数组,但我想调用一次该方法以便它运行一个查询...我输入字段名称... field1, field2, field3 as参数..“选择字段 1、字段 2、字段 3...”。将该方法作为数组调用......并输出具有给定字段名称的数据。例如数组[“field1”]、数组[“field2”]等..
  • 代码产生每一行,所以接收方法get是一个包含where子句中所有字段的对象。当接收方法完成处理一个产生的行时,while(rdr.Read()) 会更进一步并产生另一行。 @firstQuestion:不,查询被调用一次,连接一直保持到所有行都产生或调用方法中止。
  • 我使用 GetSomeData() 只返回一行,这就是为什么我不想使用任何类型的循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
相关资源
最近更新 更多