Skip to content

了解数据访问-Understanding Data Access

This topic has been updated for the Orchard 1.9 release.

本主题已针对Orchard 1.9版本进行了更新。

Data access in an Orchard project is different than data access in a traditional web application, because the data model is built through code rather than through a database management system. You define your data properties in code and the Orchard framework builds the database components to persist the data. If you need to change the data structure, you write code that specifies the changes, and those changes are then propagated by that code to the database system. This code-centric model includes layers of abstraction that permit you to reuse components in different content types and to add or change behaviors without breaking other layers.

Orchard项目中的数据访问与传统Web应用程序中的数据访问不同,因为数据模型是通过代码而不是通过数据库管理系统构建的。您可以在代码中定义数据属性,Orchard框架构建数据库组件以保留数据。如果需要更改数据结构,则编写指定更改的代码,然后将这些更改传播到数据库系统。这种以代码为中心的模型包括抽象层,允许您重用不同内容类型的组件,并在不破坏其他层的情况下添加或更改行为。

The key concepts of data access are the following:

数据访问的关键概念如下:

  • Records

  • 记录 *

  • Data migrations

  • 数据迁移 *

  • Content handlers

  • 内容处理程序 *

  • Content drivers

  • 内容驱动程序 *

Records

记录

A record is a class that represents the database schema for a content part. To create a record, you define a class that derives from ContentPartRecord and add the properties that you need in order to store data for the content part. Each property must be virtual. For example, a Map part might include the following record:

记录是表示内容部分的数据库模式的类。要创建记录,您需要定义一个派生自ContentPartRecord的类,并添加所需的属性以存储内容部分的数据。每个属性都必须是虚拟的。例如,Map部分可能包含以下记录:

namespace Map.Models {

    public class MapRecord : ContentPartRecord {

        public virtual double Latitude { get; set; }

        public virtual double Longitude { get; set; }

    }

}

Typically, the record class resides in a folder named Models. The parent class, ContentPartRecord, also includes a property named id and a reference to the content item object. Therefore, an instance of the MapRecord class includes not just Latitude and Longitude but also the id property and the content item object that is used to maintain the relationships between the part and other content.

通常,记录类位于名为“Models”的文件夹中。父类“ContentPartRecord”还包括名为“id”的属性和对内容项对象的引用。因此,MapRecord类的实例不仅包括“Latitude”和“Longitude”,还包括id属性和用于维护部件与其他内容之间关系的内容项对象。

When you define a content part, you use the record as shown below:

定义内容部分时,使用如下所示的记录:

namespace Maps.Models

{

    public class MapPart : ContentPart<MapRecord>

    {

        [Required]

        public double Latitude

        {

            get { return Retrieve(r => r.Latitude); }

            set { Store(r => r.Latitude, value); }

        }



        [Required]

        public double Longitude

        {

            get { return Retrieve(r => r.Longitude); }

            set { Store(r => r.Longitude, value); }

        }

    }

}

Notice that only data that's relevant to the part is defined in the MapPart class. You do not define any properties that are needed to maintain the data relationships between MapPart and other content.

请注意,只有与该部件相关的数据才在MapPart类中定义。您没有定义维护“MapPart”和其他内容之间的数据关系所需的任何属性。

For a complete example of the MapPart, see Writing a Content Part. You can also read the Getting Started with Modules course to familiarize yourself with the overall concepts of module development.

有关MapPart的完整示例,请参阅[编写内容部件](编写内容部分)。您还可以阅读[模块入门课程](模块入门)以熟悉模块开发的整体概念。

Data Migrations

数据迁移

Creating the record class does not create the database table; it only creates a model of the schema. To create the database table, you must write a data migration class.

创建记录类不会创建数据库表;它只创建模式的模型。要创建数据库表,必须编写数据迁移类。

A data migration class enables you to create and update the schema for a database table. The code in a migration class is executed when an administrator chooses to enable or update the part. The update methods provide a history of changes to the database schema. When an update is available, the site administrator can choose to run the update.

数据迁移类使您可以创建和更新数据库表的模式。当管理员选择启用或更新部件时,将执行迁移类中的代码。更新方法提供数据库模式更改的历史记录。当有可用更新时,站点管理员可以选择运行更新。

You can create a data migration class by running the following command from the Orchard command line:

您可以通过从Orchard命令行运行以下命令来创建数据迁移类:

codegen datamigration <feature_name>

This command creates a Migrations.cs file in the root of the feature. A Create method is automatically created in the migration class.

此命令在功能的根目录中创建“Migrations.cs”文件。在迁移类中自动创建Create方法。

In the Create method, you use the SchemaBuilder class to create the database table, as shown below for the MapPart feature.

Create方法中,使用SchemaBuilder类创建数据库表,如下面的MapPart功能所示。

