以编程方式设置值时查询的字段索引不更新
Field index for queries not updating when value set programmatically
我的模块通过控制器创建自定义内容项:
private ContentItem createContentItem()
{
// Add the field
_contentDefinitionManager.AlterPartDefinition(
"TestType",
cfg => cfg
.WithField(
"NewField",
f => f
.OfType(typeof(BooleanField).Name)
.WithDisplayName("New Field"))
);
// Not sure if this is needed
_contentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.WithPart("TestType")
);
// Create new TestType item
var newItem = _contentManager.New("TestType");
_contentManager.Create(TestItem, VersionOptions.Published);
// Set the added boolean field to true
BooleanField newField = ((dynamic)newItem).TestType.NewField as BooleanField;
newField.Value = true;
// Set title (as date created, for convenience)
var time = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt", CultureInfo.InvariantCulture).Replace(':', '.');
newItem.As<TitlePart>().Title = time;
return newItem;
}
此操作的最终结果是一个新的 TestType 项目,其字段设置为 true。查看仪表板中的内容项以及检查数据库中的 ContentItemVersionRecord 可确认值设置正确。
但是,查询似乎无法在以这种方式设置的字段上正常工作。我找到了记录 IntegerFieldIndexRecord,这是我假设投影用于填充查询结果页面的记录。对此,TestField 的值保持为 0(假),而不是 1(真)。
转到内容项编辑页面并单击 'save' 即可正确更新 IntegerFieldIndexRecord,这意味着该值现在已由查询获取。如何为以编程方式设置的字段值更新记录?
迁移的相关部分:
SchemaBuilder.CreateTable(typeof(TestTypePartRecord).Name, table => table
.ContentPartRecord()
);
ContentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.DisplayedAs("Test Type")
.WithPart(typeof(TitlePart).Name)
.WithPart(typeof(ContainablePart).Name)
.WithPart(typeof(CommonPart).Name)
.WithPart(typeof(IdentityPart).Name)
);
编辑:解决此问题的方法是在每次更改字段值时手动更改投影索引记录,使用此调用:
_fieldIndexService.Set(testResultItem.As<FieldIndexPart>(),
"TestType", // Resolves as TestTypePart, which holds the field
"newField",
"", // Not sure why value name should be empty, but whatever
true, // The value to be set goes here
typeof(bool));
有两种方法可以解决这个问题:
1) 通过调用 ContentManager.Publish()
确保新创建的项目正在发布,因为 Orchard.Projections.Handlers.FieldIndexPartHandler
侦听发布事件以更新 FieldIndexPartRecord
2) 使用 IFieldIndexService
手动更新 FieldIndexPartRecord
,请参阅 Orchard.Projections.Handlers.FieldIndexPartHandler
的实现以了解如何执行此操作
希望对您有所帮助。
:编辑
由于调用 Create(...Published)
,ContentManager.Published()
不会执行任何操作,因为该项目已被视为已发布。
您可以执行以下操作以强制发布逻辑 运行:
bool itemPublished = newItem.VersionRecord.Published;
// unpublish item first when it is already published as ContentManager.Publish() internally first checks for published flag and when set it aborts silently
// -> this behaviour prevents calling publish listeners
if (itemPublished)
_contentManager.Unpublish(newItem);
// the following call will result in calls to IContentHandler.Publishing() / IContentHandler.Published()
_contentManager.Publish(newItem);
或者只是将项目创建为草稿,并在一切设置正确后发布它。
在某些情况下,简单的 contentManager.Publish()
是行不通的。
前段时间我遇到过类似的问题,实际上实现了一个简单的帮助服务来解决这个问题;这是摘录:
public T GetStringFieldValues<T>(ContentPart contentPart, string fieldName)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
return this.fieldIndexService.Get<T>(fieldIndexPart, partName, fieldName, string.Empty);
}
private void SetStringFieldValue(ContentPart contentPart, string fieldName, IEnumerable<int> ids)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
var encodedValues = "{" + string.Join("},{", ids) + "}";
this.fieldIndexService.Set(fieldIndexPart, partName, fieldName, string.Empty, encodedValues, typeof(string));
}
我实际上已经构建了这个用于 MediaLibrary- 和 ContentPicker 字段(它们在内部将它们的值编码为字符串),因此它可能不适合您示例中的布尔字段。
但实现起来并不难,只需查看这些字段的现有驱动程序和处理程序即可。
我的模块通过控制器创建自定义内容项:
private ContentItem createContentItem()
{
// Add the field
_contentDefinitionManager.AlterPartDefinition(
"TestType",
cfg => cfg
.WithField(
"NewField",
f => f
.OfType(typeof(BooleanField).Name)
.WithDisplayName("New Field"))
);
// Not sure if this is needed
_contentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.WithPart("TestType")
);
// Create new TestType item
var newItem = _contentManager.New("TestType");
_contentManager.Create(TestItem, VersionOptions.Published);
// Set the added boolean field to true
BooleanField newField = ((dynamic)newItem).TestType.NewField as BooleanField;
newField.Value = true;
// Set title (as date created, for convenience)
var time = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt", CultureInfo.InvariantCulture).Replace(':', '.');
newItem.As<TitlePart>().Title = time;
return newItem;
}
此操作的最终结果是一个新的 TestType 项目,其字段设置为 true。查看仪表板中的内容项以及检查数据库中的 ContentItemVersionRecord 可确认值设置正确。
但是,查询似乎无法在以这种方式设置的字段上正常工作。我找到了记录 IntegerFieldIndexRecord,这是我假设投影用于填充查询结果页面的记录。对此,TestField 的值保持为 0(假),而不是 1(真)。
转到内容项编辑页面并单击 'save' 即可正确更新 IntegerFieldIndexRecord,这意味着该值现在已由查询获取。如何为以编程方式设置的字段值更新记录?
迁移的相关部分:
SchemaBuilder.CreateTable(typeof(TestTypePartRecord).Name, table => table
.ContentPartRecord()
);
ContentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.DisplayedAs("Test Type")
.WithPart(typeof(TitlePart).Name)
.WithPart(typeof(ContainablePart).Name)
.WithPart(typeof(CommonPart).Name)
.WithPart(typeof(IdentityPart).Name)
);
编辑:解决此问题的方法是在每次更改字段值时手动更改投影索引记录,使用此调用:
_fieldIndexService.Set(testResultItem.As<FieldIndexPart>(),
"TestType", // Resolves as TestTypePart, which holds the field
"newField",
"", // Not sure why value name should be empty, but whatever
true, // The value to be set goes here
typeof(bool));
有两种方法可以解决这个问题:
1) 通过调用 ContentManager.Publish()
确保新创建的项目正在发布,因为 Orchard.Projections.Handlers.FieldIndexPartHandler
侦听发布事件以更新 FieldIndexPartRecord
2) 使用 IFieldIndexService
手动更新 FieldIndexPartRecord
,请参阅 Orchard.Projections.Handlers.FieldIndexPartHandler
的实现以了解如何执行此操作
希望对您有所帮助。
:编辑
由于调用 Create(...Published)
,ContentManager.Published()
不会执行任何操作,因为该项目已被视为已发布。
您可以执行以下操作以强制发布逻辑 运行:
bool itemPublished = newItem.VersionRecord.Published;
// unpublish item first when it is already published as ContentManager.Publish() internally first checks for published flag and when set it aborts silently
// -> this behaviour prevents calling publish listeners
if (itemPublished)
_contentManager.Unpublish(newItem);
// the following call will result in calls to IContentHandler.Publishing() / IContentHandler.Published()
_contentManager.Publish(newItem);
或者只是将项目创建为草稿,并在一切设置正确后发布它。
在某些情况下,简单的 contentManager.Publish()
是行不通的。
前段时间我遇到过类似的问题,实际上实现了一个简单的帮助服务来解决这个问题;这是摘录:
public T GetStringFieldValues<T>(ContentPart contentPart, string fieldName)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
return this.fieldIndexService.Get<T>(fieldIndexPart, partName, fieldName, string.Empty);
}
private void SetStringFieldValue(ContentPart contentPart, string fieldName, IEnumerable<int> ids)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
var encodedValues = "{" + string.Join("},{", ids) + "}";
this.fieldIndexService.Set(fieldIndexPart, partName, fieldName, string.Empty, encodedValues, typeof(string));
}
我实际上已经构建了这个用于 MediaLibrary- 和 ContentPicker 字段(它们在内部将它们的值编码为字符串),因此它可能不适合您示例中的布尔字段。 但实现起来并不难,只需查看这些字段的现有驱动程序和处理程序即可。