AssertionFailure - collection was processed twice by flush() causes Orchard CMS site to crash - nhibernate

I am running Orchard CMS 1.7.2. I created a custom module called BYUtv.Shapes as a place to store reusable shape methods. I have a class called RelatedToShow : IDependency in this module. The method of interest in this class is called RelatedEpisodes. The purpose of this shape method is to retrieve Episodes data, via a query created in the admin ui, for Episodes related to a specific Show. In the manager the Episode content type definition has a Content Picker Field that allows a content manager to pick a Show that the Episode is part of or related to. The query that I created is working correctly and returning the correct data. With that explanation here is my shape method.
[Shape]
public IHtmlString RelatedEpisodes(dynamic Shape, dynamic Display, int? PageSize, string PagerSuffix = "")
{
// Retrieves the QueryPart by name for the query called Related Episodes Year.
// Related Episodes Year retrieves Episodes that are related to a specific show with an optional year filter.
QueryPart episodesQuery = GetQueryPartByName("Related Episodes Year");
dynamic pager = CreatePager(Shape, _projectionManager.GetCount(episodesQuery.Id), PageSize, PagerSuffix);
int startIndex = pager.Pager.GetStartIndex();
int pageSize = pager.Pager.PageSize;
IEnumerable<ContentItem> contentItems = new List<ContentItem>();
if(episodesQuery != null)
{
contentItems = _projectionManager.GetContentItems(episodesQuery.Id, startIndex, pageSize);
}
// Retrieves the QueryPart by name for the query called Related Episodes.
// Related Episodes retrieves Episodes that are related to a specific show.
QueryPart newestEpisodeQuery = GetQueryPartByName("Related Episodes");
ContentItem newestEpisode = null;
if (newestEpisodeQuery != null)
{
newestEpisode = _projectionManager.GetContentItems(newestEpisodeQuery.Id, 0, 1).FirstOrDefault();
}
// Retrieves a list of distinct years that the episodes premiered in.
List<string> years = _projectionManager.GetContentItems(newestEpisodeQuery.Id).Select(y => (string)((dynamic)y).TimeSpanPart.StartDateTime.Year.ToString()).Distinct().ToList();
return Display.RelatedEpisodesView(ContentItems: contentItems, Pager: pager, NewestEpisode: newestEpisode, YearFilter: GetYearFilter(), Years: years);
}
In all my testing this always works locally. It also works in production but seemingly randomly crashes the page it is used on in production. If I comment the code that runs this shape method in production than the rest of the page runs as desired. The only difference that I am aware of between production and local is possibly the HostCompontents.config file and the traffic volume. In production I turn off several properties because I understand it will help performance.
Here are the logs from the production server.
Exception information:
Exception type: AssertionFailure
Exception message: collection was processed twice by flush()
at NHibernate.Engine.Collections.PrepareCollectionForUpdate(IPersistentCollection collection, CollectionEntry entry, EntityMode entityMode, ISessionFactoryImplementor factory) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Engine\Collections.cs:line 164
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushCollections(IEventSource session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 92
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 61
at NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\DefaultAutoFlushEventListener.cs:line 32
at NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1180
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 616
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 593
at NHibernate.Impl.QueryImpl.List() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\QueryImpl.cs:line 64
at NHibernate.Impl.AbstractQueryImpl.UniqueResult() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\AbstractQueryImpl.cs:line 960
at Orchard.ContentManagement.DefaultHqlQuery.Count() in c:\Source\BYUB\byuradio2\orchard\src\Orchard\ContentManagement\DefaultHqlQuery.cs:line 212
at Orchard.Projections.Services.ProjectionManager.<GetCount>b__14(IHqlQuery contentQuery)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at Orchard.Projections.Services.ProjectionManager.GetCount(Int32 queryId)
at BYUtv.Shapes.Drivers.RelatedToShow.RelatedEpisodes(Object Shape, Object Display, Nullable`1 PageSize, String PagerSuffix)
and
Stack trace: at NHibernate.Engine.Collections.PrepareCollectionForUpdate(IPersistentCollection collection, CollectionEntry entry, EntityMode entityMode, ISessionFactoryImplementor factory) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Engine\Collections.cs:line 164
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushCollections(IEventSource session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 92
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 61
at NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\DefaultAutoFlushEventListener.cs:line 32
at NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1180
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 616
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 593
at NHibernate.Impl.QueryImpl.List() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\QueryImpl.cs:line 64
at NHibernate.Impl.AbstractQueryImpl.UniqueResult() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\AbstractQueryImpl.cs:line 960
at Orchard.ContentManagement.DefaultHqlQuery.Count() in c:\Source\BYUB\byuradio2\orchard\src\Orchard\ContentManagement\DefaultHqlQuery.cs:line 212
at Orchard.Projections.Services.ProjectionManager.<GetCount>b__14(IHqlQuery contentQuery)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at Orchard.Projections.Services.ProjectionManager.GetCount(Int32 queryId)
at BYUtv.Shapes.Drivers.RelatedToShow.RelatedEpisodes(Object Shape, Object Display, Nullable`1 PageSize, String PagerSuffix)
The error seems to always relate to collection was processed twice by flush(). I have even tried creating the query directly in the code with similar results.
Another question that was posted is Orchard cms 1.7.2 GenericADOException. Some of the side effects expressed there are similar to what I am having.
Are there any glaring issues that you can see in this code that are causing these errors?
Have you run into this or similar issues?
Any thoughts on how to resolve this problem?

Related

Json Errors in raven 3.5 client

Periodically we receive the following error when saving to a Raven Database. The client and database are v3.5. The solution thus far has been to restart the servers and after that things appear to settle down. The user can go to a different server and can go back into the site and retrieved what was saved. However when we see 1 error like this on a server the server starts to report 100's of them. We cannot reproduce this in QA. So I am leaning towards load or our Raven Sessions are not being closed properly.
Calling the Raven OpenSessionAsync() as the point of creating the class
IAsyncDocumentSession
public async Task<bool> SaveChangesAsync()
{
using (_session)
{
await _session.SaveChangesAsync();
}
return true;
}
This is the area in our code that starts the error when saving should we also be doing something more?
Message: Token PropertyName in state Property would result in an invalid JSON object. Path ''.
Raven.Imports.Newtonsoft.Json.JsonWriter.AutoComplete(JsonToken tokenBeingWritten) in C:\Builds\RavenDB-Stable-3.5\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\JsonWriter.cs:779
Raven.Json.Linq.RavenJTokenWriter.WritePropertyName(String name) in C:\Builds\RavenDB-Stable-3.5\Raven.Abstractions\Json\Linq\RavenJTokenWriter.cs:51
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) in C:\Builds\RavenDB-Stable-3.5\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:428
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in C:\Builds\RavenDB-Stable-3.5\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:101
Raven.Imports.Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) in C:\Builds\RavenDB-Stable-3.5\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:949
Raven.Json.Linq.RavenJToken.FromObjectInternal(Object o, JsonSerializer jsonSerializer) in C:\Builds\RavenDB-Stable-3.5\Raven.Abstractions\Json\Linq\RavenJToken.cs:91
Raven.Json.Linq.RavenJObject.FromObject(Object o, JsonSerializer jsonSerializer) in C:\Builds\RavenDB-Stable-3.5\Raven.Abstractions\Json\Linq\RavenJObject.cs:174
Raven.Client.Document.EntityToJson.GetObjectAsJson(Object entity) in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\EntityToJson.cs:72
Raven.Client.Document.EntityToJson.ConvertEntityToJson(String key, Object entity, RavenJObject metadata) in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\EntityToJson.cs:44
Raven.Client.Document.InMemoryDocumentSessionOperations.EntityChanged(Object entity, DocumentMetadata documentMetadata, IDictionary2 changes) in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:1218
Raven.Client.Document.InMemoryDocumentSessionOperations.<PrepareForEntitiesPuts>b__110_0(KeyValuePair2 pair) in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:1025
System.Linq.Enumerable+WhereEnumerableIterator1.MoveNext():55
System.Linq.Buffer1..ctor(IEnumerable1 source):114
System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source):20
Raven.Client.Document.InMemoryDocumentSessionOperations.PrepareForEntitiesPuts(SaveChangesData result) in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:1025
Raven.Client.Document.InMemoryDocumentSessionOperations.PrepareForSaveChanges() in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:986
Raven.Client.Document.Async.AsyncDocumentSession+d__73.MoveNext() in C:\Builds\RavenDB-Stable-3.5\Raven.Client.Lightweight\Document\Async\AsyncDocumentSession.cs:928
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw():12
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task):46
ApplicantCenter.Services.ApplicationService+d__9.MoveNext() in d:\a\1\s\Project\Services\ApplicationService_Helpers.cs:207
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw():12
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task):46
ApplicantCenter.Controllers.ApplicationController+d__10.MoveNext() in d:\a\1\s\Project\Controllers\ApplicationController.cs:117
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw():12
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task):46
System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)
System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass8_0.b__1(IAsyncResult asyncResult)
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters.b__11_0():19
System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters+<>c__DisplayClass11_1.b__2():134
System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters+<>c__DisplayClass11_1.b__2():134
System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters+<>c__DisplayClass11_1.b__2():134
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass3_6.b__3()
System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass3_1.b__5(IAsyncResult asyncResult)
The problem here is that you are disposing the session that maybe used by others.
You put a global _session inside an using block, the _session resources will be disposed after the using block end, and other parts of code that are using the same global _session will become invalid.

