【问题标题】:passing params expression results in strange error传递参数表达式会导致奇怪的错误
【发布时间】:2013-03-29 14:36:55
【问题描述】:

我有一个模型调用地址,我使用该模型创建了一些 crud 操作,在执行此操作的过程中,我想要一种可以基于任意数量的属性创建查询的方法:

public static IEnumerable<address> GetByParams(Expression<Func<address, bool>> predicate, int? pageNumber, int? pageSize)
    {
        using (IDbConnection db = DbFactory.OpenDbConnection())
        {
            if ((pageNumber != null) && (pageSize != null))
            {
                var data = db.Where<address>(predicate).Skip((int) pageNumber).Take((int) pageSize).ToList();
                if (data.Any())
                {
                    data[0].TotalCount = data.Count();
                    data[0].TotalPages = (int) (data.Count()/pageSize);
                }
                return data;
            }
            //this is the code that creates the error
            return db.Where<address>(predicate);
        }
    }

然后我尝试使用以下代码测试此代码:

ViewBag.PossibleBilling = new SelectList(address.GetByParams(x=> x.AddressType == 2,null,null),0);

然而,这会导致有史以来最奇怪的错误:(错误不是来自 selectList )

The given key was not present in the dictionary.

我尝试用谷歌搜索,但结果比实际错误更复杂。我想这与我没有将谓词设置为正确的类型有关,或者在我将谓词传递到 where 之前,谓词必须发生某些事情。

谓词的原因是我有一个为我生成所有这些的 TT 文件,所以我不知道属性名称并且需要保持异常。

编辑:

为了清楚地了解未来的阅读:我正在针对 servicestack.ormlite 使用它:https://github.com/ServiceStack/ServiceStack.OrmLite

我正在尝试创建一个 TT 文件以使用我的模型构建一些基本的 crud 方法,我在 ormlite 中找到了这段代码:

System.Collections.Generic.List<T> Where<T>(this System.Data.IDbConnection dbConn, object anonType) Member of ServiceStack.OrmLite.OrmLiteReadConnectionExtensions

对象 anonType 可以是我自己的查询/谓词

分页代码错误,但这不是错误的过程,drax 解决的问题是我使用了 Where,而我只需要一个带参数的选择。

此改进将代码的使用更改为以下过程:

public static List<T> Select<T>(this IDbConnection dbConn, Expression<Func<T, bool>> predicate)

此过程接受表达式并消除错误

谢谢

【问题讨论】:

  • 异常到底是在哪里抛出的?
  • 您必须发布异常的整个堆栈跟踪。您还有一个错误 - data.Count() 将始终返回当前页面的大小,而不是整个集合。
  • 为什么参数类型使用Expression&lt;Func&lt;address, bool&gt;&gt;而不是简单的Func&lt;address, bool&gt;
  • 数据库表的内容是什么,该语句的预期返回是什么?您需要消除可能的错误来源。您可以尝试使用 x=> x.AddressType == 2 直接调用该语句,或者在没有 where 的情况下测试它是否有效。
  • @nmat 我这里没有列出内容的原因是因为地址可以是你喜欢的任何东西,它只是一个地址,并且预期的类型在顶部带有 IEnumerable
    也无法调用addressType == 因为这是一个 TT 文件,其中包含对 TT 文件未知的任何类型的通用查询,该问题更多地针对会理解该问题的人,请参阅下面 JOn 和 drax 的 cmets 以获得更好的理解,但是感谢您的意见

标签: c# asp.net asp.net-mvc-4 expression ormlite-servicestack


【解决方案1】:

我认为您应该使用 Select 而不是 Where 扩展方法。所以你的例子可以写成:

public static IEnumerable<address> GetByParams(Expression<Func<address, bool>> predicate, int? pageNumber, int? pageSize)
{
    using (IDbConnection db = DbFactory.OpenDbConnection())
    {
        if ((pageNumber != null) && (pageSize != null))
        {
            var data = db.Select<address>(predicate).Skip((int) pageNumber).Take((int) pageSize).ToList();
            if (data.Any())
            {
                data[0].TotalCount = data.Count();
                data[0].TotalPages = (int) (data.Count()/pageSize);
            }
            return data;
        }
        //this is the code that creates the error
        return db.Select<address>(predicate);
    }
}

【讨论】:

  • 不,这会将地址投影为布尔值...根据方法的签名,这显然不是必需的。
  • @Jon Skeet 我认为这应该是正确的。这个扩展来自 OrmLite,被描述为 here 方法签名看起来像这样:public static List&lt;T&gt; Select&lt;T&gt;(this IDbConnection dbConn, Expression&lt;Func&lt;T, bool&gt;&gt; predicate)
  • 哇,与 LINQ 的其余部分相比,这是多么奇怪和完全。 (诚​​然,它适合 DataTable.Select,但 ick ick ick。)
  • 我无法反驳这一点。它也会很慢,因为它会在分页之前从数据库中获取所有项目。
  • 嗨,很抱歉延迟没有机会检查这个,因为我刚从山谷回来,但是我确实意识到代码在分页时不好,我的主要问题是传递参数,感谢有关使用 select 而不是 WHERE 的信息,我的头被一个地方缠住了,以至于我完全被事物本身蒙蔽了双眼。 @Jon bool 事情也让我感到震惊,老实说,我真的不明白为什么这是一个 bool,但如果我能改进这个过程并更好地调整我的 TT 文件,我将不胜感激。
【解决方案2】:

我的猜测是 address.GetByParams(...) 部分返回一个空集,因此 SelectList 的默认选择不能设置为第 0 个元素(它没有)。

检查您是否真的通过 GetByParams 从数据库中获取结果。是否存在 AddressType 等于 2 的地址?

【讨论】:

  • 不,有 2 个地址,如果我使用 Get(id) 等,它们会拉取,只有这个
  • 同样错误不在selectList上,有问题的错误与谓词有关,选择列表只是调用的一个例子
  • 好的,也许使用db.Address.Where(predicate)Db.Set&lt;Address&gt;.Where(predicate) 之类的东西来代替当前的db.Where&lt;address&gt;(predicate)
  • 这就是我正在使用的,这是 servicestack 没有设置 但调用 .where() 是一样的。这通常是 .where(x => x.AddressTYpe == 2) 但我想要做的是将 (x => x.AddressType) 作为参数传递,以便我可以从控制器添加任何内容并查询在任何事情上,我确信是这种方法导致了错误,而不是它的调用方式。 where 接受 Object anonType 的类型
  • public static System.Collections.Generic.List Where(this System.Data.IDbConnection dbConn, object anonType) ServiceStack.OrmLite.OrmLiteReadConnectionExtensions 的成员
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 2021-04-06
相关资源
最近更新 更多