操作可能会破坏运行时的稳定?
我在理解这里出现的问题上有点麻烦。 我有一些代码使用LINQ从数据库中提取logging,并将它们放入一个投射到界面的对象中。 它看起来有点像这样:
public IEnumerable<ISomeObject> query() { return from a in dc.SomeTable select new SomeObject { //Assign various members here } as ISomeObject; }
当我testing这个时,我把返回的IEnumerable放到一个名为results的variables中,并运行这一行:
Assert.AreEqual(EXPECTED_COUNT, results.Count());
当这个运行时,我得到一个System.Security.VerificationException:“操作可能会破坏运行时。”
我在这里find了解决scheme,这是:
var results = from a in dc.SomeTable select new SomeObject { //Assign various members here } as ISomeTable; return results.OfType<ISomeObject>();
这工作,但我无法理解这里发生了什么。 为什么我首先得到exception,以及上面的代码行是如何解决的呢? MSDN文档似乎表明,这是一个types安全的问题,但我没有看到以前的代码types不安全的地方。
更新更多的信息,我发现了。 第一个例子工作,如果我使返回typesIQueryable。 这对于发生了什么问题有了更多的了解 ,但是我仍然对此感到困惑。 为什么编译器不让我把IEnumerable转换成IQueryable?
我相信这是论坛post中提到的协变或逆变问题。
请参阅C#中的协变和反variables,第二部分:arrays协 方差以及 Eric Lippert博客中的协方差和反variables系列的其余部分。
虽然他在与我联系的文章中讨论数组,但我相信在这里也会出现类似的问题。 在第一个例子中,您将返回一个IEnumerable
,它可能包含实现比ISomeTable
更大的接口的对象(例如,当IEnumerable只能包含长颈鹿时,您可以将一只Turtle放入一个Animals IEnumerable中)。 我认为它返回IQueryable
的原因是因为它比任何可能返回的更大/更宽 ,所以你可以保证你返回的东西将能够处理(?)。
在第二个示例中, OfType确保返回的内容是存储所有必要信息的对象,以便只返回可以转换为长颈鹿的那些元素。
我很确定这与上面提到的types安全问题有关,但正如Eric Lippert所说, 高阶函数伤害了我的大脑,而且我无法准确地expression这是一个合作/逆变问题。
我发现这个条目,同时寻找我自己的解决scheme,“操作可能会破坏运行时”。 虽然上面的协方差/对比方差build议看起来非常有趣,但最终我发现通过运行我的unit testing,打开了代码覆盖率并设置了AllowPartiallyTrustedCallers程序集属性,我得到了相同的错误消息。
删除AllowPartiallyTrustedCallers属性导致我的testing运行良好。 我也可以closures代码覆盖,使他们运行,但这不是一个可以接受的解决scheme。
希望这可以帮助其他人,使其到这个网页试图find解决这个问题。
只是一个猜测,但是as运算符可能会返回null – 所以它可能与new SomeObject { ... }
代码的实际实现有关,因为它是语法糖。 return results.OfType<ISomeTable>();
基于types的filter,所以你的方法的返回语句将只返回该types(确保types安全)。 我遇到类似的问题,返回genericstypes。
PS我喜欢“操作可能会破坏运行时的稳定性”。 例外。 这几乎就像“你可能会炸毁互联网”的例外。
我用类似的代码来看到这个错误。
IEnumerable<Table> records = (from t in db.Tables where t.Id.Equals(1) select t).ToList();
这个看似无害的代码是从页面调用的UserControl方法的一部分。 在.NET4开发环境中没有问题,但是,当这个站点被预先编译并部署到.NET3.5上的服务器时,我得到了这个错误。
我怀疑这与这个事实有关,控件被编译成一个单独的DLL,并且在这个.NET安全博客中描述的框架之间的安全变化
我的解决scheme:在.NET4上运行实时站点
如果你改变这个,它仍然失败:
select new SomeObject { ... } as ISomeTable;
对此:
select (ISomeTable) new SomeObject { ... };
?
如果是的话(就像我看到你已经证实),也许这与接口实现可能是类或结构的事实有关? 如果转换为抽象类而不是接口,问题是否仍然存在?
我发现OfType在使用linq到sql时有一些令人讨厌的副作用。 例如,以前在对数据库运行查询之后评估的linq部分被转换为SQL。 这失败了,因为这些部分没有SQL等效。 我最终使用.Cast而不是似乎也解决了这个问题。
在我的情况下,我错误地声明了Linq2SQL类的Column属性中的Storage属性
[Column(Storage = "_Alias", DbType = "NVarChar(50)")] public string UserAlias
我有同样的问题,但与inheritance我定义了一个类在程序集A和一个子类在程序集B后,我将下面的属性添加到程序集A,问题解决了:
[assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust = true)]
我遇到了这个错误,同时使用“dynamic数据访问框架” 被动库 。 错误的来源是DynamicDatabase.cs文件中的第100行。
databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector());
我将这行代码改为:
databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector()).OfType<IDatabaseDetector>();
这样做解决了这个问题。 我继续前进并分发了这个项目 ,并将这个改动提交给了原作者。
谢谢贾森·贝克(Jason Baker)在你的原始问题中指出了解决scheme。
在附注中,原始库在我的本地机器和Rackspace VPS上运行良好,但是当我将相同的代码推送到共享主机环境(GoDaddy和Rackspace的云网站)时,我开始得到“操作可能会破坏运行时“错误。
我猜,Linq to Sql在转换成sql语句时可能不支持强制转换。