Linq to SharePoint выбрасывает исключение нулевой ссылки
В нашем проекте SharePoint 2010 мы используем Linq to SharePoint, чтобы получить список ConfigurationItems. В наших средах тестирования у нас никогда не было проблем с получением данных из этого списка. В нашей производственной среде мы теперь иногда (мы не можем найти шаблон прямо сейчас) получаем исключение нулевой ссылки при циклическом просмотре элементов в списке.
Ниже приведено исключение из кода Linq to SharePoint:
В экземпляре объекта не задана ссылка на объект. StackTrace: в Microsoft.SharePoint.Linq.FieldRef.GetHashCode() в Microsoft.SharePoint.Linq.FieldRef.FieldRefEqualityComparer.GetHashCode(FieldRef obj) в System.Linq.Set`1.InternalGetHashCode(значение элемента TEL) в System.Lement. `1.Find(значение TElement, логическое добавление) в System.Linq.Enumerable.d__7a`1.MoveNext() в System.Linq.Buffer`1..ctor(источник IEnumerable`1) в System.Linq.Enumerable.ToArray[TSource](источник IEnumerable`1) в Microsoft.SharePoint.Linq.SelectMappingInfo.GetDistinctMappedFields() в Microsoft.SharePoint.Linq.Rules.PushDownProcessor.SelectWithInfoOp.PushDownSelect(Context ctx) в Microsoft.SushDL.L.SelectWithInfoOp.Process(Context ctx) в Microsoft.SharePoint.Linq.Rules.GuardedRule`4.c__DisplayClass7.b__6(TSourceBase src, TContext ctx) в Microsoft.SharePoint.Linq.Rules.RewriteRule`2.Apply, TNT) в Microsoft.SharePoint.Linq.Rules.CacheRule`3.Apply(TSource src, TContext ctx) в Microsoft.SharePoint.Linq.Rules.PushDownProcessor.b__0(выражение e, контекст ctx) в Microsoft.SharePoint.Linq.Rules.ChildRule`2.Apply(TNode src, TContext ctx) в Microsoft.SharePoint.Linq.Rules.PushDownProcessor.b__3(выражение e, Context ctx) в Microsoft.SharePoint.Linq.Rules.RewriteRule`2.Apply(TNode src, TContext ctx) в Microsoft.SharePoint.Linq.Rules.CacheRule`3.Apply(TSource src, TContext ctx) в Microsoft.SharePoint.Linq.SPLinP.Rewrite(Выражение выражения, List`1& предположения) в Microsoft.SharePoint.Linq.SPLinqProvider.RewriteAndCompile[T](Выражение выражения, List`1& предположения) в Microsoft.SharePoint.Linq.LinqQuery`1.GetEnumerator() в системе.Collections.Generic.List`1..ctor(коллекция IEnumerable`1) в System.Linq.Enumerable.ToList[TSource](источник IEnumerable`1) в Common.Configuration.ConfigurationRepository.GetConfiguration(String siteUrl) InnerException: Источник: Microsoft.SharePoint.Linq TargetSite: Int32 GetHashCode()
И вот код, который мы используем в нашем методе GetConfiguration.
using (SpDataContext dataContext = new SpDataContext(siteUrl))
{
result = new ConfigurationModel()
{
Configurations = (from item in dataContext.GasportConfiguration
select new ConfigurationItem()
{
Key = item.Key,
Value = item.Value,
Environment = (Environment)Enum.Parse(typeof(Environment), item.Environment.ToString(), true)
}).ToList()
};
}
У кого-нибудь есть идеи о том, как отследить это до причины этого исключения?
ОБНОВЛЕНИЕ 31-05-2011:
Мы нашли образец, каким образом мы можем воспроизвести это поведение в нашей производственной среде. А также в нашей тестовой среде у нас тоже была эта проблема, из которой мы извлекли некоторые файлы Crash Dump с помощью AdPlus.
Мы видим, что такое поведение происходит после повторного использования пула приложений. Единственный способ исправить эту ошибку - выполнить полный сброс IIS.
В анализе сбоя я обнаружил сообщение об исключении, которое гласит: Код исключения: 0xC0000005 Информация об исключении: Поток пытается прочитать или записать виртуальный адрес, к которому у него нет соответствующего доступа.
Надеюсь, что кто-то может дать мне больше информации об этом исключении?
3 ответа
К сожалению, мы не нашли решения этой проблемы и решили перейти от LINQ к SharePoint. Для нескольких списков мы изменили его на таблицы SQL (Linq to SQL), а для списков SharePoint мы вернулись к CAML.
В нашем проекте мы активно используем Linq для Sharepoint, и эта проблема периодически возникала, и только на производстве. Единственная вещь, которая, казалось, работала, когда это произошло, была IISReset.
Мы углубились в проблему и до сих пор не знаем, что ее вызывает. Но мы обнаружили, что вы можете автоматически исправить это при очистке некоторых переменных частного кэша. Вот наш код:
public static class SharePointless
{
public static void Reset()
{
var assembly = Assembly.GetAssembly(typeof(EntityList<>));
var providerType = assembly.GetType("Microsoft.SharePoint.Linq.SPLinqProvider");
var singleton = providerType.GetField("Singleton", BindingFlags.Static | BindingFlags.Public);
if (singleton == null) throw new Exception("Expected field doesn't exist in SPLinqProvider");
singleton.SetValue(null, Activator.CreateInstance(providerType));
var itemMappingInfoType = assembly.GetType("Microsoft.SharePoint.Linq.SPItemMappingInfo");
var cachedMappings = itemMappingInfoType.GetField("cachedMappings", BindingFlags.Static | BindingFlags.NonPublic);
if (cachedMappings == null) throw new Exception("Expected field doesn't exist in SPItemMappingInfo");
cachedMappings.SetValue(null, null);
}
}
Пример использования:
public static void MyMethod(bool retry)
{
try
{
using (var db = new MyDataContext())
{
DoStuff(db);
}
}
catch (NullReferenceException ex)
{
if (retry && ex.StackTrace.Contains("FieldRef.GetHashCode"))
{
SharePointless.Reset();
MyMethod(false);
}
}
}
В нашем случае мы также получили код пересылки, отправив нам электронное письмо, чтобы мы знали, что проблема возникла и исправление сработало.
Мы столкнулись с тем же. Следующие шаги решили это:
- Восстановление класса dataContext через SPMetal на сервере, вызывающее проблему
- Повторно примените класс к своему проекту и пересоберите
- Повторно разверните решение (копирование DLL в GAC сработало)