这两天看了Terrylee的ActiveRecord学习实践系列,使我对Castle的ActiveRecord有了一个初步的认识。今天先把实践中遇到的一些小问题作个记录,便于日后总结、修正。
最初遇到的一个问题就是:在做Many-Many关系映射,用实体类生成数据表的时候出现异常,如下:
************** Exception Text **************
Castle.ActiveRecord.Framework.ActiveRecordException: Could not create the schema
---> NHibernate.HibernateException: Column names in each table must be unique. Column name 'blog_id' in table 'Blog_Community' is specified more than once.
---> System.Data.SqlClient.SqlException: Column names in each table must be unique. Column name 'blog_id' in table 'Blog_Community' is specified more than once.
...
实体类设计如下:
[ActiveRecord("Blogs")] public class Blog : ActiveRecordBase<Blog> { private int _id; private String _name; private String _author; [PrimaryKey(PrimaryKeyType.Native, "blog_id")] public int Id { get { return _id; } set { _id = value; } } [Property("blog_name", NotNull = true)] public String Name { get { return _name; } set { _name = value; } } [Property("blog_author", NotNull = true)] public String Author { get { return _author; } set { _author = value; } } private IList _posts; [HasMany(typeof(Post), Table = "Posts", ColumnKey = "post_blogid")] public IList Posts { get { return _posts; } set { _posts = value; } } private IList _community; [HasAndBelongsToMany(typeof(Community), Table = "Blog_Community", ColumnRef = "community_id", ColumnKey = "blog_id ")] public IList Communities { get { return _community; } set { _community = value; } } } [ActiveRecord("Posts")] public class Post : ActiveRecordBase<Post> { private int _id; private String _title; private String _contents; private String _category; private DateTime _created; private bool _published; private Blog _blog; public Post() { _created = DateTime.Now; } public Post(Blog blog, String title, String contents, String category) : this() { _blog = blog; _title = title; _contents = contents; _category = category; } [PrimaryKey(PrimaryKeyType.Native, "post_id")] public int Id { get { return _id; } set { _id = value; } } [Property("post_title", NotNull = true)] public String Title { get { return _title; } set { _title = value; } } [Property(Column = "post_contents", ColumnType = "StringClob")] public String Contents { get { return _contents; } set { _contents = value; } } [Property("post_categories")] public String Category { get { return _category; } set { _category = value; } } [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; } } } [ActiveRecord("Communities")] public class Community : ActiveRecordBase<Community> { private int _id; private String _name; private String _intro; [PrimaryKey(PrimaryKeyType.Native, "community_id")] public int Id { get { return _id; } set { _id = value; } } [Property("community_name", NotNull = true)] public String Name { get { return _name; } set { _name = value; } } [Property("community_intro")] public String Intro { get { return _intro; } set { _intro = value; } } private IList _blog; [HasAndBelongsToMany(typeof(Blog), Table = "Blog_Community", ColumnRef = "blog_id", ColumnKey = "community_id")] public IList Blogs { get { return _blog; } set { _blog = value; } } }
当时以为是Many–Many的映射在正向生成数据表时,由于成对出现的HasAndBelongsToMany属性,导致重复创建Blog_Community表的列(blog_id,community_id)而导致以上错误。虽然这个问题应该是不会出现的,但实在没找出具体原因,也只能暂且认为是AR本身的问题了 -_-! 于是乎就跳过它,接着搞。
在做过另一些实验后,回过头来突然发现Many–Many的映射在正向生成数据表时又执行成功了.... 一阵莫名其妙&*%^*%^$ 仔细地对照了前后的代码,发现原因出在空格符上(实体类代码中红色背景部分)。
在Sql里不区分大小写,一般的空格符也会被忽略掉,例如这个小例子:
create table T_tmp (t_id int, t_name varchar(25))
alter table T_tmp add t_id int --报错 (这里的 t_id前有个空格)
错误信息:
Msg 2705, Level 16, State 4, Line 2
Column names in each table must be unique. Column name 'id' in table 'T_tmp' is specified more than once.
create table [ T_tmp](t_id int) --成功创建了表 T_tmp
select * from T_tmp
select * from [ T_tmp]
回到C#里,C#是区分大小写的,而且"blog_id "(右边有空格)和"blog_id"是不同的。所以在生成数据表时,应该就会去创建"blog_id "和"blog_id"两个字段,而到数据库中则认为这两个列名是相同的,异常就这样产生了。同理大小写的不同也会造成以上错误。
看来学习还是严谨点好,尤其是在一些细节上。又一次教训!
另外发现AR里ActiveRecordBase挺好用的,它已经为我们重写了基础的静态方法,如Find(),TryFind(),DeleteAll(),FindAll()。这样不仅减少了我们的代码量,也保证了类型安全。要提一下的是,其中Find()在没有找到符合的结果时会抛出"Castle.ActiveRecord.NotFoundException"类型的异常。如果不希望抛出异常则可以使用TryFind(),它只返回null值。
留下几个待进一步实践学习的东西
1. 关于延时加载 lazy
2. 有继承关系的类怎样较好地转化为AR的实体类
最后,感谢Terrylee以及许多无私奉献的前辈们!
文章来源:http://www.agilelabs.cn/blogs/%e8%8c%83%e4%bf%8a/archive/2006/05/14/1211.aspx
转载于:https://www.cnblogs.com/debug1/archive/2006/05/14/413758.html