Операция может дестабилизировать время выполнения? - PullRequest
37 голосов
/ 18 декабря 2008

У меня небольшие затруднения с пониманием, в чем здесь проблема. У меня есть немного кода, который извлекает записи из базы данных с помощью 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: «Операция может дестабилизировать среду выполнения.»

Я нашел решение здесь , а именно:

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

Это работает, но мне трудно понять, что здесь происходит. Почему я вообще получил исключение и как строки кода выше исправили это? Документация MSDN, по-видимому, предполагает, что это проблема безопасности типов, но я не вижу, где предыдущий код был небезопасным.

UPDATE Чуть больше информации я узнал. Первый пример работает, если я сделаю возвращаемый тип IQueryable. Это проливает немного больше света на , что пошло не так, но я все еще не понимаю, почему почему . Почему компилятор не заставил меня преобразовать IEnumerable в IQueryable?

Ответы [ 10 ]

19 голосов
/ 18 декабря 2008

Я считаю, что это проблема ковариации или контравариантности, как отмечено в этом сообщении на форуме .

См. Ковариация и Контравариантность в C #, Часть вторая: Ковариация массива и остальные серии Ковариация и Контравариантность в блоге Эрика Липперта.

Хотя он имеет дело с Массивами в статье, которую я связал, я думаю, что подобная проблема возникает здесь. В вашем первом примере вы возвращаете IEnumerable, который может содержать объекты, реализующие интерфейс, который на больше , чем ISomeTable (то есть - вы можете поместить Черепашку в IEnumerable Animals, когда этот IEnumerable может только содержат жирафов). Я думаю, что причина, по которой это работает, когда вы возвращаете IQueryable, заключается в том, что это больше / шире , чем все, что вы могли бы вернуть, поэтому вы гарантированно, что то, что вы вернете, вы сможете обработать (?).

Во втором примере OfType гарантирует, что возвращаемое является объектом, который хранит всю информацию, необходимую для возврата только тех элементов, которые могут быть брошены в Giraffe.

Я почти уверен, что это как-то связано с вопросами безопасности типов, о которых говорилось выше, но, как говорит Эрик Липперт, Функции высшего порядка повредили мой мозг , и у меня возникают проблемы с точным объяснением, почему это сопутствующая / контравариантная проблема.

14 голосов
/ 21 мая 2010

Я нашел эту запись, когда искал собственное решение о том, что «операция может дестабилизировать среду выполнения». Хотя приведенный выше совет по ковариации / противодействию выглядит очень интересным, в итоге я обнаружил, что получаю то же сообщение об ошибке, выполняя свои модульные тесты с включенным покрытием кода и установленным атрибутом сборки AllowPartiallyTrustedCallers.

Удаление атрибута AllowPartiallyTrustedCallers приводило к тому, что мои тесты работали нормально. Я также мог отключить покрытие кода для их запуска, но это было неприемлемым решением.

Надеюсь, это поможет кому-то другому, кто зайдет на эту страницу, попытаться найти решение этой проблемы.

5 голосов
/ 18 декабря 2008

Просто предположение, но оператор как может возвращать ноль - так что это может иметь отношение к фактической реализации кода new SomeObject { ... }, поскольку это синтаксический сахар. Фильтр return results.OfType<ISomeTable>(); основан на типе, поэтому оператор возврата вашего метода будет возвращать только этот тип (обеспечивая безопасность типов). Я столкнулся с подобной проблемой с возвращением универсальных типов.

P.S. Мне нравится «Операция может дестабилизировать время выполнения». исключение. Это почти как исключение «Вы можете взорвать интернет».

2 голосов
/ 11 сентября 2012

Я сталкивался с этой ошибкой с похожим кодом;

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

Этот, казалось бы, безвредный код был частью метода UserControl, который вызывался со страницы. Никаких проблем в среде разработки .NET4, однако, когда сайт был предварительно скомпилирован и развернут на сервере в .NET3.5, я получил эту ошибку.

Я подозреваю, что это как-то связано с тем, что элемент управления был скомпилирован в отдельную DLL в сочетании с изменениями безопасности между платформами, как описано в этом блоге по безопасности .NET

Мое решение: запустить работающий сайт на .NET4

0 голосов
/ 06 июня 2014

Я столкнулся с этой ошибкой при использовании «Динамического каркаса доступа к данным» Пассивная библиотека . Источником ошибки была строка 100 в файле DynamicDatabase.cs.

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

Я изменил эту строку кода на:

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

Это решило проблему. Я пошел вперед и разветвил проект и отправил изменения первоначальному автору.

Спасибо, Джейсон Бейкер, за то, что вы указали решение в вашем первоначальном вопросе.

Кроме того, исходная библиотека работала нормально на моем локальном компьютере и в Rackspace VPS, но когда я перенес один и тот же код в среду общего хостинга (GoDaddy и облачные сайты Rackspace), я начал получать «Операция может «дестабилизировать время выполнения».

0 голосов
/ 03 декабря 2013

У меня была такая же проблема, но с наследованием Я определил класс в сборке A и подкласс в сборке B после того, как я добавил ниже атрибут в сборку A, проблема решена:

[assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust = true)]
0 голосов
/ 20 ноября 2013

В моем случае я ошибочно объявил свойство Storage в атрибуте Column класса Linq2SQL

    [Column(Storage = "_Alias", DbType = "NVarChar(50)")]
    public string UserAlias
0 голосов
/ 05 мая 2009

Я обнаружил, что у OfType были некоторые неприятные побочные эффекты при использовании linq to sql. Например, части linq, которые ранее оценивались после выполнения запроса к базе данных, вместо этого были переведены в SQL. Это не удалось, поскольку эти разделы не имели эквивалента SQL. В итоге я вместо этого использовал .Cast, который, похоже, тоже решил проблему.

0 голосов
/ 19 декабря 2008

Полагаю, что Linq to Sql может не поддерживать приведение при переводе в оператор SQL.

0 голосов
/ 18 декабря 2008

Будет ли сбой, если вы измените это:

select new SomeObject { ... } as ISomeTable;

к этому:

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

Если это так (как я вижу, вы подтвердили), возможно, это связано с тем, что реализация интерфейса может быть либо классом, либо структурой? Проблема все еще появляется, если вы приводите к абстрактному классу, а не к интерфейсу?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...