Linq to SharePoint 抛出空引用异常。

5
在我们的SharePoint 2010项目中,我们使用Linq to SharePoint获取ConfigurationItems列表。在我们的测试环境中,从这个列表中获取数据从未出现过问题。但是在我们的生产环境中,当循环遍历列表中的项时,有时会出现空引用异常(我们目前无法找到规律)。
以下是我们从Linq to SharePoint代码中抛出的异常:
Object reference not set to an instance of an object. StackTrace: at Microsoft.SharePoint.Linq.FieldRef.GetHashCode() at Microsoft.SharePoint.Linq.FieldRef.FieldRefEqualityComparer.GetHashCode(FieldRef obj) at System.Linq.Set`1.InternalGetHashCode(TElement value) at System.Linq.Set`1.Find(TElement value, Boolean add) at System.Linq.Enumerable.d__7a`1.MoveNext() at System.Linq.Buffer`1..ctor(IEnumerable`1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) at Microsoft.SharePoint.Linq.SelectMappingInfo.GetDistinctMappedFields() at Microsoft.SharePoint.Linq.Rules.PushDownProcessor.SelectWithInfoOp.PushDownSelect(Context ctx) at Microsoft.SharePoint.Linq.Rules.PushDownProcessor.SelectWithInfoOp.Process(Context ctx) at Microsoft.SharePoint.Linq.Rules.GuardedRule`4.c__DisplayClass7.b__6(TSourceBase src, TContext ctx) at Microsoft.SharePoint.Linq.Rules.RewriteRule`2.Apply(TNode src, TContext ctx) at Microsoft.SharePoint.Linq.Rules.CacheRule`3.Apply(TSource src, TContext ctx) at Microsoft.SharePoint.Linq.Rules.PushDownProcessor.b__0(Expression e, Context ctx) at Microsoft.SharePoint.Linq.Rules.ChildRule`2.Apply(TNode src, TContext ctx) at Microsoft.SharePoint.Linq.Rules.PushDownProcessor.b__3(Expression e, Context ctx) at Microsoft.SharePoint.Linq.Rules.RewriteRule`2.Apply(TNode src, TContext ctx) at Microsoft.SharePoint.Linq.Rules.CacheRule`3.Apply(TSource src, TContext ctx) at Microsoft.SharePoint.Linq.SPLinqProvider.Rewrite(Expression expression, List`1& assumptions) at Microsoft.SharePoint.Linq.SPLinqProvider.RewriteAndCompile[T](Expression expression, List`1& assumptions) at Microsoft.SharePoint.Linq.LinqQuery`1.GetEnumerator() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at 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()
    };
}

有没有人有想法如何跟踪这个异常的原因?

更新于2011年5月31日:

我们在生产环境中找到了一种可以重现此行为的模式。并且在我们的测试环境中也遇到了这个问题,通过使用AdPlus提取了一些崩溃转储文件。

我们发现这种行为发生在应用程序池被回收后。唯一修复此错误的方法是执行完整的IISreset。

在崩溃转储分析中,我发现一个异常消息,指出: 异常代码:0xC0000005 异常信息:线程尝试读取或写入其没有适当访问权限的虚拟地址。

希望有人能给我更多关于此异常的信息?


你在这里解决了这个问题吗?我们也遇到了同样的事情。 - billfredtom
不,我们没有解决我们的问题。奇怪的是,只有一个前端出现了这个问题。另一个运行得非常完美。我们发现了一些关于如何重现此问题的更多信息。问题在应用程序池回收后开始出现。 - ChristiaanV
我遇到了一些随机问题,其中上下文没有完全重新加载,只有部分不可用。这也是在应用程序重置后而没有进行IIS重置的情况下发生的。由于这个问题,我们没有花费任何时间重新编译,而是在出现这种情况时执行IIS重置来解决问题。不确定这是否有帮助。我们目前使用的所有版本以及大多数热修复都是最新的。 - brian brinley
这是我们目前的解决方法。虽然我对这个解决方法并不满意。执行应用程序池回收将会对用户造成较少的不可用性。 - ChristiaanV
1
还有一件值得注意的事情 - 我们在重置运行应用程序池的用户帐户密码后遇到了问题。使用Set-SPManagedAccount PowerShell命令更新帐户可能已经解决了我们的问题 - 目前为止没有再次发生。 - billfredtom
3个回答

2

很遗憾,我们没有找到这个问题的解决方案,并决定放弃使用LINQ to SharePoint。对于一些列表,我们已将其更改为SQL表(Linq to SQL),而对于SharePoint列表,我们则回到了CAML。


1
在我们的项目中,我们大量使用Linq to 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);
        }
    }
}

在我们的情况下,我们还让捕获代码发送电子邮件给我们,这样我们就知道了问题发生的情况以及修复是否奏效。

0
我们遇到了同样的问题。以下步骤解决了它:
  • 通过服务器上的 SPMetal 重新生成 dataContext 类,导致了问题
  • 将类重新应用到您的项目并重新构建
  • 重新部署解决方案(将 DLL 复制到 GAC 中可行)

你有能力比较在开发环境中生成的数据上下文和导致问题的服务器上的数据上下文吗?我认为两个服务器上的上下文之间不应该有任何区别。 - ChristiaanV
我们比较了生成的两个文件 - 发现微小的差异 - 版本号在顶部注释中稍有不同,并且添加了一些行。 - billfredtom
好的,但如果我听到你说的话,那么就没有真正的差异可以导致这种行为发生。我将查看我们的生产环境上是否有spmetal实例,并生成数据上下文以便比较它们。导致错误开始的列表中是否有查找字段? - ChristiaanV
是的,列表中有查找字段。上述步骤似乎已经解决了问题 - 但仅过去一天,所以不确定是否会再次发生,特别是如果它与spmetal无关并且更多是应用程序池问题。 - billfredtom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接