Nhibernate queries fail itermitently

I'm having a really hard time nailing down a problem coming from NHibernate (3.3). The application serves some 150 req/s in a six node NLB cluster. The application behaves ok generally, but sometimes maybe 1-2 day the following error comes in the logs and all queries fail.
I'm using adonet.batch_size of 15 and MultipleActiveResultSets=True is set to true. All controllers inherit from AsyncController (this is an ASP.NET MVC 4 app), so session state is read only to maximize concurrency.
Initially, we had a lot of trouble NHibernate Session handling because the AbstractBatcher did a pretty poor job managing which readers were related to which connection. So, in a high load, readers would try to read from connections that were already closed. We solved this by defining manually the lifetime of a SQLConnection which stabilized things.
However, the following comes up often. I think it is a symptom of something really wrong with the session factory. At this point, I'm thinking about reinitializing the session factory when an unhandled exception of this type is thrown, but that's not nice. Does anyone have any insight to why this happens?
System.NotSupportedException: PartialEvaluationExceptionExpression
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root)
at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
For those who may be facing this issue, I thought I'd give some insight of two years in production (thousands of users) of a fix that we put in place to address this issue.
In the base constructor we have something like this:
public MvcBaseController()
{
try
{
var currentRepositorySession = RepositorySession.Current;
dbConnection = new SqlConnection(currentRepositorySession.GetConnectionString());
dbConnection.Open();
session = currentRepositorySession.Create(false, dbConnection);
}
catch (Exception e)
{
LogDebug("Error was thrown: " + e.Message);
}
}
Binding the db connection to the NHibernate session forcefully is the only way to ensure that the AbstractBatcher doesn't close the session before all readers are done. On Dispose we have the following:
protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
if (session != null)
{
session.Dispose();
session = null;
}
}
catch (Exception ex)
{
LogDebug("Error was thrown: " + ex.Message);
}
try
{
if (dbConnection != null)
{
dbConnection.Close();
dbConnection.Dispose();
dbConnection = null;
}
}
catch (Exception ex)
{
LogDebug("Error was thrown: " + ex.Message);
}
}
base.Dispose(disposing);
}
This means that a connection is opened for every requests, which is fine. We had to increase SQL Server workers, but the system has been stable for two years now. The only time we've seen NHibernate session factory break is when there is a lot of data paged from the database, say 1 million records. Then the application pool overflows, and is orphaned. These were mostly code bugs and not related to the concurrency issues described in the question.