In the Uninstall method you can implement destructive operations that will be executed when the module is uninstalled. Keep in mind that when a module is re-added and enabled after it was uninstalled it will be installed again, thus the Create method of migrations will also run.

在“卸载”方法中,您可以实现在卸载模块时将执行的破坏性操作。请记住,当一个模块在卸载后重新添加并启用时,它将再次安装,因此“Create”方法也将运行。

namespace Map.DataMigrations {

    public class Migrations : DataMigrationImpl {



        public int Create() {

            // Creating table MapRecord

            SchemaBuilder.CreateTable("MapRecord", table => table

                .ContentPartRecord()

                .Column("Latitude", DbType.Double)

                .Column("Longitude", DbType.Double)

            );



            ContentDefinitionManager.AlterPartDefinition(

                typeof(MapPart).Name, cfg => cfg.Attachable());



            return 1;

        }

        public void Uninstall() {

            // Dropping tables can potentially cause data loss for users so be sure to warn them in your module's documentation about the implications.

            SchemaBuilder.DropTable("MapRecord");

            ContentDefinitionManager.DeletePartDefinition(typeof(MapPart).Name);

        }

    }

}

By including .ContentPartRecord() with your properties in the definition of the database schema, you ensure that other essential fields are included in the table. In this case, an id field is included with Latitude and Longitude.

通过在数据库模式的定义中包含.ContentPartRecord()和您的属性,可以确保表中包含其他必要字段。在这种情况下,“纬度”和“经度”中包含一个“id”字段。

The return value is important, because it specifies the version number for the feature. You will use this version number to update the schema.

返回值很重要,因为它指定了要素的版本号。您将使用此版本号更新架构。

You can update the database table by adding a method with the naming convention UpdateFromN, where N is the number of the version to update. The following code shows the migration class with a method that updates version by adding a new column.

您可以通过添加命名约定为“UpdateFromN”的方法来更新数据库表,其中_N_是要更新的版本号。以下代码显示了迁移类,其中包含通过添加新列来更新版本的方法。

namespace Map.DataMigrations {

    public class Migrations : DataMigrationImpl {



        public int Create() {

            // Creating table MapRecord

            SchemaBuilder.CreateTable("MapRecord", table => table

                .ContentPartRecord()

                .Column("Latitude", DbType.Double)

                .Column("Longitude", DbType.Double)

            );



            ContentDefinitionManager.AlterPartDefinition(

                typeof(MapPart).Name, cfg => cfg.Attachable());



            return 1;

        }



        public int UpdateFrom1() {

            SchemaBuilder.AlterTable("MapRecord", table => table

                .AddColumn("Description", DbType.String)

           );

            return 2;

        }



    }

}

The update method returns 2, because after the column is added, the version number is 2. If you have to add another update method, that method would be called UpdateFrom2().

update方法返回2,因为在添加列之后,版本号为2.如果必须添加另一个更新方法,则该方法将被称为UpdateFrom2()

After you add the update method and run the project the module will be silently & automatically upgraded.

添加更新方法并运行项目后,模块将以静默方式自动升级。

Content Handlers

内容处理程序

A content handler is similar to a filter in ASP.NET MVC. In the handler, you define actions for specific events. In a simple content handler, you just define the repository of record objects for the content part, as shown in the following example:

内容处理程序类似于ASP.NET MVC中的过滤器。在处理程序中,您可以定义特定事件的操作。在简单的内容处理程序中,您只需为内容部件定义记录对象的存储库,如以下示例所示:

namespace Map.Handlers {

    public class MapHandler : ContentHandler {

        public MapHandler(IRepository<MapRecord> repository) {

            Filters.Add(StorageFilter.For(repository));

        }

    }

}

In more advanced content handlers, you define actions that are performed when an event occurs, such as when the feature is published or activated. For more information about content handlers, see Understanding Content Handlers.

在更高级的内容处理程序中,您可以定义事件发生时执行的操作,例如发布或激活功能时。有关内容处理程序的详细信息,请参阅[了解内容处理程序](了解内容处理程序)。

Content Drivers

内容驱动程序

A content driver is similar to a controller in ASP.NET MVC. It contains code that is specific to a content part type and is usually involved in creating data shapes for different conditions, such as display or edit modes. Typically, you override the Display and Editor methods to return the ContentShapeResult object for your scenario.

内容驱动程序类似于ASP.NET MVC中的控制器。它包含特定于内容部件类型的代码,通常涉及为不同条件创建数据形状,例如显示或编辑模式。通常,您重写DisplayEditor方法以返回场景的ContentShapeResult对象。

For an example of using a content driver, see Accessing and Rendering Shapes.

有关使用内容驱动程序的示例,请参阅[访问和渲染形状](访问和渲染形状)。