博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[项目过程中所遇到的各种问题记录]ORM篇——使用NHibernate配置对象实体的一些小问题...
阅读量:6617 次
发布时间:2019-06-24

本文共 4523 字,大约阅读时间需要 15 分钟。

    继续问题记录,前段时间公司有新的项目所以我想在新的项目里使用NHibernate这类ORM框架来代替原有的代码生成的拼SQL,不过可惜的是最终使用NHibernate还是没成功,最终还是继续使用已有的代码生成方式。

       NHibernate在去年的这个时候也研究过,可后来也搁浅了,今年的这个时候研究了结果有搁浅了,不知道是不是犯冲?不过还是把遇到的问题记录下来吧,以备后患。

 

配置实体的一些小问题

      下面就开始记录下我碰到的问题吧,其实都是自己没看资料而导致的问题,稍微熟悉NHibernate的朋友都应该知道的。

1、hbm文件的格式检查

     这个问题是最弱智的,由于我在手写映射文件的时候没有将NHibernate的XSD文件放到VS相关目录下(X:\Program Files\Microsoft Visual Studio X.0\Xml\Schemas),而直接根据数据库关系手写了相应的映射文件,结果导致程序一再运行报错(由于NHibernate在运行的时候会将所有的映射文件格式是否正确进行检查),导致不得不反工。

 

2、延迟加载与直接加载引发的问题

    在实际配置映射文件的过程中,我采用的配置方式与Linq2Sql类似,主要的规则就是:

1)如果此表为主键表,其他表中与此表,则在映射文件中添加<bag>集合,同时在实体代码中添加集合对象

配置代码如下:

1
2
3
4
<
bag 
name="StudentList" table="Student">
  
<
key 
column="ID" />
  
<
one-to-many 
class="Model.Student, Model"/>
</
bag
>

实体代码如下:

1
2
3
4
5
6
7
8
9
10
private 
IList<Student> _studentList =
new 
List<Student>();
 
/// <summary>
/// 子集:ID
/// </summary>
public 
virtual 
IList<Student> StudentList
{
    
get 
{
return 
_studentList; }
    
set 
{ _studentList = value; }
}

2)如果此表存在外键关联,则在映射文件中添加<many-to-one>多对一映射,同时在实体代码中添加实体属性

配置代码如下:

1
2
3
<
many-to-one 
name="Class" class="Model.ClassInfo, Model">
  
<
column 
name="ClassId" length="4" sql-type="int" not-null="false" />
</
many-to-one
>

实体代码如下:

1
2
3
4
5
6
7
8
9
10
private 
ClassInfo _class;
 
/// <summary>
/// 外键:ClassId
/// </summary>
public 
virtual 
ClassInfo Class
{
    
get 
{
return 
_class; }
    
set 
{ _class = value; }    
}

具体数据库关系图如下:

如果是正常访问类本身属性是没什么问题,但是如果访问上面配置外键Class属性或者StudentList集合属性就会出现下面的异常:

其原因就是延迟加载导致,由于默认情况下NHibernate对于外键这类数据是采用延迟加载的,而我的查询方式是采用如下代码:

1
2
3
4
5
6
7
8
9
public 
virtual 
IList<T> GetList()
{
    
using 
(_session = NHibernateHelper.GetCurrentSession())
    
{
        
IList<T> list = (
from 
item
in 
_session.Query<T>()
                         
select 
item).ToList<T>();
        
return 
list;
    
}
}

可以看到代码中,我采用using方式将_session在读取完数据后释放了,而此时外键数据,这个时候并没有加载上去,所以,当我需要访问外键数据的时候,NHibernate会再次查询数据库,而此时的_session已经被关闭了,所以就导致了上面的异常。

如果想解决这个问题有2个办法:

1)才用直接加载,在配置的时候为<bag>或<many-to-one>配置上增加lazy=”false”属性,表示不采用延迟加载

2)修改查询代码,不将_session给关闭掉,如下代码:

1
2
3
4
5
6
7
8
9
public 
virtual 
IList<T> GetList()
{
    
_session = NHibernateHelper.GetCurrentSession();
     
    
IList<T> list = (
from 
item
in 
_session.Query<T>()
                        
select 
item).ToList<T>();
    
return 
list;
     
}

其实这个问题在(李永京)的NHibernate系列中已经写明了:和。

 

3、复合主键的问题

     在实际的数据库表设计中经常会出现复合主键的设计,比如:通过一张关联表来实现2张表之间的多对多关系,如下图:

根据我上面列出的规则,我的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<
hibernate-mapping 
xmlns="urn:nhibernate-mapping-2.2">
  
