【问题标题】:LinqPad dynamic sql and displaying resultsLinqPad 动态 sql 并显示结果
【发布时间】:2015-02-25 17:56:59
【问题描述】:

我正在使用 LinqPad 执行一些动态 sql,当我调用 .Dump() 时它返回 IEnumerable。我希望它显示它返回的匿名类型的结果。任何有关在 LinqPad 中执行动态 sql 语句并显示结果的帮助将不胜感激。

这是我正在尝试做的代码 sn-p:

// Any sql string for example.
var query = "SELECT DISTINCT [CustomerId] FROM Customers Where CustomerId = 2";

var dyn = this.ExecuteQuery<dynamic>(query);

LINQPad.Extensions.Dump(dyn);

【问题讨论】:

标签: c# sql dynamic linqpad


【解决方案1】:

您在使用 IDataRecord 时走在正确的轨道上。要使输出动态化,请使用 DynamicObject:

static class Extensions
{
    public static IEnumerable<dynamic> ExecuteSQL (this DataContext dc, string sql)
    {
        var cx = new SqlConnection (dc.Connection.ConnectionString);
        cx.Open();
        return new SqlCommand (sql, cx).ExecuteReader (CommandBehavior.CloseConnection).Cast<IDataRecord>().Select (r => new DynamicDataRecord (r));
    }
}

class DynamicDataRecord : System.Dynamic.DynamicObject
{
    readonly IDataRecord _row;
    public DynamicDataRecord (IDataRecord row) { _row = row; }

    public override bool TryConvert (System.Dynamic.ConvertBinder binder, out object result)
    {
        if (binder.Type == typeof (IDataRecord))
        {
            result = _row;
            return true;
        }
        return base.TryConvert (binder, out result);
    }

    public override bool TryInvokeMember (System.Dynamic.InvokeMemberBinder binder, object [] args, out object result)
    {
        if (binder.Name == "Dump")
        {
            if (args.Length == 0)
                _row.Dump ();
            else if (args.Length == 1 && args [0] is int)
                _row.Dump ((int)args [0]);
            else if (args.Length == 1 && args [0] is string)
                _row.Dump ((string)args [0]);
            else if (args.Length == 2)
                _row.Dump (args [0] as string, args [1] as int?);
            else
                _row.Dump ();
            result = _row;
            return true;
        }
        return base.TryInvokeMember (binder, args, out result);
    }

    public override bool TryGetMember (System.Dynamic.GetMemberBinder binder, out object result)
    {
        result = _row [binder.Name];
        if (result is DBNull) result = null;
        return true;
    }

    public override bool TryGetIndex (System.Dynamic.GetIndexBinder binder, object [] indexes, out object result)
    {
        if (indexes.Length == 1)
        {
            result = _row [int.Parse (indexes [0].ToString ())];
            return true;
        }
        return base.TryGetIndex (binder, indexes, out result);
    }

    public override IEnumerable<string> GetDynamicMemberNames ()
    {
        return Enumerable.Range (0, _row.FieldCount).Select (i => _row.GetName (i));
    }
}

这将允许以下操作:

this.ExecuteSQL ("select * from customer").GroupBy (c => c.Name).Dump();

编辑:从 v4.53.02 开始,此功能现在可在 LINQPad 中使用。你现在可以去:

ExecuteQueryDynamic ("SELECT DISTINCT * FROM Customer WHERE ID = {0}", 2)

【讨论】:

  • 我在 v4.51.03 版本上运行了“检查更新”,LINQPad 报告说没有任何更新。 v4.53.02 更新何时发布?
【解决方案2】:

所以我为得到结果所做的就是这样,但我认为必须有更好的方法。

using (SqlConnection connection = new SqlConnection(this.Connection.ConnectionString))
{
  connection.Open();

  SqlCommand command = new SqlCommand(query, connection);
  SqlDataReader reader = command.ExecuteReader();

  reader.Cast<IDataRecord>().AsQueryable().Dump();      
}

【讨论】:

    【解决方案3】:

    除了Joe's answer

    使用 Linq-to-SQL 连接很重要,因为ExecuteQueryDynamic
    实体框架中不可用

    以下是在 LinqPad 5 中如何将不同的数据类型作为参数处理(基于 Northwind 数据库):

    void Main()
    {
        // Boolean
        ExecuteQueryDynamic(@"DECLARE @Discontinued bit={0}; 
                            SELECT DISTINCT * FROM Products 
                            WHERE Discontinued = @Discontinued", true).Dump();
        // Int
        ExecuteQueryDynamic(@"DECLARE @OrderId Int={0}; 
                            SELECT DISTINCT OrderId, CustomerId, ShipName FROM Orders 
                            WHERE OrderID = @OrderId", 10248).Dump();
        // String
        ExecuteQueryDynamic(@"DECLARE @CustomerId nvarchar(max)={0}; 
                            SELECT DISTINCT * FROM Customers 
                            WHERE CustomerId = @CustomerId", "VINET").Dump();
    }
    

    我建议您对 SQL 变量使用DECLARE 语句。这样,您可以首先在 T-SQL(或 LinqPad SQL 模式)中尝试使用分配的固定值 - 如果数据类型不匹配,您将收到有意义的错误消息,然后您可以将其插入 ExecuteQueryDynamic 并插入 @987654325 @为第一、二、三、...参数如下:

        ExecuteQueryDynamic(@"DECLARE @Discontinued bit={0}; DECLARE @ProductID Int={1}; 
                              DECLARE @CategoryID Int={2}; 
                              SELECT DISTINCT * FROM Products 
                              WHERE Discontinued = @Discontinued AND ProductId = @ProductID 
                              AND CategoryID = @CategoryID;                     
                             ", true, 5, 2).Dump();
    

    注意: ExecuteQueryDynamic 不支持多个结果集。这意味着,只允许一个 SELECT 语句,其他的将被忽略。

    【讨论】:

      猜你喜欢
      • 2011-08-30
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多