惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
博客园 - 聂微东
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
Jina AI
Jina AI
D
Docker
B
Blog
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
D
DataBreaches.Net
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Y
Y Combinator Blog
N
Netflix TechBlog - Medium
月光博客
月光博客
F
Fortinet All Blogs
爱范儿
爱范儿
H
Help Net Security
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
The Cloudflare Blog
有赞技术团队
有赞技术团队
T
Tailwind CSS Blog
U
Unit 42

博客园 - JerryZhao

[转载]jQuery对象VS DOM对象 [Reference] Navigation on Matrix Subtotal [Refereces]Creating an .ini File for the Application Manager [Refereces] Developing and Deploying Pocket PC Setup Applications [References]More on device app installs - Installing a Windows Mobile device application from a desktop MSI [References]Deploying .NET Compact Framework 2.0 Applications with .cab and .msi Files [References]Installing Multiple CAB Files [Reference]Wix Restart IIS code snippet [Reference] Windows Installer XML (WiX) 3.0 Snippets [Reference] Casle Demo App: Midway Summary [ActiveRecord] 之五:ActiveRecordMediator [Reference][ActiveRecord] 之四:Cascade [Reference][ActiveRecord] 之六:继承 [Referece][ActiveRecord] 之七:多数据库配置 [Reference] [Castle AR] 5. Base Relations [Reference][Castle AR] 3. Validate [Reference][Castle AR] 2. ActiveRecord [reference][Castle AR] 4. CRUD [Reference]NHibernateDataSource: A DataSourceControl for ASP.NET 2.0
[Reference][Castle AR] 1. Starter
JerryZhao · 2008-01-23 · via 博客园 - JerryZhao

http://www.rainsts.net/article.asp?id=483
以前研究过一阵 ORM,基于某些理由,比较喜欢 XPO 和 Castle ActiveRecord。原因不外乎以下几点:

  • "Class to DB",我觉得 ORM 最重要的目的是用一种简便的方式来存储对象。我们对业务分析的重点是对象,而不会优先考虑数据库设计。XPO 和 Castle AR 在这方面做得都很好。
  • 一个是著名厂商 DevExpress 的产品,另一个是被广泛使用的 NHibernate 的封装,较好的升级保障对于项目开发是很重要的。网上一些个人的 ORM 作品虽然很有特色,但毕竟没人能保证 "未来三天" 它是否依然存在,也没有人能保证 Bug 会得到修复。
  • 这两个组件都能得到较好的技术支持,XPO 是商业软件自不必说,NHibernate 的用户群组和开发资料网上也很多。
  • 基于开发成本考虑,这两套组件无论是代码维护还是人力资源上都有较好的性价比。
  • 最后就是我个人对用于映射的配置文件有那么点 "偏见"。除非是改造现有系统,否则这些配置文件几乎不会发生改变。基于特性的映射将数据库、配置文件、实体类三个变化源归纳到一起,更好维护一些。

最近打算用 ORM 做点东西,细细衡量之下,还是选择 Castle AR,毕竟 "OpenSource" 的授权方式还是比较吸引人的。看了看以前写的 AR 文章,有点简单,有点落后,所以再写一点,应该没有炒剩饭的嫌疑。

------------ 以上都是题外话,就此打住!----------------------

AR 中有个类叫 ActiveRecordStarter,它是 AR 运行的起始点。我们就用它拉开序幕,重新研究 Castle AR RC2 的功能和特点。特别申明,我使用的 Castle 版本是从 Build Server 获取的最新编译版本 (castleproject-1.1-build_382-net-2.0-debug.zip)。

ActiveRecordStarter 的核心任务是获取所有 ActiveRecord 实体类型的信息,并创建 ActiveRecordModel。当然,ActiveRecordStarter 作用远不止如此。

1. 创建数据库连接

