Sitecore 如何解决 Sitecore 搜索中 Invalid cast from 'System.String' to 'Sitecore.Data.ID' 的错误

Sitecore How to solve the error Invalid cast from 'System.String' to 'Sitecore.Data.ID' in Sitecore Search

我正在使用 sitecore 搜索 API,但出现异常 'Exception Details: System.InvalidCastException: Invalid cast from 'System.String' to 'Sitecore.Data.ID'.' 在这一行:foreach (var result in query)。我正在使用以下代码:

using (var context = ContentSearchManager.GetIndex("my_text_index").CreateSearchContext())
{
IQueryable<Person> query = context.GetQueryable<Person>().Where(p=> p.Firstname.Equals("John"));

foreach(result in query) // I am getting the exception here on this line.
{
  lbltest.Text = result.Name;
}

}

这是class“Person

public class Person : SearchResultItem
{
    [IndexField("firstname_t")]
    public string Firstname { get; set; }
    [IndexField("surname_t")]
    public string Surname { get; set; }
}

这是堆栈跟踪:

[InvalidCastException: Invalid cast from 'System.String' to 'Sitecore.Data.ID'.]
   System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) +14116726
   System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +14116814
   Sitecore.ContentSearch.Converters.IndexFieldStorageValueFormatter.ReadFromIndexStorage(Object indexValue, Type destinationType) +609

[InvalidCastException: Could not convert value of type System.String to destination type Sitecore.Data.ID: Invalid cast from 'System.String' to 'Sitecore.Data.ID'.]
   Sitecore.ContentSearch.Converters.IndexFieldStorageValueFormatter.ReadFromIndexStorage(Object indexValue, Type destinationType) +869
   Sitecore.ContentSearch.DocumentTypeMapInfo.SetProperty(Object target, String propertyName, String documentFieldName, Object value) +172

[InvalidCastException: Could not map index document field to property "ItemId" on type Starco.ISK.Website.Search.PersonSearchItem : Could not convert value of type System.String to destination type Sitecore.Data.ID: Invalid cast from 'System.String' to 'Sitecore.Data.ID'.]
   Sitecore.ContentSearch.DocumentTypeMapInfo.SetProperty(Object target, String propertyName, String documentFieldName, Object value) +360
   Sitecore.ContentSearch.DefaultDocumentMapper`1.MapFieldValuesToType(IDictionary`2 fieldValues, TElement result, DocumentTypeMapInfo documentTypeMapInfo) +792
   Sitecore.ContentSearch.LuceneProvider.DefaultLuceneDocumentTypeMapper.ReadDocumentFields(Document document, IEnumerable`1 fieldNames, DocumentTypeMapInfo documentTypeMapInfo, IEnumerable`1 virtualFieldProcessors, TElement result) +1249
   Sitecore.ContentSearch.DefaultDocumentMapper`1.MapToType(TDocument document, SelectMethod selectMethod, IEnumerable`1 virtualFieldProcessors, SearchSecurityOptions securityOptions) +283
   Sitecore.ContentSearch.LuceneProvider.<GetSearchResults>d__8.MoveNext() +1577
   Starco.ISK.Website.Search.Output.Page_Load(Object sender, EventArgs e) in e:\IIS Data\Starco_intra.starco.com\Website\Search\Output.ascx.cs:76
   System.Web.UI.Control.LoadRecursive() +71
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Control.LoadRecursive() +190
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3178

索引的配置文件:

 <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <contentSearch>
      <configuration type="Sitecore.ContentSearch.LuceneProvider.LuceneSearchConfiguration, Sitecore.ContentSearch.LuceneProvider">
        <indexes hint="list:AddIndex"> 
          <index id="my_text_Index" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
            <param desc="name">$(id)</param>
            <param desc="folder">$(id)</param>
            <param desc="propertyStore" ref="contentSearch/databasePropertyStore" param1="$(id)" />
            <Configuration ref="profileSearch/configuration" />
            <strategies hint="list:AddStrategy">
              <strategy ref="contentSearch/indexUpdateStrategies/onPublishEndAsync" />
            </strategies>
            <commitPolicyExecutor type="Sitecore.ContentSearch.CommitPolicyExecutor, Sitecore.ContentSearch">
              <policies hint="list:AddCommitPolicy">
                <policy type="Sitecore.ContentSearch.TimeIntervalCommitPolicy, Sitecore.ContentSearch" />
              </policies>
            </commitPolicyExecutor>
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
                <Database>master</Database>
                <Root>/sitecore/content/Intranet</Root> 
              </crawler>
            </locations>
          </index>
        </indexes>
      </configuration>
    </contentSearch>
  </sitecore>
