• Castle ActiveRecord学习笔记五:一对多(OneMany)映射关系


    本节主要是实现数据库表一对多之间的映射关系。首先,我们需要创建一个Blogs表和一个Posts表,一个Blogs表中可以有多个文章(Posts),典型的一对多的关系:

    Blogs表:

    CREATE TABLE [dbo].[Blogs](
    [blog_id] [int] IDENTITY(1,1) NOT NULL,
    [blog_name] [varchar](50) NULL,
    [blog_author] [varchar](50) NULL,
    CONSTRAINT [PK_Blogs] PRIMARY KEY CLUSTERED
    (
    [blog_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    Posts表:

    CREATE TABLE [dbo].[Posts](
    [post_id] [int] IDENTITY(1,1) NOT NULL,
    [post_title] [varchar](50) NULL,
    [post_contents] [text] NULL,
    [post_categories] [varchar](50) NULL,
    [post_blogid] [int] NULL,
    [post_created] [datetime] NULL,
    [post_published] [bit] NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY CLUSTERED
    (
    [post_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    GO

    然后根据前面几章的学习,很轻松的就能够创建Blog和Post操作类:

    Blog类如下:

    using Castle.ActiveRecord;
    using System.Collections;
    using NHibernate.Mapping;

    namespace CastleLib
    {
    [ActiveRecord("Blogs")]
    public class Blog:ActiveRecordBase
    {
    private int _id;
    private string _name;
    private string _author;
    private IList _posts;

    [PrimaryKey(PrimaryKeyType.Native,"blog_id")]
    public int ID
    {
    get { return _id; }
    set { _id = value; }
    }

    [Property("blog_name")]
    public string Name
    {
    get { return _name; }
    set { _name = value; }
    }

    [Property("blog_author")]
    public string Author
    {
    get { return _author; }
    set { _author = value; }
    }

    //需要注意的是,这里指定了Blogs表和Posts表之间的对应关系,二者之间是通过post_blogid来进行对应的
    //并且通过HasMany指定Blogs为主表,可以有多个Posts
    [HasMany(typeof(Post),Table="Posts",ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
    public IList Posts
    {
    get { return _posts; }
    set { _posts = value; }
    }

    public static void DeleteAll()
    {
    DeleteAll(typeof(Blog));
    }

    public static Blog[] FindAll()
    {
    return (Blog[])FindAll(typeof(Blog));
    }

    public static Blog Find(int id)
    {
    return (Blog)FindByPrimaryKey(typeof(Blog), id);
    }
    }
    }

    Post类如下:

    using System;
    using Castle.ActiveRecord;

    namespace CastleLib
    {
    [ActiveRecord("Posts")]
    public class Post:ActiveRecordBase
    {
    private int _id;

    private string _title;

    private string _content;

    private string _category;

    private DateTime _created;

    private bool _published;

    private Blog _blog;

    [PrimaryKey(PrimaryKeyType.Native,"post_id")]
    public int ID
    {
    get { return _id; }
    set { _id = value; }
    }

    [Property("post_title")]
    public string Title
    {
    get { return _title; }
    set { _title = value; }
    }

    [Property(Column="post_contents",ColumnType="StringClob")]
    public string Contents
    {
    get { return _content; }
    set { _content = value; }
    }

    [Property("post_categories")]
    public string Category
    {
    get { return _category; }
    set { _category = value; }
    }

    //注意,这里主要是用来指明Posts和Blogs表之间的对应关系,即Posts表属于Blogs,并且通过post_blogid关联
    [BelongsTo("post_blogid")]
    public Blog Blog
    {
    get { return _blog; }
    set { _blog = value; }
    }

    [Property("post_created")]
    public DateTime Created
    {
    get { return _created; }
    set { _created = value; }
    }

    [Property("post_published")]
    public bool Published
    {
    get { return _published; }
    set { _published = value; }
    }

    public static void DeleteAll()
    {
    DeleteAll(typeof(Post));
    }

    public static Post[] FindAll()
    {
    return (Post[])FindAll(typeof(Post));
    }

    public static Post FindByPrimaryKey(int id)
    {
    return (Post)FindByPrimaryKey(typeof(Post),id);
    }

    }
    }

    下面就来测试,这里我们需要一个Init()函数来初始化Post和Blog类,当然是需要加入到ActiveRecord容器中进行初始化。

    下面具体看代码,需要注意的是,在我的测试过程中,出现过两次错误,这两次错误也是很多人在初次使用ActiveRecord的时候容易犯的:

     //You have accessed an ActiveRecord class that wasn't properly initialized. 
    //The only explanation is that the call to ActiveRecordStarter.Initialize() didn't include

    出现这个错误是你没有进行初始化。

    //Could not perform Save for Post

    出现这个的最可能原因是你的数据格式化不对,我这里主要是试图往DateTime类型中插入超出范围的日期导致出错。

    具体见代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Castle.ActiveRecord.Framework.Config;
    using Castle.ActiveRecord;
    using CastleLib;

    namespace CastleAPP
    {
    public partial class OneMany : Form
    {
    public OneMany()
    {
    InitializeComponent();
    //记住,如果Init()函数没有调用的话,会出现:
    //You have accessed an ActiveRecord class that wasn't properly initialized.
    //The only explanation is that the call to ActiveRecordStarter.Initialize() didn't include
    Init();
    }

    private void Init()
    {
    InPlaceConfigurationSource source = new InPlaceConfigurationSource();
    IDictionary<string, string> properties = new Dictionary<string, string>();
    properties.Add("connection.driver_class", "NHibernate.Driver.SqlClientDriver");
    properties.Add("dialect", "NHibernate.Dialect.MsSql2008Dialect");
    properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
    properties.Add("proxyfactory.factory_class", "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
    properties.Add("connection.connection_string", "UID=sa;Password=251147;Initial Catalog=CastleBase;Data Source=.;");
    source.Add(typeof(ActiveRecordBase), properties);
    ActiveRecordStarter.Initialize(source, typeof(Post),typeof(Blog));
    }

    private void OneMany_Load(object sender, EventArgs e)
    {

    }

    ///<summary>
    /// 执行事务,持久化对象到数据库
    ///</summary>
    public void TestCascadingSave()
    {
    //创建Blog对象
    Blog blog = new Blog();
    blog.Name = "程序诗人的博客空间";
    blog.Author = "程序诗人";

    //执行事务,持久化对象到数据库

    using (TransactionScope tran = new TransactionScope())
    {
    using (new SessionScope());
    try
    {
    blog.Create();
    for (int i = 0; i < 11; i++)
    {
    Post post = new Post();
    post.Title = "这是我的第"+i+"篇文章";
    post.Category = "Castle Learn";
    post.Created = DateTime.Now; //要给时间赋值,否则会出现Could not perform Save for Post的错误
    post.Blog = blog;
    post.Save(); //这个地方将文章保存到session中
    }
    tran.VoteCommit(); //统一提交到数据库中
    }
    catch
    {
    tran.VoteRollBack();
    }
    }
    }

    ///<summary>
    /// 级联更新
    ///</summary>
    public void TestCascadingUpdate()
    {
    Blog blog = Blog.Find(5);
    using (TransactionScope tran = new TransactionScope())
    {
    try
    {
    for (int i = 0; i < 5; i++)
    {
    Post post = new Post();
    post.Title = "哈哈哈,这是第"+i+"次写文章了。";
    post.Category = "杂记";
    post.Created = DateTime.Now;
    post.Save();
    //blog.Posts.Add(post);
    //准确的来讲,这两句话作用相同
    post.Blog = blog;
    }
    blog.Update();
    tran.VoteCommit();
    }
    catch
    {
    tran.VoteRollBack();
    }
    }
    }

    private void button1_Click(object sender, EventArgs e)
    {
    TestCascadingSave();
    }

    private void button2_Click(object sender, EventArgs e)
    {
    TestCascadingUpdate();
    }
    }
    }

    希望有用,谢谢。






     

  • 相关阅读:
    cve-2019-1388复现+烂土豆+CVE-2019-0803
    子父域控双向信任
    黄金票据 白银票据 ms14068
    joomla3.4.6 rce 分析与复现
    主键索引跟唯一索引的区别
    hash 跟B+tree的区别
    MySQL数据库有几种索引?分别是什么?
    什么是事务?事务有什么特性?分别是什么?
    MySQL建立索引的原则
    什么是索引?索引的作用是什么?
  • 原文地址:https://www.cnblogs.com/scy251147/p/2225863.html
Copyright © 2020-2023  润新知