<
class 
name="Model.SubjectAndStudent, Model" table="SubjectAndStudent">
 
    
<
composite-id
>
      
<
key-property 
name="SubjectId" type="int">
        
<
column 
name="SubjectId" length="4" sql-type="int" not-null="false" />
      
</
key-property
>
      
<
key-property 
name="StudentId" type="int">
        
<
column 
name="StudentId" length="4" sql-type="int" not-null="false"/>
      
</
key-property
>
    
</
composite-id
>
    
<
many-to-one 
name="Subject"  class="Model.Subject, Model">
      
<
column 
name="SubjectId" length="4" sql-type="int" not-null="false" />
    
</
many-to-one
>
    
<
many-to-one 
name="Student"  class="Model.Student, Model">
      
<
column 
name="StudentId" length="4" sql-type="int" not-null="false" />
    
</
many-to-one
>
  
</
class
>
</
hibernate-mapping
>

实体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public 
class 
SubjectAndStudent
{
 
    
public 
virtual 
int 
SubjectId {
get
;
set
; }
 
    
public 
virtual 
int 
StudentId {
get
;
set
; }
 
    
public 
virtual 
Subject Subject {
get
;
set
; }
 
    
public 
virtual 
Student Student {
get
;
set
; }
 
    
#region override
    
public 
override 
bool 
Equals(
object 
obj)
    
{
        
return 
base
.Equals(obj);
    
}
    
public 
override 
int 
GetHashCode()
    
{
        
return 
base
.GetHashCode();
    
}
    
#endregion
 
}

这边需要注意的是,采用复合主键映射,在编写实体类的时候,需要重载Equals和GetHashCode方法,否则会报错。

正常来看,这个映射和实体代码的编写没什么问题,但是在实际的新增运行过程中出现了这个问题:

仔细查看了下映射文件才发现问题所在,就是在具体的配置映射关系的时候将SubjectId和StudentId配置了2次,而实际在表中,这2个字段都只有一个,找了下资料,解决办法还是有,想了解的朋友可以继续查看(李永京)的这篇文章,不过在李哥的文章中给出的解决方案我觉得有点繁琐,需要将复合主键单独建立一个类,然后重新编写映射关系和实体类。

后来在纠结了很久的情况下,无意中在VS中按空格查看<many-to-one>配置节下可用的属性的时候发现了2个属性insert和update,查了下资料后知道这2个属性是用于控制在新增和更新状态下是否映射,将其都置为false后,代码果然正常执行了,配置如下:

1
2
3
4
5
6
<
many-to-one 
name="Subject"  class="Model.Subject, Model" insert="false" update="false">
  
<
column 
name="SubjectId" length="4" sql-type="int" not-null="false" />
</
many-to-one
>
<
many-to-one 
name="Student"  class="Model.Student, Model" insert="false" update="false">
  
<
column 
name="StudentId" length="4" sql-type="int" not-null="false" />
</
many-to-one
>

 

话说,各位看过的朋友如果觉得本文对您还有点用,或者觉得本文还有价值的话,麻烦将鼠标移到【推荐】上,帮我点击下,非常非常的感谢!

 

项目过程中所遇到的各种问题记录

编辑器篇:

        

        

        

图表篇:

        

        

ORM篇:

        

        

部署篇:

        

        

工具篇:

        

本文转自kyo-yo博客园博客,原文链接:http://www.cnblogs.com/kyo-yo/archive/2010/12/22/Problem-Record-ORM-Some-Problem-Of-Configuration-With-NHibernate.html,如需转载请自行联系原作者

你可能感兴趣的文章
使用SQL Server Analysis Services数据挖掘的关联规则实现商品推荐功能(二)
查看>>
ubuntu下安装jdk
查看>>
XML学习总结(2)——XML简单介绍
查看>>
python操作数据库-安装
查看>>
你真的了解interface和内部类么
查看>>
kuangbin专题七 POJ3264 Balanced Lineup (线段树最大最小)
查看>>
JS动画效果链接汇总
查看>>
陈云川的OPENLDAP系列
查看>>
P1197 [JSOI2008]星球大战
查看>>
urllib模块
查看>>
XML转义字符
查看>>
mysql设置字符集CHARACTER SET
查看>>
Perl完全自学手册图文教程
查看>>
python(5)字典
查看>>
wordpress拿WebShell
查看>>
脚本结构和执行
查看>>
warden创建容器的过程
查看>>
【c++】size_t 和 size_type的区别
查看>>
15.2. switchport trunk encapsulation dot1q 提示 invaild input at^marker.
查看>>
getline函数(精华版)
查看>>