Problem record, previous time the company has a new project so I would like to use the NHibernate type ORM framework in the new project instead of the original code-generated SQL, but unfortunately the end use of NHibernate is still unsuccessful, eventually continue to use the existing code generation method.
NHibernate at this time last year also studied, but later also stranded, this time this year to study the results have been stranded, do not know is not committed to Chong? But keep a record of the problems you have encountered, for the future.
Some small issues with configuring entities
The following began to record the problems I encountered, in fact, they did not read the information caused by the problem, a little familiar with NHibernate's friends should know.
1, the HBM file format check
This problem is the most mentally retarded, because I did not put the nhibernate XSD file in the VS related directory (X:\Program Files\Microsoft Visual Studio X.0\xml\schemas) When I was in the handwriting mapping file. and directly according to the database relationship handwritten mapping files, resulting in the program repeatedly run an error ( because the nhibernate in the runtime will be all the mapping file format is checked correctly ), resulting in the anti-worker.
2. Problems caused by delayed loading and direct loading
In the process of actually configuring the mapping file, I used the same configuration as Linq2sql, the main rule is:
1) If this table is the primary key table in the other table, add the <bag> collection to the mapping file and add the collection object to the entity code
The configuration code is as follows:
1234 |
< bag name="StudentList" table="Student"> < key column="ID" /> < one-to-many class="Model.Student, Model"/> </ bag > |
The entity code is as follows:
12345678910 |
private
IList<Student> _studentList =
new
List<Student>();
/// <summary>
/// 子集:ID
/// </summary>
public
virtual
IList<Student> StudentList
{
get
{
return
_studentList; }
set
{ _studentList = value; }
}
|
2) If the table has a foreign key association, add <many-to-one> Many-to-one mappings in the mapping file and add entity attributes to the entity code
The configuration code is as follows:
123 |
< many-to-one name="Class" class="Model.ClassInfo, Model"> < column name="ClassId" length="4" sql-type="int" not-null="false" /> </ many-to-one > |
The entity code is as follows:
12345678910 |
private classinfo _class; ///<summary> ///foreign key: ClassId Code class= "CSharp color1" >///</summary> public virtual classinfo class { &NBSP;&NBSP;&NBSP;&NBSP; get { return _class;} &NBSP;&NBSP;&NBSP;&NBSP; set {_class = value;} |
The specific database diagram is as follows:
If it is normal to access the property of the class itself is not a problem, but if the access above to configure the foreign key class property or Studentlist collection properties, the following exception appears:
The reason for this is that lazy loading is caused by the fact that, by default, NHibernate is lazy-loaded for foreign key data, and my query is based on the following code:
123456789 |
public
virtual
IList<T> GetList()
{
using
(_session = NHibernateHelper.GetCurrentSession())
{
IList<T> list = (
from
item
in
_session.Query<T>()
select
item).ToList<T>();
return
list;
}
}
|
Can see the code, I use the way to _session after reading the data released, and the foreign key data, this time and did not load up, so, when I need to access the foreign key data, NHibernate will query the database again, and at this time _ The session has been closed, so it causes the above exception.
There are 2 ways to solve this problem:
1) to add the lazy= "false" property to the <bag> or <many-to-one> configuration at the time of configuration, indicating that no lazy loading is used
2) Modify the query code, do not _session to shut down, the following code:
123456789 |
public
virtual
IList<T> GetList()
{
_session = NHibernateHelper.GetCurrentSession();
IList<T> list = (
from
item
in
_session.Query<T>()
select
item).ToList<T>();
return list;
}
|
In fact, this problem has been stated in the NHibernate series of the Mfullyaware (Li Yongjing): A preliminary study of the delay loading mechanism and the immediate loading mechanism.
3. Problems with Composite primary keys
In the actual database table design, there will often be composite primary key design, such as: Through an association table to achieve the 2-table between the many-to-many relationships, such as:
According to the rules I have listed above, my configuration is as follows:
12345678910111213141516171819 |
<
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
>
|
The entity code is as follows:
1234567891011121314151617181920212223 |
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
}
|
It is important to note that with composite primary key mappings, when writing entity classes, you need to overload the Equals and GetHashCode methods, or else you will get an error.
Normally, this mapping and the writing of the entity code are fine, but this problem occurs during the actual new operation:
Carefully review the mapping file to find the problem, that is, in the specific configuration mapping relationship Subjectid and StudentID configured 2 times, and actually in the table, the 2 fields are only one , find the next information, the solution is still there, Friends who want to know can continue to view Mfullyaware (Li Yongjing) 's Federated primary Key (Composite-id) This article, but the solution given in Mfullyaware's article is a bit cumbersome, you need to create a separate class for the composite primary key, and then rewrite the mapping relationships and entity classes.
Later in the tangle for a long time, inadvertently in the VS in the space to view <many-to-one> Configure the properties available under the section, found 2 properties insert and update, after checking the information to know that the 2 properties are used to control whether in the new and updated state mapping, When it is set to false, the code is executed as expected, and is configured as follows:
123456 |
<
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
>
|
Words, you have seen a friend if this article to you still a little use, or think this article also has the value, the trouble will move the mouse to "recommend" on, help me click, Very very thanks!
ORM--some small problems of using NHibernate to configure object entities