【问题标题】:Database.Query return type should be IEnumerable<dynamic>Database.Query 返回类型应该是 IEnumerable<dynamic>
【发布时间】:2013-03-20 14:00:55
【问题描述】:

我需要帮助来理解这件事。为什么在下面的代码中变量“ejes”和“habilidades”被解析为“动态”而第三个被解析为IEnumerable&lt;dynamic&gt;。这会影响接下来运行的代码,当我尝试调用扩展方法“Count()”时出现异常,因为“ejes”和“habilidades”不是 IEnumerable。它们是同一方法“Database.Query”的结果。

这里是sn-p:

var db = Database.Open("froned");
db.Execute("begin transaction");

try
{
  var asignacion = db.QuerySingle("select * from asignacion_avanza where id_asignacion = @0", id_asignacion);

  var ejes = db.Query(String.Format(@"
                                  select id_eje
                                    from asignatura_eje_nivel
                                   where id_nivel = {0}
                                     and id_asignatura = {1}",
                                       asignacion.id_nivel,
                                       asignacion.id_asignatura));

  var habilidades = db.Query(String.Format(@"
                                  select id_habilidad
                                    from asignatura_habilidad_nivel
                                   where id_nivel = {0}
                                     and id_asignatura = {1}",
                                       asignacion.id_nivel,
                                       asignacion.id_asignatura));
  var dificultades = db.Query("select id_dificultad from dificultad");

  var c_dif = dificultades.Count();
  var c_eje = ejes.Count();
  var c_habilidades = habilidades.Count();

我放了一个调试器的图像来显示变量的运行时类型。

【问题讨论】:

  • 很棒的 VS2012 的深色主题。您应该将图片的链接放在您的问题中,很难从图片中读取那么小的文字(而且我懒得查看源代码)。
  • 是的,在正常尺寸下有点难以看清,但只需按 ctrl 键并向上滚动即可放大。图片质量很好,因此即使放大很大也可以完美阅读.

标签: c# dynamic ienumerable webmatrix


【解决方案1】:

asignacion.id_nivelasignacion.id_asignatura 是动态类型。

当您将动态类型作为参数传递给任何方法时,该方法的返回类型将变为动态类型,而不是 MSDN 所说的任何类型。您不能对动态类型使用扩展方法。 Count()Enumerable 的扩展方法。这就是你得到例外的原因。

有两种方法可以解决问题并将返回类型恢复为 Enumerable。首先是明确定义:

IEnumerable<dynamic> data = db.Query(someSQL, parameterValue);

另一种是将参数强制转换为非动态类型:

var data = db.Query(someSQL, (string)parameterValue);

正如 Knox 指出的那样,您必须使用参数而不是 string.Format。

【讨论】:

  • 迈克,感谢您的解释。你知道这是否在 MSDN 中的某个地方提到过吗?确保该陈述始终有效。我没有使用正常的参数规范,因为很多时候,例如参数是一个字符串,我在解析步骤中遇到问题......'@i' 被错误解释......当我有十多个参数......并且使用 String.Format 我从来没有遇到任何问题......DataBase.Query 的 msdn 站点有点差......并且不解释任何提到的案例。
  • 比MSDN好,这里出自飞碟之口:stackoverflow.com/questions/15391115/…
【解决方案2】:

你确定habilidades和另一个有数据吗?我认为可能是 db.Query 返回 null,这意味着没有返回行,然后 habilidades.Count 无法执行,因为 null 没有要执行的对象。在调试器之外进行测试的一种方法是执行 db.QueryValue("Select Count(*) from ...") 并查看是否返回零行。

顺便说一句,C# 中的数据库函数构建变量处理的方式比您所拥有的要短一些。你可以写

var ejes = db.Query( @"
        Select *  
        From asign  
        Where id_nivel = @0",   
        asignacion.id_nivel );  

这种技术称为参数化 SQL。我只显示一个参数,但您需要更多。 @0、@1、@2 等被替换,就像在 String.Format 中一样。

【讨论】:

    【解决方案3】:

    不同之处在于调试器是由于已经评估了困难
    (var c_dif = dificultades.Count();)。
    其他两个变量尚未评估(linq deferred)。 所以调试器更了解困难。

    【讨论】:

    • 如果我继续执行,则会引发异常。恰好在突出显示的行中。您的答案没有回应为什么他们被评估不同。此查询立即执行而不是延迟。
    • 嗯,它们看起来像 linq 枚举。由于上一行的 Count() 计算了困难,其他人正在等待他们的 Count()。我可能是错的,但这是合理的。
    • 检查它的最简单方法是在var c_dif = dificultades.Count();执行之前和之后比较困难的调试器值。
    猜你喜欢
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    相关资源
    最近更新 更多