Sitecore 7 ContentSearch crawling failure: "Crawler : AddRecursive DoItemAdd failed"

When we try to rebuild our Lucene (ContentSearch) indexes, our CrawlingLog is filled up with these exceptions:
7052 15:08:21 WARN Crawler : AddRecursive DoItemAdd failed - {5A1E50E4-46B9-42D5-B743-1ED10D15D47E}
Exception: System.AggregateException
Message: One or more errors occurred.
Source: mscorlib
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body)
at Sitecore.ContentSearch.AbstractDocumentBuilder`1.AddItemFields()
at Sitecore.ContentSearch.LuceneProvider.CrawlerLuceneIndexOperations.GetIndexData(IIndexable indexable, IProviderUpdateContext context)
at Sitecore.ContentSearch.LuceneProvider.CrawlerLuceneIndexOperations.BuildDataToIndex(IProviderUpdateContext context, IIndexable version)
at Sitecore.ContentSearch.LuceneProvider.CrawlerLuceneIndexOperations.Add(IIndexable indexable, IProviderUpdateContext context, ProviderIndexConfiguration indexConfiguration)
at Sitecore.ContentSearch.SitecoreItemCrawler.DoAdd(IProviderUpdateContext context, SitecoreIndexableItem indexable)
at Sitecore.ContentSearch.HierarchicalDataCrawler`1.CrawlItem(Tuple`3 tuple)
Nested Exception
Exception: System.ArgumentOutOfRangeException
Message: Index and length must refer to a location within the string.
Parameter name: length
Source: mscorlib
at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
at Sitecore.Data.ShortID.Encode(String guid)
at Sitecore.ContentSearch.FieldReaders.MultiListFieldReader.GetFieldValue(IIndexableDataField indexableField)
at Sitecore.ContentSearch.FieldReaders.FieldReaderMap.GetFieldValue(IIndexableDataField field)
at Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilder.AddField(IIndexableDataField field)
at System.Threading.Tasks.Parallel.<>c__DisplayClass32`2.<PartitionerForEachWorker>b__30()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass11.<ExecuteSelfReplicating>b__10(Object param0)
This appears to be caused by the ShortID.Encode(string) method expecting the GUID in the string parameter to have brackets (" { " and " } ") around it. Some of our multilist field relationships were associated programmatically using Guid.ToString(), which does not include the brackets. Unfortunately, these values cause the ShortID.Encode() method to choke.
First things first: find all the places you call MultiListField.Add(string) and change Guid.ToString() to Guid.ToString("B"). This will resolve the issue for all new relationships.
Create a custom FieldReader class to replace the standard MultiListFieldReader (we called ours CustomMultiListFieldReader).
Set your custom class to inherit from Sitecore.ContentSearch.FieldReaders.FieldReader.
Decompile the Sitecore.ContentSearch.FieldReaders.MultiListFieldReader.GetFieldValue(IIndexableDataField) method into your custom class.
Before the if (ID.IsID(id)) line, add the following code:
if (!str.StartsWith("{") && !str.EndsWith("}"))
id = String.Format("{{{0}}}", str);
In your index configuration (we added ours to the default, Sitecore.ContentSearch.DefaultIndexConfiguration.config) change the fieldReaderType for the MultiList fields to your custom type. (This can be found in your config at sitecore/contentSearch/configuration/defaultIndexConfiguration/fieldReaders/mapFieldByTypeName/fieldReader.)
Full disclosure: I don't love this approach because if the default implementation of the MultiListFieldReader ever changed, we'd be without those changes. But this allows the items to be included in the index without reformatting all of the GUIDs in every multilist field.

How do I read this stack trace I'm only getting from scrapers?

The following is the stack trace error I get when I try to run my site through a validator like http://validator.w3.org/ or the facebook open graph debugger. The thing is, the page appears to load just fine in the browser, or in the mobile app web view. The only way I can see this error is by having the validator show me error pages (option). Any suggestions about how to read the stack trace? I see the reference to one of my controllers Literrater.Controllers.BookController.Index(Int32 id, String slug) but I havent changed anything and it used to work, and it works fine in the browser. So, I'm confused. Do I need to check redirect happening or something?
The follow page has the problem. http://literrater.azurewebsites.net/book/33625/birdsong-a-novel-of-love-and-war
[RuntimeBinderException: Cannot convert null to 'bool' because it is a non-nullable value type]
CallSite.Target(Closure , CallSite , Object ) +115
System.Dynamic.UpdateDelegates.UpdateAndExecute1(CallSite site, T0 arg0) +661
Literrater.Controllers.BookController.Index(Int32 id, String slug) +13725
lambda_method(Closure , ControllerBase , Object[] ) +146
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +182
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +28
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +58
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +225
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +225
At this moment, your page is not loading and producing the error:
Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot convert null to 'bool' because it is a non-nullable value type
Source Error:
Line 32: <div class="status-wrapper">
Line 33: <h2 class="sub-title">Collections</h2>
Line 34: #{Model.CollectionVM.FacebookStatus = ViewBag.FacebookStatus;}
Line 35: #Html.Partial("_MiniBookStatus", Model.CollectionVM)
Line 36:
Source File: d:\home\site\wwwroot\Views\Book\Index.cshtml Line: 34
It looks like maybe you did not initialize the ViewBag.FacebookStatus value in your controller. With those ViewBag values, if you don't set the value in all code paths, then you may have a case like this where the it's null.
As an example:
protected ActionResult Test()
{
ViewBag.SomeString = string.Empty;
ViewBag.SomeBool = false;
//some code
if (condition)
{
ViewBag.SomeBool = true;
}
else
{
ViewBag.SomeString = "Yea I'm a string!";
}
return View();
}
It's good practice to init the ViewBag values or it can come back to bite you in the Razor view because Intellisense won't pick it up, and it won't cause a build error or warning.

NHibernate Validator throws System.NotSupportedException after upgrading to 3.1

Has anyone encountered this?
After upgrading to NHibernate 3.1, I am receiving the following exception from NHibernate Validator when running NUnit test cases:
System.NotSupportedException : The invoked member is not supported in
a dynamic assembly. at
System.Reflection.Emit.InternalAssemblyBuilder.GetManifestResourceStream(String
name) at
NHibernate.Validator.Cfg.XmlMappingLoader.AddResource(Assembly
assembly, String resource) at
NHibernate.Validator.Cfg.XmlMappingLoader.GetXmlMappingFor(Type type)
at
NHibernate.Validator.Engine.JITClassMappingFactory.GetExternalDefinitionFor(Type
type) at
NHibernate.Validator.Engine.JITClassMappingFactory.GetClassMapping(Type
clazz, ValidatorMode mode) at
NHibernate.Validator.Engine.ClassValidator.InitValidator(Type clazz,
IDictionary`2 nestedClassValidators) at
NHibernate.Validator.Engine.ClassValidator..ctor(Type clazz,
IConstraintValidatorFactory constraintValidatorFactory, IDictionary`2
childClassValidators, IClassValidatorFactory factory) at
NHibernate.Validator.Engine.StateFullClassValidatorFactory.GetRootValidator(Type
type) at
NHibernate.Validator.Engine.ValidatorEngine.GetClassValidator(Type
entityType) at
NHibernate.Validator.Engine.ValidatorEngine.GetElementOrNew(Type
entityType) at
NHibernate.Validator.Engine.ValidatorEngine.InternalValidate(Object
entity, Object[] activeTags) at
NHibernate.Validator.Engine.ValidatorEngine.Validate(Object entity,
Object[] activeTags) at
NHibernate.Validator.Event.ValidateEventListener.Validate(Object
entity, EntityMode mode) at
NHibernate.Validator.Event.ValidatePreUpdateEventListener.OnPreUpdate(PreUpdateEvent
event) at NHibernate.Action.EntityUpdateAction.PreUpdate() in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Action\EntityUpdateAction.cs:
line 200 at NHibernate.Action.EntityUpdateAction.Execute() in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Action\EntityUpdateAction.cs:
line 58 at NHibernate.Engine.ActionQueue.Execute(IExecutable
executable) in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line
136 at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line
126 at NHibernate.Engine.ActionQueue.ExecuteActions() in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line
170 at
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource
session) in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:
line 241 at
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent
event) in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs:
line 19 at NHibernate.Impl.SessionImpl.Flush() in
d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs: line
1472 at TestDataAccess.FooTest.TestFoo() in FooTest.cs
As you can see from the stack trace, the error occurs when the session is flushed and NHibernate Validator does its thing.
Update I have tried stepping through the NH Validator code and it appears that at some point it is trying to validate the Castle proxy of an entity, rather than the underlying entity itself. This then causes the trouble. No idea what to do about this...
Update The problem goes away if I use the LinFu ProxyFactoryFactory, rather than Castle. Unfortunately, LinFu is giving me other problems so I don't want to use it.
NHibernate 3.2 removed the need for external proxy libraries.
They are still supported, but they are not distributed anymore, and the default is to use an internal implementation.
Have you tried upgrading?
Update: in order to compile NHibernate Validator for NH 3.2, you need to modify NHibernateHelper as follows:
public static bool IsProxyFactoryConfigurated()
{
var f = NHibernate.Cfg.Environment.BytecodeProvider.ProxyFactoryFactory;
return f != null;
}
For details, read NHV-116