Orchard中的data access与传统web程序不同,因为是通过代码建立data model而不是通过数据库管理系统。你在代码中定义你的数据属性,Orchard Framework建立持久化数据的数据库组件。如果你需要更改数据结构,你写具体更改的代码,这些更改被这段代码传播到数据库。这个代码中心的model包含抽象层,允许你在不同的内容类型中重用组件,并且添加或更改行为不会破坏其它layers。
数据访问的主要概念:
- Records
- Data migrations
- Content handlers
- Content drivers
Records
一个record是为内容类型描述数据库架构的类,要创建一个record,需要定义一个从ContentPartRecord继承的类,并添加你需要为内容类型存储数据的属性,每个属性必须是虚拟的,例如:Map part可能含有下面的record:
namespace Map.Models {
public class MapRecord : ContentPartRecord {
public virtual double Latitude { get; set; }
public virtual double Longitude { get; set; }
}
}
通常,record类在Models文件夹下,ContentPartRecord父类包含Id 属性和 到content item object的引用。因此,MapRecord类实例不公有Latitude
and Longitude属性,也有Id属性和到content item object的引用,这个引用用来维持part和其它content之间的关系。
当定义一个content part时,像下面显示这样使用record:
namespace Map.Models {
public class MapPart : ContentPart<MapRecord> {
[Required]
public double Latitude
{
get { return Record.Latitude; }
set { Record.Latitude = value; }
}
[Required]
public double Longitude
{
get { return Record.Longitude; }
set { Record.Longitude = value; }
}
}
}
请注意,这part相关的数据在MapPart类定义,你不需定义需要维护MapPart和其它content之间的关系的任何属性。
Data Migrations
创建record类不创建数据库表,它仅傻仔架构的model,要创建数据库表,你必须写一个data migration 类。
一个data migration类使用能创建和更新数据库表的架构,data migration类中的代码在当一个管理员选择启用或更新这个part时执行。update方法提供更改数据库架构的历史记录。当一个更新可用时,网站管理员能选择运行这个更新。
你能通过命令行工具创建一个migration类:
codegen datamigration <feature_name>
这个命令在feature的根目录创建一个Migrations.cs文件,自动创建了一个Create方法,Create方法中,使用SchemaBuilder类创建数据库表,像下面MapPart feature显示的这样:
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;
}
}
}
在数据库架构定义中用.ContentPartRecord() 使用你的属性,你确保其它必要的fields包含在表中,Id field
包含Latitude and Longitude.
返回值很重要,因为它指定了feature的版本号,你会使用这个版本号来更新架构。
你能添加一个方法习惯叫UpdateFromN来更新数据库表,N是要更新到的版本号。下面代码展示的migration类,使用更新版本的方法来添加一个列。
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;
}
}
}
update方法返回2,因为这个列添加后,版本号是2,如果你添加另一个update方法,这个方法应该叫UpdateFrom2()。
你能在feature管理面板更新模块:
点击update后,数据库表中就会包含一个新列。你将不得不修改record和part类来使用新的字段。
Content Handlers
一个内容处理程序就像是ASP.NET MVC的filter。handler中,你为具体的事件定义行为。在一个简单的内容处理程序中,你仅定义关于content part的record对象的存储,像下面的示例:
namespace Map.Handlers {
public class MapHandler : ContentHandler {
public MapHandler(IRepository<MapRecord> repository) {
Filters.Add(StorageFilter.For(repository));
}
}
}
更高级的内容处理程序,当一个事件发生时你定义的行为就执行,比如feature发布或激活时。
Content Drivers
Content driver就像ASP.NET MVC中的控制器,它包含指定content part type的代码,通常牵涉关于不同条件创建data shapes,比如display or edit modes。通常,你为你的scenario重写Display和Editor方法返回ContentShapeResult对象。