</configuration>

以下是showconfig.aspx页面sitecore/admin/showconfig.aspx :

<indexFieldStorageValueFormatter type="Sitecore.ContentSearch.LuceneProvider.Converters.LuceneIndexFieldStorageValueFormatter, Sitecore.ContentSearch.LuceneProvider">
<converters hint="raw:AddConverter">
<converter handlesType="System.Guid" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldGuidValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.Data.ID, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldIDValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.Data.ShortID, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldShortIDValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="System.Boolean" typeConverter="Sitecore.ContentSearch.LuceneProvider.Converters.IndexFieldBooleanValueConverter, Sitecore.ContentSearch.LuceneProvider"/>
<converter handlesType="System.DateTime" typeConverter="Sitecore.ContentSearch.LuceneProvider.Converters.IndexFieldDateTimeValueConverter, Sitecore.ContentSearch.LuceneProvider"/>
<converter handlesType="System.DateTimeOffset" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldDateTimeOffsetValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="System.TimeSpan" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldTimeSpanValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.ContentSearch.SitecoreItemId, Sitecore.ContentSearch" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldSitecoreItemIDValueConvertor, Sitecore.ContentSearch">
<param type="Sitecore.ContentSearch.Converters.IndexFieldIDValueConverter, Sitecore.ContentSearch"/>
</converter>
<converter handlesType="Sitecore.ContentSearch.SitecoreItemUniqueId, Sitecore.ContentSearch" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldSitecoreItemUniqueIDValueConverter, Sitecore.ContentSearch">
<param type="Sitecore.ContentSearch.Converters.IndexFieldItemUriValueConverter, Sitecore.ContentSearch"/>
</converter>
<converter handlesType="Sitecore.Data.ItemUri, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldItemUriValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.Globalization.Language, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldLanguageValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="System.Globalization.CultureInfo" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldCultureInfoValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.Data.Version, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldVersionValueConverter, Sitecore.ContentSearch"/>
<converter handlesType="Sitecore.Data.Database, Sitecore.Kernel" typeConverter="Sitecore.ContentSearch.Converters.IndexFieldDatabaseValueConverter, Sitecore.ContentSearch"/>
</converters>
</indexFieldStorageValueFormatter>

通常这意味着您的 属性 缺少转换属性。但是 none 其中有 Id 的。

看来您的 IndexField 属性设置不正确。您不需要在末尾添加类型后缀。 Sitecore API 会为您做到这一点。

因此将 Person class 更改为:

public class Person : SearchResultItem
{
    [IndexField("firstname")]
    public string Firstname { get; set; }
    [IndexField("surname")]
    public string Surname { get; set; }
}

还要确保这些字段不是 CMS 中的 ID 字段。

尝试更新如下:

using (var context = ContentSearchManager.GetIndex("my_text_index").CreateSearchContext())
{
 IQueryable<Person> query = context.GetQueryable<Person>().Where(p=> p.Firstname == "John");

  SearchResults<Person> results = query.GetResults();

 foreach(result in results) // I am getting the exception here on this line.
 {
    lbltest.Text = result.Name;
 }

}

我认为配置有问题。

IndexFieldStorageValueFormatter 无法找到合适的 TypeConverter 并退回到 Convert.ChangeType。但 ID class 没有任何字符串转换运算符,因此转换失败。

应该找到合适的TypeConverter了。它是从配置中收集的,默认情况下在 Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration 中。它应该有一个 indexFieldStorageValueFormatter 部分,其中这一行在这种情况下特别有用:

<converter handlesType="Sitecore.Data.ID, Sitecore.Kernel"                                    typeConverter="Sitecore.ContentSearch.Converters.IndexFieldIDValueConverter, Sitecore.ContentSearch" />

确保内容搜索配置正确并且您的自定义 my_text_index 不会覆盖此部分。

您可以使用 dotPeek 生成 pdb 文件并调试 IndexFieldStorageValueFormatter,但我认为您会得出相同的结论,即它没有适用于该类型的转换器。

将索引中的字符串转换为 Sitecore guid 时,Base class SearchResultItem 中出现问题。

这将指向 itemid 字段索引中的一些恶意数据。第一件事是检查您的 Search.log 文件以检查实际查询 运行 然后使用 Luke 运行 查询来查看结果。

索引中的条目可能有一个字段 (__group) 不是 Sitecore Guid 的格式。