问题
I've been working with a custom module that has a widget with some fields stored in the DB. I added a new non-required field to the widget and a corresponding field in the database is not being added. What's the best way to handle this type of change?
I can manually add a field in the dev database to match it, but this is unrealistic for 50 some odd production tenant sites.
回答1:
To expand on @Bertand's answer a little, you don’t need to create database columns when you add fields (Boolean Field, Text Field, Media Picker Field etc) to content parts because the database structure for storing fields is already in place in the database.
Fields are stored as serialized XML against the content part. All of my records are stored in the Orchard_Framework_ContentItemVersionRecord
table (there’s a similar table Orchard_Framework_ContentItemRecord
, but that doesn’t appear to be used.
The XML is essentially of the format:
<Data>
<SomePart>
<SomeFieldName SomeFieldProperty=”value”
SomeOtherProperty=”value”>FieldValue</SomeFieldName>
</SomePart>
<SomeOtherPart>
<SomeOtherFieldName>FieldValue</SomeOtherFieldName>
</SomeOtherPart>
</Data>
So, for example you might have something like this:
<Data>
<PicturePart>
<picture AlternateText="" Class="" Style="" Alignment="" Width="1219"
Height="709">~/Media/Default/images/greatPicture.jpg</picture>
</PicturePart>
<PictureType>
<ExtraDescription>It’s a great picture!</ExtraDescription>
</Pictureype>
</Data>
Orchard uses the information from the Settings_XXXRecord
tables to determine the types of the fields when it’s deserializing them back from the database.
All of this is why, as Bertand says here, fields are easier to create, but harder to query.
Looking at the solution you've posted, it looks like you're adding custom columns, rather than Orchard Fields. If this is what you're trying to do, then it seems like something you should be doing in a datamigration for your module by using AddColumn, as described here. This would look something like:
public int UpdateFrom1() {
SchemaBuilder.AlterTable("TABLE_NAME", table => table
.AddColumn<int>("mynewcolumn")
.AddColumn<string>("mynewcolumn2")
);
return 2;
}
回答2:
I'm not sure if it's the ideal solution, but running an sql script that manually adds the columns to the module table for all tenants sites seems to do the trick okay. Luckily I setup all my sites to exist in the same database!
SELECT 'Alter table ' + TABLE_NAME + ' Add mynewcolumn int null, mynewcolumn2 nvarchar(15) null' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%the_suffix_my_module_puts_for_a_tenant'
回答3:
A field is not supposed to add a column in the database. By design.
来源:https://stackoverflow.com/questions/10805584/orchard-cms-how-to-manage-new-fields-for-custom-module-widget-with-database