2

OrchardCMS 开发人员/用户,

我有

public class MyContentPartRecord : ContentPartRecord
{ ... }

我想把它改成

public class MyContentPartRecord : ContentPartVersionRecord
{ ... }

为了能够为这部分创建草稿。

我添加到 Migrations

SchemaBuilder.AlterTable(
            "MyContentPartRecord",
            table =>
            table
                .AddColumn<int>("ContentItemRecord_id")
            );

我运行该应用程序,结果是获取 MyContentPart 的内容项,它创建了一个空的已发布版本。

在 MyContentPartRecord 表的数据库中:

Id  [..fields..]    ContentItemRecord_Id
657 NULL,..         67
67  'MYDATA',...    NULL

如何创建有效的可起草 MyContentPart?

更新。我试过没有成功添加:

SchemaBuilder.ExecuteSql(@"
    UPDATE       MyContentPartRecord 
    SET                ContentItemRecord_id = t2.ContentItemRecord_id 
    from MyContentPartRecord t1 inner join Orchard_Framework_ContentItemVersionRecord t2 on t1.id= t2.id
");

因为果园似乎无法处理 MyContentPartRecord 表中的旧记录,因为它们没有设置 ContentItemRecord_id。

4

3 回答 3

2

如果没有手动 SQL 脚本,您将无法做到这一点。

Id对这两者来说意味着不同的东西:

  • 因为ContentPartRecord它是一个 Id 的外键ContentItemRecord
  • 因为ContentPartVersionRecord它是一个 Id 的外键ContentItemVersionRecord

因此,在添加新列后ContentItemRecord_id,您需要

  • Id首先,将现有数据从列复制到ContentItemRecord_id,然后
  • 用每个项目的最新版本的正确 id填充Id列。版本记录保存在Orchard_Framework_ContentItemVersionRecord表中。
于 2013-05-17T19:47:08.577 回答
0

在 Piotr 的帮助下,这里有一个解决方案。要放入以下内容Migrations.cs

SchemaBuilder.AlterTable(
                "MyContentPart",
                table =>
                table
                    .AddColumn<int>("ContentItemRecord_id")
                );

            SchemaBuilder.ExecuteSql(@"
ALTER TABLE MyModuleName_MyContentPart
DROP CONSTRAINT PK__MyModuleName_W__3214EC072C83793F
");
            SchemaBuilder.ExecuteSql(@"
INSERT INTO MyModuleName_MyContentPart
                         (Id, ContentItemRecord_id, Field1, Field2)
SELECT        t3.Id AS id, t2.Id AS ContentItemRecord_id, t2.Field1, t2Field2
FROM            MyModuleName_MyContentPart AS t2 LEFT OUTER JOIN
                         Orchard_Framework_ContentItemVersionRecord AS t3 ON t2.Id = t3.ContentItemRecord_id
WHERE        (t3.Latest = 1) AND (NOT (t3.Id IS NULL))
");
            SchemaBuilder.ExecuteSql(@"
DELETE FROM MyModuleName_MyContentPart
WHERE ContentItemRecord_id is NULL
");
            SchemaBuilder.ExecuteSql(@"
ALTER TABLE MyModuleName_MyContentPart
ADD CONSTRAINT PK_MyModuleName_MyContentPart_ID PRIMARY KEY (Id)
");

更新。

最终的解决方案:

SchemaBuilder.AlterTable(
                "MyContentPart",
                table =>
                table
                    .AddColumn<int>("ContentItemRecord_id")
                );

            SchemaBuilder.ExecuteSql(@"
ALTER TABLE MyModuleName_MyContentPart
DROP CONSTRAINT PK__MyModule_W__3214EC072C83793F
");
            SchemaBuilder.ExecuteSql(@"
INSERT INTO MyModuleName_MyContentPart
 (Id, ContentItemRecord_id, Field1)
SELECT V.Id as Id
       ,T.Id as ContentItemRecord_id 
      ,Field1
FROM  [MyModuleName_MyContentPart] T
    LEFT OUTER JOIN
        Orchard_Framework_ContentItemVersionRecord AS V ON V.ID in
            (select top(1) Id 
                from Orchard_Framework_ContentItemVersionRecord 
                where ContentItemRecord_id = T.ID 
                order by latest desc, id desc)
");
            SchemaBuilder.ExecuteSql(@"
DELETE FROM MyModuleName_MyContentPart
WHERE ContentItemRecord_id is NULL
");
            SchemaBuilder.ExecuteSql(@"
ALTER TABLE MyModuleName_MyContentPart
ADD CONSTRAINT PK_MyModuleName_MyContentPart_ID PRIMARY KEY (Id)
");
        }
于 2013-05-20T11:29:17.290 回答
0

这是一个更通用的解决方案,可以基于@Artjom 和@PiotrSzmyd 的解决方案进入您的migration.cs 文件。该解决方案处理了自动生成的主键可能为模块的每个用户命名不同的事实。如果用户定义了全局数据库前缀(例如,当使用多租户时),表名也可以作为前缀。

    // Manually add the column that is required for the part to be a ContentPartVersionRecord
    SchemaBuilder.AlterTable("MyCustomPartRecord", table => table.AddColumn<int>("ContentItemRecord_id"));

    // Get table name
    var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_";
    var tableName = tablePrefix + "MyModule_MyCustomPartRecord";

    // Drop the primary key
    SchemaBuilder.ExecuteSql(string.Format(@"
        DECLARE @primaryKeyName NVARCHAR(MAX)

        SELECT @primaryKeyName = constraint_name
        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
        WHERE CONSTRAINT_TYPE = 'Primary Key' and TABLE_NAME = '{0}'                

        EXEC(N'ALTER TABLE {0} DROP CONSTRAINT ' + @primaryKeyName)
    ", tableName));

    // Migrate IDs to ContentItemRecord_id
    SchemaBuilder.ExecuteSql(string.Format(@"
        INSERT INTO {0} (Id, ContentItemRecord_id, Category_Id, ItemCode, Name, Description, DisplayOrder, Location, MaintenanceFrequency, MaintenanceFrequencyMultiplier, MaintenanceStartDate, Notes, IsEnabled)
        SELECT V.Id as Id, T.Id as ContentItemRecord_id, Category_Id, ItemCode, Name, Description, DisplayOrder, Location, MaintenanceFrequency, MaintenanceFrequencyMultiplier, MaintenanceStartDate, Notes, IsEnabled
        FROM {0} T
        LEFT OUTER JOIN
        {1}Orchard_Framework_ContentItemVersionRecord AS V ON V.ID in
            (select top(1) Id 
                from {1}Orchard_Framework_ContentItemVersionRecord 
                where ContentItemRecord_id = T.ID 
                order by latest desc, id desc)
    ", tableName, tablePrefix));

    // Remove old rows (no ContentItemRecord_id value)
    SchemaBuilder.ExecuteSql(string.Format(@"
        DELETE FROM {0}
        WHERE ContentItemRecord_id is NULL
    ", tableName));

    // Re-add the primary key
    SchemaBuilder.ExecuteSql(string.Format(@"
        ALTER TABLE {0}
        ADD CONSTRAINT PK_{0}_Id PRIMARY KEY (Id)
    ", tableName));
于 2013-09-10T11:21:07.940 回答