65.9K
CodeProject 正在变化。 阅读更多。
Home

MercuryORM - 简单实体框架

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.77/5 (6投票s)

2014 年 6 月 29 日

CPOL

4分钟阅读

viewsIcon

16706

downloadIcon

129

一个轻量级的基于实体的框架

Using the Code

我们从介绍 Mercury\DbContext 类开始。 DbContext 类是一个 abstract 类,不能直接实例化,必须被继承。必须创建一个具体的类来继承 DbContext。通过继承 DbContext,您实际上是为数据库相关任务创建了一个包装器。 DbContext 类公开了一个 dbSet() 方法,该方法用于注册实体。下面的清单 1.1 展示了一个带有两个已注册实体的示例 BlogContext 类。

列表 1.1

class BlogContext extends \Mercury\DbContext{
	public function getUsers(){
		return $this->dbSet('Models\User');
	}
	
	public function getPosts(){
		return $this->dbSet('Models\Post');
	}
}

上面的上下文 (BlogContext) 定义了两个方法 (getUsers()getPosts()),这两个方法都将返回 Mercury\DbSet 的一个实例,但是每个 DbSet 将维护其实体的数据。在上面的示例中, getUsers() 方法注册了一个 DbSet,它将负责管理 Models\User 实体。 DbSet 实例由 DbContext 在内部以数组的形式管理。如果随后调用 getUsers() 方法,则会返回先前实例化的 DbSet。 在我们继续之前,让我们看看如何使用新创建的 BlogContext 连接到数据库。下面的清单 1.2 展示了如何使用默认设置和连接字符串连接到 MySQL 数据库。

列表 1.2

// Default settings
$blogContext = new BlogContext();

// Using a connection string
$blogContext = new BlogContext('driver=mysql;host=127.0.0.1;
               dbname=blogcontext;uid=root;pwd=pass;charset=utf8');

使用默认设置实例化上下文时,上下文的名称用作数据库名称,并且使用用户名 "root" 和空密码在 localhost 上建立连接。

DbSet

如前所述,每个 DbSet 实例管理它所注册类型的实体集合。除了管理实体集合之外, DbSet 还维护实体元数据。 实体元数据是描述实体的数据,并使用注释放置在实体类中。 下面的清单 1.3 展示了一个带有元数据的 Model\User 实体。

清单 1.3

namespace Models;

//[TableName("users")]
//[UniqueKey("user_id")]
class User {
    
    protected $user_id;
    
    //[Required]
    //[StringLength(30)]
    protected $first_name;
    
    //[Required]
    //[StringLength(30)]
    protected $last_name;

    //[Required]
    //[StringLength(50)]
	//[DefaultValue("user@mail.com")]
    protected $email;
    
    public function setFirstName($name){
        $this->first_name = $name;
    }
    
    public function setLastName($name){
        $this->last_name= $name;
    }
    
    public function setEmail($email){
        $this->email = $email;
    }
}

上面的代码示例使用注释来为实体和实体属性分配属性。 每个属性都是一种特定类型。 例如, Required 属性的类型为 Mercury\Attributes\Required,而属性 StringLength 的类型为 Mercury\Attributes\StringLength。 属性有助于强制执行验证并提供有关实体的元数据。 也可以使用 DefaultValue 属性为实体属性提供默认数据。

必须使用 DbSets add() 方法将实体的实例添加到其相关的 DbSet 中。 add 方法不会将实体持久化到数据库中,而是将实体的状态更改为 PERSIST,这意味着当调用 DbContextsaveChanges() 方法时,该实体将被持久化到基础数据库。 一旦持久化, DbContext 将在内部集合中维护该实体,并将其状态更改为 PERSISTED。 将实体添加到不相关的 DbSet 将引发 EntityException 类型的异常。 下面的清单 1.4 展示了如何创建一个新用户并将该用户持久化到数据库中。

清单 1.4

$user = new Models\User();
$user->setFirstName('John');
$user->setLastName('Smith');
$user->setEmail('j.smith@mail.com');

$blogContext = new BlogContext();
$blogContext->getUsers()->add($user);
$blogContext->saveChanges();

可以使用 add 方法将多个用户添加到 DbSet,然后使用 saveChanges() 方法进行持久化。 saveChanges() 方法也用于更新记录。 在下一个示例中, DbSet 类的 find() 方法用于查找具有给定 user_id 的用户,然后更新用户详细信息,并使用 saveChanges() 方法更新用户详细信息。

清单 1.5

$blogContext = new BlogContext();

// Find a user with the user_id=3
$user = $blogContext->getUsers()->find(3);

// Change the email address
$user->setEmail('new@mail.com');

// Save changes
$blogContext->saveChanges();

上面的代码示例引入了一个 find() 方法。 find 方法用于在基础数据库中搜索记录,并将记录映射到 DbSet 实体类型。 由于 find 方法属于 DbSet 类,因此它知道表名和主键,因为 DbSet 维护实体元数据。 找到记录后,它将传递给 DbContext,后者将其存储在内部集合中,并将实体的状态更改为 PERSISTED,然后返回它。 还存在一个 findAll() 方法,该方法返回给定实体类型的数组。 findAll() 方法接受一个键/值数组,用作搜索条件。

也可以实现简单的关联。 在某些情况下,您可能有一个 insert 依赖于另一个 insert。 考虑以下示例,您要创建一个也发表了一篇文章的用户。 用户和文章都将被持久化。 通常,您将持久化用户并返回用户的最后一个插入 id,用作文章的 author_id 的外键值。 下面的清单 1.6 展示了关联如何帮助插入用户和文章,而无需自己返回最后一个插入 id。

清单 1.6

$user = new Models\User();
$user->setFirstName('John');
$user->setLastName('Smith');
$user->setEmail('j.smith@mail.com');

$post = new Models\Post();
$post->setTitle('My first post');
$post->setBody('This is my first blog post');
$post->setAuthor($user);

$blogContext = new BlogContext();
$blogContext->getUsers()->add($user);
$blogContext->getPosts()->add($post);

$blogContext->saveChanges();

请注意, Models\Post 实体的 setAuthor() 方法如何接受 Models\User 实体对象。 当 Models\Post 实体被持久化时, DbContext 将查找 Models\User 实体并返回最后一个插入 id。

这标志着本文的结束。 请随时留下您的评论和建议。

历史

  • 2014 年 6 月 29 日:初始版本
© . All rights reserved.