AR 沿用了 NHibernate 的配置习惯,我们可以使用配置文件,也可以使用代码。虽然我们可以使用默认方式,将配置信息写入 App.config / web.config,但我建议你使用单独的配置文件更好维护一些。

ar.xml

<?xml version="1.0" encoding="utf-8" ?>
<activerecord>
  <config>
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="hibernate.connection.connection_string" value="server=(local);uid=sa;pwd=123456;database=test" />
  </config>
</activerecord>

XmlConfigurationSource

XmlConfigurationSource config = new XmlConfigurationSource("ar.xml");
ActiveRecordStarter.Initialize(Assembly.GetCallingAssembly(), config);

当然,我们还可以使用代码来代替配置文件。(注意添加 Castle.Core.dll 的引用。)

InPlaceConfigurationSource config = new InPlaceConfigurationSource();

Hashtable properties = new Hashtable();
properties.Add("hibernate.connection.driver_class", "NHibernate.Driver.SqlClientDriver");
properties.Add("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
properties.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("hibernate.connection.connection_string", "server=(local);uid=sa;pwd=123456;database=test");

config.Add(typeof(ActiveRecordBase), properties);

ActiveRecordStarter.Initialize(Assembly.GetCallingAssembly(), config);

uploads/200705/08_103129_ar1.gif

2. 初始化实体类

方式1:指定具体实体类型。

ActiveRecordStarter.Initialize(config, typeof(User), typeof(Order));

方法2:指定程序集,初始化程序集中所有实体类型。 (使用重载方法,我们可以指定多个程序集。)

ActiveRecordStarter.Initialize(Assembly.GetExecutingAssembly(), config);

方法3:后续注册。

ActiveRecordStarter.Initialize(Assembly.GetExecutingAssembly(), config);
ActiveRecordStarter.RegisterTypes(typeof(User));

由于 Initialize 只能执行一次,所以 "后续注册" 就非常有用了,如果你看过我写的有关 CodeDom / Emit 方面的文章,就会明白动态构造类型对于 ORM 有些什么好处。

public static void Initialize(IConfigurationSource source, params Type[] types)
{
  lock (lockConfig)
  {
    if (isInitialized)
    {
      throw new ActiveRecordInitializationException("You can't invoke ActiveRecordStarter.Initialize more than once");
    }
    ...
  }
}

3. 创建数据库架构

初始化类型之后,我们可以用 ActiveRecordStarter 提供的方法创建所需的实体数据表了。

// 删除架构
ActiveRecordStarter.DropSchema();

// 创建架构
ActiveRecordStarter.CreateSchema();

// 创建相关 SQL 脚本。
ActiveRecordStarter.GenerateCreationScripts("create.sql");
ActiveRecordStarter.GenerateDropScripts("drop.sql");

最后,我们写一个完整一些的例子。

[ActiveRecord("Users")]
public class User
{
  private int id;

  [PrimaryKey(Generator=PrimaryKeyType.Identity)]
  public int Id
  {
    get { return id; }
    set { id = value; }
  }

  private string name;

  [Property(Unique=true, NotNull=true)]
  public string Name
  {
    get { return name; }
    set { name = value; }
  }

}

public class ARTester
{
  public static void Test()
  {
    InPlaceConfigurationSource config = new InPlaceConfigurationSource();
    Hashtable properties = new Hashtable();
    properties.Add("hibernate.connection.driver_class", "NHibernate.Driver.SqlClientDriver");
    properties.Add("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
    properties.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
    properties.Add("hibernate.connection.connection_string", "server=(local);uid=sa;pwd=123456;database=test");
    config.Add(typeof(ActiveRecordBase), properties);

    ActiveRecordStarter.Initialize(Assembly.GetExecutingAssembly(), config);

    ActiveRecordStarter.DropSchema();
    ActiveRecordStarter.CreateSchema();

    //ActiveRecordStarter.GenerateCreationScripts("create.sql");
    //ActiveRecordStarter.GenerateDropScripts("drop.sql");
  }
}