Recently in the project to use the NHibernate, use it is not difficult, but very troublesome. If I have hundreds of tables in my database it would be cumbersome to use nhibernate in this case, although the ORM framework itself is powerful, but it is too cumbersome to be heavyweight in use, so it needs to be improved in the project. This is the fluentnhibernate, it is a smooth version of the NHibernate, support all the nhibernate functions, but also encapsulates the mapping function of the configuration file, that is, you can use the C # code to write, so it will be easy to maintain.
In the absence of fluentnhibernate, if you use NHibernate to do database mapping, Then you first need to install NHibernate (that is, apply Nhibernate.dll), then create the Nhibernate.cfg.xml database configuration file, and then create the mapping file. XML, and finally create the session, directly to the object operation. Although this is not difficult, but very troublesome, imagine if the database table has hundreds of, the use of this method mapping is not very cumbersome, cumbersome.
So what is the benefit of fluentnhibernate, which can omit the creation of the mapping file. XML, which uses C # code to write a mapping file, simplifies the workload in some cases, and makes it easier to modify the mapping code, which is discussed in detail in the next steps.
First, create a database configuration file
First create a database configuration file, just start to use the word manual writing too cumbersome, this time can consider the use of the configuration file, in the official website after the download will have a folder named Configuration_templates, there are different database configuration files, You can use its default settings, but you will need to change the name to Nhibernate.cfg.xml. The following configuration is used here:
<?xml version= "1.0" encoding= "Utf-8"?><!--This was the System.Data.dll provider for SQL Server-->
Ii. creation of entities
NHibernate Basic mapping and hibernate is exactly the same, about the basic mapping is no longer discussed in detail here, you can read the author's previous articles. Below I did a small project demo, demonstrating how to use NHibernate to create a database mapping, the specific database structure diagram is as follows:
of the database structure diagram covers the basic mapping, in the actual project is also the above several basic relationships, which covers one-to-one, many-to-a, many-to-many relationship, the next will use Fluentnhibernate to achieve the basic mapping relationship.
2.1 Creating Entities
After you add the configuration file, use a third-party tool to export the database table as an entity object, which is the entity object that adds the database table. After adding the mapping class to continue adding the database, adding the mapping class requires inheriting the Classmap<t> class of NHibernate, placing the database entity inside the object so that it can be used directly at the time of mapping, which is implemented using generics. The entity of the database table is the following code:
Using system;using system.collections.generic;using system.collections.objectmodel;using System.Linq;using System.text;using system.threading.tasks;using fluentnhibernate.automapping;using FluentNHibernate.Conventions; Using nhibernate;using nhibernate.collection.generic;namespace classlibrary1.mapping{public abstract class Entity {Virtual public int ID {get; set;} } public class User:entity {virtual public string Name {get; set;} Public virtual string No {get; set;} Public virtual userdetails userdetails {get; set;} public class Project:entity {public Project () {task=new list<task> (); Product=new list<product> (); } public virtual string Name {get; set;} Public virtual user User {get; set;} Public virtual ilist<product> Product {get; set;} Public virtual ilist<task> task{get;protected set;} } public classproduct:entity {public Product () {project=new list<project> (); Public virtual ilist<project> Project {get; set;} Public virtual string Name {get; set;} Public virtual string Color {get; set;} } public class Task:entity {public virtual string Name {get; set;} Public virtual Project Project {get; set;} } public class Userdetails:entity {public virtual user user {get; set;} public virtual int Sex {get; set;} public virtual int Age {get; set;} Public virtual DateTime BirthDate {get; set;} Public virtual decimal Height {get; set;} }}
third, mapping detailed
When you add a mapping file, you need to inherit the Classmap<t> class of Fluentnhibernate, and then add the mapped method to the class's constructor, using the Lamuda expression to map it, and the name of the method is basically the same as the name of the configuration file. Writing is also handy, and the next step is to split the map to explain the mapping usage of fluentnhibernate in detail.
3.1 One-to-one mapping
First of all to look at a one-to-one mapping relationship, the user and User information table in the actual relationship between the two tables are related by using the UserID, they have a common ID, when inserting the users table also to write the Userdetails table, So you need to add a one-to-one limit relationship, specifically in the users and usersdetails two table mapping method is as follows code:
public class usersmapping:classmap<user>{public usersmapping () { Table ("Users"); Lazyload (); Id (x = x.id). Column ("UserID"). Generatedby.identity (); HasOne (x = x.userdetails). Cascade.all (). PropertyRef ("User"); Map (x = x.name). Nullable (); Map (x = x.no). Nullable (); }}
Note:fluentnhibernate has many mapping methods, such as Cascade, which refers to the action type of the child object that the object is associated to when it is being manipulated, specifying that all indicates that all operations are associated to the child table. There are also saveupdate associated with child tables when adding and updating, and the none type is not recommended because there are many problems.
The primary key ID in the userdetails mapping is inherited from the user class, so you need to add the property name of the Foreign Foreign Key Association when specifying the ID, and the internal parameter must be the Userdetails property name.
public class userdetailsmapping:classmap<userdetails>{public userdetailsmapping () { Table (" Userdetails "); Lazyload (); Id (x = x.id). Column ("UserID"). Generatedby.foreign ("User"); Map (x = x.height). Nullable (); Map (x = x.age). Nullable (); Map (x = x.sex). Nullable (); Map (x = x.birthdate). Nullable (); HasOne (x = x.user). Cascade.all (); }}
Use the test method to view the results of the mapping, with the following test methods:
Using system;using system.collections.generic;using classlibrary1.mapping;using fluentnhibernate.testing;using classlibrary1;using nhibernate;using nunit.framework;namespace unittestproject1{[TestFixture] public class UnitTest 1:nhconfig {[Test] public void Testusers_userdetails () {//get user from database User user1 = session.load<user> (1); Save the User data Session.Transaction.Begin (); User User=new User () {Name = "Jack", No = "12321"}; Userdetails userdetails=new Userdetails () {age = all, BirthDate = DateTime.Now.Da Te, Height = +, Sex = 1}; User. Userdetails = userdetails; Userdetails.user = User; Session.save (user); Session.Transaction.Commit (); } }}
Add a breakpoint where the get and save objects are, and debug runs the test to see the result of the execution.
3.2 One-to-many/multi-pair
A one-to-many and many-to-one is relatively similar to projects and tasks in the previous example, a projects has multiple tasks, and conversely, multiple tasks may correspond to a projects so sometimes a one-to-many relationship is a one-to-many relationship, It's just a special many-to-one. Here are many to a more special, common many-to-one relationship such as the relationship between students and classes, multiple students belong to a class.
A one-to-many mapping method and one-on-one mapping method in fact many places are similar, but a pair of relationships inside to add a foreign key reference relationship, and then add a foreign key at the end of the many, add Hasmany, mapping to projects and tasks is the addition of project's foreign keys in Tasks (many).
3.2.1 MappingThe first time the Tasks table is mapped, because the tasks table is more than one end, so to add a foreign key reference to the projects table, and because it is a foreign key reference is not related to the operation of the parent table, so you can use Cascade.none ().
public class tasksmappping:classmap<classlibrary1.mapping.task>{public tasksmappping () { Table ("Tasks"); Lazyload (); Id (x = x.id). Column ("TaskID"). Generatedby.identity (); References (x = x.project). Nullable (). Column ("ProjectID"). Cascade.none (); Map (x = x.name). Nullable (); }}
In the Projects table, because an ID in the table corresponds to more than one task, in addition to the Hasmany method to indicate a many-to-one relationship between projects and tasks, the following code involves adding and updating tasks, So you need to use Cascade.saveupdate ().
public class projectsmapping:classmap<project>{public projectsmapping () { Table ("Projects"); Lazyload (); Id (x = x.id). Column ("ProjectID"). Generatedby.identity (); References (x = x.user). Column ("UserID"). Cascade.none (); Map (x = x.name). Nullable (); Hasmany (x = x.task). KeyColumn ("ProjectID"). Lazyload (). Cascade.saveupdate (); }}
The foreign key relationship in Note:tasksmapping uses cascade.none, which means that it does not involve projects operations, but Cascade.saveupdate () is used in projectsmapping. Method so you can change tasks with the Save or update projects.
3.2.2 Unit TestWrite the unit test code as follows:
[test]public void Testonetomany () { Project project = session.get<project> (); Save the User Data Session.Transaction.Begin (); Task task = new Task () { Name = "Create", project = Project }; Session.save (Task); Session.Transaction.Commit (); Task Task1 = session.get<task> (1);}
To perform the view results:
The use of a one-to-many association is only a unidirectional association, in the association is not only a one-way and two-way association, the specific use of the method is no longer discussed here, interested in learning can be read the author's previous article about hibernate related relations.
3.3-to-many
The first-to-one and many-to-many relationships are discussed in detail, and it is simple to use fluentnhibernate to map this relationship, and finally continue to discuss many-to-many relationships, where many-to-many relationships are more similar to one-to-a-one relationships because they belong to a two-way association, Therefore, it is necessary to add the Hasmanytomany mapping method at both ends of the association, in addition to the database, this is actually necessary to establish an association table, using the third table to maintain a two-way relationship, the specific use of the following examples.
3.3.1 MappingMany-to-many relationships are common in the project, such as the relationship between product and project used in this example, when a project has a lot of product, and one product may be in more than one project, and there is a many-to-many association between them. reflected in the mapping relationship, the code is as follows:
public class projectsmapping:classmap<project>{Public projectsmapping () {Table ("Projects"); Lazyload (); Id (x = x.id). Column ("ProjectID"). Generatedby.identity (); References (x = x.user). Column ("UserID"). Cascade.none (); Map (x = x.name). Nullable (); Hasmany (x = x.task). KeyColumn ("ProjectID"). Lazyload (). Cascade.saveupdate (); Hasmanytomany (x = x.product). ParentKeyColumn ("ProjectID"). Childkeycolumn ("ProductID"). Table ("Projectproduct"); }}public class productmapping:classmap<product>{Public productmapping () {Table ("Product"); Id (x = x.id). Column ("ProductID"). Generatedby.identity (); Map (x = x.name). Nullable (); Map (x = x.color). Nullable (); Hasmanytomany (x = x.project). ParentKeyColumn ("ProductID"). Childkeycolumn ("ProjectID"). Table ("Projectproduct"); }}
The steps to add a specific association are as follows:
(1) Adding hasmanytomany relationships at both ends of the map to form a two-way correlation
(2) specifies the Parentkey and childkey of the map, which typically specifies the ID of the object itself as Parentkey, and the ID of the associated object is specified as Childkey
(3) Specify the relational table for the association relationship, using the table method to specify the associated table, such as table ("Projectproduct") on the example above.
3.3.2 Unit TestFinally add a test method to see the results of the map, whether the implementation of many-to-many mapping relationship, the specific test method is as follows.
[test]public void Testmanytomany () { Session.Transaction.Begin (); Get the Project icriteria query = session.createcriteria<project> (); ilist<project> projects = Query. List<project> (); Create the product Product Product=new product () { Name = "Product1", Color = "Red" }; Product. Project = projects; Session.save (product); Session.Transaction.Commit ();}
Debug runs the test method and runs to get projects to view the object information obtained by projects such as:
It can be seen that the product associated with projects has been acquired, which is a many-to-many relationship that acquires the products associated with it when acquiring projects, and if Lazyload is used here, it will not get all the information. So it depends on the specific situation.
Continue to run the test and execute successfully.
View database discovery Data has been successfully added, such as:
Conclusion
This paper mainly discusses the basic usage skills of fluentnhibernate, and discusses the two-way association mapping, one-to-many unidirectional association and many-to-many bidirectional association relationships, which are fairly simple to use because of the fluentnhibernate, You just need to know the rules of the association, and from the data model to the object model it's really easy.
Although the use of fluentnhibernate to some extent to reduce the writing code, but does not really solve the tedious problem of code redundancy, can there be no need to write mapping code to implement mapping relationships? Yes, Fluentnhibernate also encapsulates a automapping way to map objects, is an automatic mapping method, only to inherit the implementation of database table-to-object conversion rules can be, the specific implementation of the method will be discussed in detail in the next article.
The basic mapping of the--fluentnhibernate of "The Path of Architecture"