【问题标题】:Get Dictionary Object from Linq context.ExecuteQuery using dynamic query使用动态查询从 Linq context.ExecuteQuery 获取字典对象
【发布时间】:2017-07-27 19:29:49
【问题描述】:

我有这样的查询

string sql = " Select Id, CateId  From StateCategories ";

我有几个查询选择二到 N 列,我之前无法决定,因为我的查询是在运行时构建的。

我想在不使用任何模型对象的情况下(对于上述查询)将其结果转换为字典对象。喜欢(我尝试过的)

var alertCount = context.ExecuteQuery<Dictionary<int, int>>(sql).FirstOrDefault();

从上面的查询中,我希望Id 作为键,CateId 作为字典的值。

请注意,在查询中,有两列是整数(至少我保证)。 但它失败了(而且很可能)

无法为成员“比较器”赋值。它没有定义 setter。

有什么更好的方法来做到这一点?

【问题讨论】:

  • 而不是说“如果?”你为什么不自己试试呢?
  • “如果我使用元组而不是字典会怎样” - 你试过了吗?
  • 我的问题是对于所有DictionaryTuple 并且我尝试选择多个列。如果您跳过这些what ifs 我的问题仍然渴望得到答案。 :)
  • 好的,所以你尝试了一件事 - 但你想到了其他一些。你问之前有没有试过?如果是这样,发生了什么?您不应该只是从问题中删除您的想法 - 您应该尝试它们,并将该信息包含在问题中。
  • 不,在上面的问题中尝试元组的结果是 not 。并且请不要假设拒绝投票是因为没有答案 - 这只是假设这是一个好问题,IMO 不是。

标签: c# linq dynamic linq-to-sql


【解决方案1】:

经过一些在线研究并从 2012 年的这篇文章中找到了这个想法

DataContext ExecuteQuery extension method returning dynamic objects

下面的扩展方法和支持类可以用来实现你想要的。

public static class DataContextExtensions {
    public static IEnumerable<dynamic> ExecuteQuery(this DataContext ctx, string query, DbParameter[] parameters = null) {
        using (var cmd = ctx.Connection.CreateCommand()) {
            cmd.CommandText = query;
            if (parameters != null) cmd.Parameters.AddRange(parameters);
            ctx.Connection.Open();
            using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
                while (rdr.Read()) {
                    dynamic row = new DynamicRow();
                    for (int i = 0; i < rdr.FieldCount; i++) {
                        row[rdr.GetName(i)] = rdr[i];
                    }
                    yield return row;
                }
            }
        }
    }


    /// <summary>
    /// DynamicRow class is similiar to ExpandoObject but with addition of indexer
    /// </summary>
    public class DynamicRow : DynamicObject {
        private readonly Dictionary<string, object> _data = new Dictionary<string, object>();

        public object this[string propertyName] {
            get {
                object result = null;
                TryGetMember(propertyName, out result);
                return result;
            }
            set { TrySetMember(propertyName, value); }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result) {
            return TryGetMember(binder.Name, out result);
        }

        private bool TryGetMember(string propertyName, out object result) {
            return _data.TryGetValue(propertyName.ToLower(), out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value) {
            return TrySetMember(binder.Name, value);
        }

        private bool TrySetMember(string propertyName, object value) {
            _data[propertyName.ToLower()] = value;
            return true;
        }
    }
}

鉴于您不愿意使用强类型模型将项目从上下文中取出,那么另一种选择是使用动态对象。这会带来其自身的风险,因为类型和属性要到运行时才能知道。

使用上面的代码,下面将从查询中提取数据,然后您可以使用 linq ToDictionary 将记录转换为所需的类型。

var sql = " Select Id, CateId  From StateCategories ";
var dictionary = context.ExecuteQuery(sql).ToDictionary(_ => (int)_.Id, _ => (int)_.CateId);

这应该让你开始,你应该能够从那里提取你需要的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多