操作可能会破坏运行时的稳定性?

时间:2008-12-18 19:19:39

标签: c# .net linq linq-to-sql .net-3.5

我在理解这里的问题时遇到了一些麻烦。我有一些代码使用LINQ从数据库中提取记录,并将它们放入一个被转换为接口的对象中。看起来有点像这样:

public IEnumerable<ISomeObject> query()
{
    return from a in dc.SomeTable
           select new SomeObject
           {
             //Assign various members here
           } as ISomeObject;
}

当我测试它时,我将返回的IEnumerable放入一个名为results的变量中并运行这一行:

Assert.AreEqual(EXPECTED_COUNT, results.Count());

当运行它时,我得到一个System.Security.VerificationException:“操作可能会破坏运行时的稳定性。”

我找到了解决方案here,就是这样:

var results = from a in dc.SomeTable
              select new SomeObject
              {
                //Assign various members here
              } as ISomeTable;
return results.OfType<ISomeObject>();

这有效,但我无法理解这里发生的事情。为什么我首先得到异常,上面的代码行是如何解决的? MSDN文档似乎表明这是类型安全的问题,但我没有看到以前的代码在类型不安全的位置。

更新 我发现了更多的信息。如果我返回类型IQueryable,第一个示例有效。这使得 出错了一点点,但我仍然对为什么感到困惑。为什么编译器不强迫我将IEnumerable转换为IQueryable?

11 个答案:

答案 0 :(得分:19)

我认为这是this forum post所指出的协方差或逆转问题。

请参阅Eric Lippert博客中的Covariance and Contravariance in C#, Part Two: Array Covariance和其他Covariance and Contravariance series

虽然他在我链接的文章中处理数组,但我相信类似的问题出现在这里。在第一个示例中,您将返回IEnumerable,其中可能包含实现大于的接口的对象,而不是ISomeTable(即 - 您可以将Turtle放入动物IEnumerable中当IEnumerable只能包含Giraffes时)。我认为当你返回IQueryable时它起作用的原因是因为它比你可以返回的任何东西更大/更宽,所以你保证你返回的东西能够处理( ?)。

在第二个例子中,OfType确保返回的内容是一个对象,它存储了只返回那些可以强制转换为Giraffe的元素所需的所有信息。

我很确定它与上面列出的类型安全问题有关,但正如Eric Lippert所说Higher Order Functions Hurt My Brain而我无法准确地说出为什么这是一个共同/逆变问题。

答案 1 :(得分:14)

我在寻找自己的解决方案时发现了这个条目,“操作可能会破坏运行时的稳定性”。虽然上面的协方差/反差方案建议看起来非常有趣,但最后我发现通过运行我的单元测试并启用代码覆盖率和AllowPartiallyTrustedCallers程序集属性集,我得到了相同的错误消息。

删除AllowPartiallyTrustedCallers属性导致我的测试运行正常。我还可以关闭代码覆盖率以使其运行但这不是一个可接受的解决方案。

希望这有助于其他人访问此页面,试图找到解决此问题的方法。

答案 2 :(得分:5)

只是一个猜测,但 as 运算符可能返回null - 因此它可能与new SomeObject { ... }代码的实际实现有关,因为它是语法糖。 return results.OfType<ISomeTable>();过滤器基于类型,因此您的方法的return语句将仅返回该类型(确保类型安全)。我在返回泛型类型方面遇到了类似的问题。

P.S。我喜欢“操作可能破坏运行时的稳定性”。例外。这几乎就像“你可能会炸毁互联网”例外。

答案 3 :(得分:2)

我用类似的代码遇到了这个错误;

IEnumerable<Table> records = (from t in db.Tables
                              where t.Id.Equals(1)
                              select t).ToList();

这个看似无害的代码是从Page调用的UserControl方法的一部分。但是,在.NET4开发环境中没有问题,当网站预编译并在.NET3.5上部署到服务器时,我收到了此错误。

我怀疑这与控件被编译成一个单独的DLL以及框架之间的安全性更改这一事实有关,如this .NET security blog

中所述

我的解决方案:在.NET4上运行实时网站

答案 4 :(得分:0)

如果你改变它仍然会失败:

select new SomeObject { ... } as ISomeTable;

到此:

select (ISomeTable) new SomeObject { ... };

如果是这样(我认为你已经证实),或许这与接口实现可以是类还是结构这一事实有关?如果转换为抽象类而不是接口,问题是否仍会出现?

答案 5 :(得分:0)

我发现当使用linq到sql时,OfType有一些令人讨厌的副作用。例如,在针对db运行查询之后先前评估的linq的部分被转换为SQL。这失败了,因为这些部分没有SQL等价物。我最终使用了.Cast,这似乎也解决了这个问题。

答案 6 :(得分:0)

在我的情况下,我错误地在Linq2SQL类的Column属性中声明了Storage属性

    [Column(Storage = "_Alias", DbType = "NVarChar(50)")]
    public string UserAlias

答案 7 :(得分:0)

我有同样的问题,但继承 我在程序集A中定义了一个类,在程序集B中定义了一个子类 在我将下面的属性添加到程序集A后,问题解决了:

[assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust = true)]

答案 8 :(得分:0)

我在使用&#34;动态数据访问框架&#34;时遇到了这个错误。 Passive library。错误的来源是DynamicDatabase.cs文件中的第100行。

databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector());

我将这行代码更改为:

databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector()).OfType<IDatabaseDetector>();

这样做解决了这个问题。我继续forked the project并将更改提交给原作者。

谢谢Jason Baker在原始问题中指出解决方案。

另一方面,我的本地计算机和Rackspace VPS上的原始库运行正常,但当我将相同的代码推送到共享托管环境(GoDaddy和Rackspace的云站点)时,我开始得到&#34;操作可能会破坏运行时的稳定性。错误。

答案 9 :(得分:0)

`我在“ System.Security.VerificationException”部分添加到了web.config文件中:“操作可能会破坏运行时的稳定性。”不来找我。

  <script type="text/javascript">
    $(document).ready(function () {
      $("li").filter(function() {
        return $(this).text() === '0';
      })
      .hide()
    })
  </script>

答案 10 :(得分:-4)

我猜,在转换为sql语句时,Linq to Sql可能不支持转换。