【ORM】--FluentNHibernate之AutoMapping详解
在项目中如果使用了AutoMapping那么它的具体的架构图如下
上面的架构图使用了AutoMapping,它的使用能够避免繁杂的Mapping文件的编写,也就是说NHibernate在访问数据库时首先要从FluentNHibernate那里获取对象和数据是如何相互转化的,然后FluentNHibernate会从AutoMapping中获取各种映射的规则,也就是说AutoMapping只需要重写对象模型的映射规则就可以实现完全的映射,这样就使得程序的开发变得相当简单。
一、AutoMapping
上文使用架构图对FluentNHibernate的AutoMapping做了初步的解读,可以看出AutoMapping是依附于FluentNHibernate的,而且FluentNHibernate是依附于NHibernate的,它们三者首先是NHibernate先工作,查找到FluentNHibernate,然后是FluentNHibernate查找到AutoMapping的规则,按照规则进行映射。
往往在开发时我们都会把Mapping和Models放到Core的程序集内,供其它层的程序集调用,如上图的Repository层,是对数据库做的一系列操作,都封装到该层中。
1.1 AutoMapping详解
在没有AutoMapping情况下如果使用FluentNHibernate来实现映射的话,首先要创建Mapping文件,然后对每个Entity都做Mapping代码的编写,但是这样就太麻烦了,因为如果有很多表的话一个个的编写Mapping很浪费时间,同时也会产生很多冗余的Code,所以这时候可以考虑使用AutoMapping来映射文件,只不过需要按照创建的规则来创建数据库的。
(1)创建AutoMapping的映射配置类,继承DefaultAutomappingConfiguration类,并重写ShouldMap方法,指定实体类所在的命名空间
(2)实现映射的接口,定义Entity到Table自动Mapping的规则,主要的接口如下:
IClassConvention,Entity Class到Table的映射,需要实现指定Table名称的Apply方法,默认情况下是以Entity的名称作为Table名称。
IIdConvention,Entity Class到Table ID的映射规则,需要实现指定Table ID生成的规则及ID的生成规则等,如果不实现该接口的话默认情况下会以“实体名_ID”形式命名Table的ID。
IReferenceConvention,Entity Class到Table的外键列映射规则,需要实现Apply方法,来指定外键列名称的生成规则及连接对象的加载规则,默认情况下会以“外键对象_ID”形式命名外键列。
IPropertyConvention,Entity Class属性到Table列名称的生成规则及加载规则,默认情况下会以属性名作为Table的列名。
IHasOneConvention,Entity Class一对一映射的规则及列的生成规则,需要实现Apply方法指定外键列的命名规则,同时也可以规定外键对象的加载和操作方式,默认情况下会以“对象_ID”形式命名。
IHasManyConvention,Entity Class一对多映射的规则及列的生成规则,需要实现Apply方法指定列的命名规则,同时也可以规定外键对象的加载和操作方式,默认情况下会以“对象_ID”形式命名。
IHasManyToManyConvention,Entity Class多对多映射的规则及列的生成规则,需要实现Apply方法指定关联表及关联表中列的命名规则,默认情况下会以“对象_ID”形式命名列名,“对象To对象”形式命名表名。
(3)编写Unit Test运行AutoMapping的配置文件,生成NHibernate的映射xml,查看映射是否成功。
Note:AutoMapping的映射过程会生成一些冗余表或者冗余列,如在多对多的映射过程中因为对象的两端都有另外一端对象的引用,所以在生成表结构时会同时生成两个关联表,但是在数据时只会使用到一个关联表。所以如果不是必要的情况不要使用AutoMapping来映射表结构,在一些特别小型的项目中可以考虑使用AutoMapping,大型的项目建议手动创建映射文件,这样可以手动的控制。
1.2 实例详解
上文对AutoMapping的使用过程做了详细的讨论,接下来我们将会创建一个代码实例来讨论AutoMapping的具体使用方法。
这里还以上文中的数据结构图为例来详细的讨论AutoMapping的使用方法,示例中使用的AutoMapping自动生成的数据库结构图如下:
上图是使用了AutoMapping来映射Entity后生成的数据库结构图,图中包括了一对一、一对多、多对多的关系,这些关系在生成的时候是按照1.1所说的映射规则实现的,具体的使用方法将会按照上文中所说的开发步骤来详细讨论。
1.2.1 创建AutoMapping的配置文件
在使用NHibernate做开发时首先要创建一个数据库的镜像Session,在使用FluentNHibernate也是如此,在使用时首先要创建一个数据库的Session对象,然后通过将对象转化为持久态来实现数据的操作。
AutoMapping的配置文件在创建Session时首先要创建AutoPersistenceModel对象,也就是将实体类所在的程序集/命名空间及Entity到Table的映射规则注册到 FluentNHibernate的AutoMapping中,具体的代码如下:
- /// <summary>
- /// 继承默认的AutoMapping配置类
- /// 重写ShouldMap方法指定映射Entity所在的命名空间
- /// </summary>
- public class StoreConfiguration : DefaultAutomappingConfiguration
- {
- public override bool ShouldMap(Type type)
- {
- return type.Namespace == "ClassLibrary1.mapping";
- }
- }
- /// <summary>
- /// 创建SessionFactory
- /// </summary>
- public class Build
- {
- private static AutoPersistenceModel CreateAutomappings()
- {
- //AutoMap.Assembly(Assembly.Load("ClassLibrary1"), new StoreConfiguration())
- //添加需要映射的程序集,在添加时可以使用默认的DefaultAutomappingConfiguration也可以继承该类重写ShouldMap方法来指定映射的命名空间
- return AutoMap
- .Assembly(Assembly.Load("ClassLibrary1"), new StoreConfiguration())
- //Conventions.Setup()方法是将映射的具体规则绑定到AutoMapping配置中,如下配置了:
- //DefualtTableNameConvertion默认表命名方式
- //DefaultPrimarykeyConvention默认主键命名方式
- //DefualtStringLengthConvertion默认的字符串长度
- //DefaultReferenceConvention默认的外键创建方法
- //DefaultHasManyConvention默认的一对多的创建方法
- //DefualtHasOneConvertion默认的一对一的创建方法
- //HasManyToManyConvention默认的多对多的创建方法
- .Conventions.Setup(con =>
- {
- con.Add<DefualtTableNameConvertion>();
- con.Add<DefaultPrimarykeyConvention>();
- con.Add<DefualtStringLengthConvertion>();
- con.Add<DefaultReferenceConvention>();
- con.Add<DefaultHasManyConvention>();
- con.Add<DefualtHasOneConvertion>();
- con.Add<HasManyToManyConvention>();
- });
- }
- public ISessionFactory CreateSessionFactory()
- {
- return Fluently
- .Configure() //创建或者指定数据库的配置xml,这里使用的是自动创建的方法
- //指定数据库的映射方法,其实它的底层使用的是反射来实现的映射
- .Database(
- MsSqlConfiguration
- .MsSql2005
- .ConnectionString(
- "Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60")
- //指定连接字符串
- .ShowSql()
- )
- //配置映射规则
- .Mappings(m => m.AutoMappings.Add(CreateAutomappings()) //将创建的AutoPersistenceModel对象添加到AutoMapping中
- .ExportTo("c:\\path") //导出映射文件
- )
- //生成数据库架构
- //new SchemaExport(cfg).Create(true, false)创建配置文件。
- //这里的Create方法是创建的脚本文件的映射方法,
- //第一个参数bool script指定是否生成数据库脚本
- //第二个参数bool export指定每次生成的数据库的创建脚本是否执行
- .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, false))
- .BuildSessionFactory();
- }
- }
/// <summary>
/// 继承默认的AutoMapping配置类
/// 重写ShouldMap方法指定映射Entity所在的命名空间
/// </summary>
public class StoreConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Namespace == "ClassLibrary1.mapping";
}
} /// <summary>
/// 创建SessionFactory
/// </summary>
public class Build
{ private static AutoPersistenceModel CreateAutomappings()
{
//AutoMap.Assembly(Assembly.Load("ClassLibrary1"), new StoreConfiguration())
//添加需要映射的程序集,在添加时可以使用默认的DefaultAutomappingConfiguration也可以继承该类重写ShouldMap方法来指定映射的命名空间
return AutoMap
.Assembly(Assembly.Load("ClassLibrary1"), new StoreConfiguration())
//Conventions.Setup()方法是将映射的具体规则绑定到AutoMapping配置中,如下配置了:
//DefualtTableNameConvertion默认表命名方式
//DefaultPrimarykeyConvention默认主键命名方式
//DefualtStringLengthConvertion默认的字符串长度
//DefaultReferenceConvention默认的外键创建方法
//DefaultHasManyConvention默认的一对多的创建方法
//DefualtHasOneConvertion默认的一对一的创建方法
//HasManyToManyConvention默认的多对多的创建方法
.Conventions.Setup(con =>
{
con.Add<DefualtTableNameConvertion>();
con.Add<DefaultPrimarykeyConvention>();
con.Add<DefualtStringLengthConvertion>();
con.Add<DefaultReferenceConvention>();
con.Add<DefaultHasManyConvention>();
con.Add<DefualtHasOneConvertion>();
con.Add<HasManyToManyConvention>();
});
} public ISessionFactory CreateSessionFactory()
{
return Fluently
.Configure() //创建或者指定数据库的配置xml,这里使用的是自动创建的方法
//指定数据库的映射方法,其实它的底层使用的是反射来实现的映射
.Database(
MsSqlConfiguration
.MsSql2005
.ConnectionString(
"Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60")
//指定连接字符串
.ShowSql()
)
//配置映射规则
.Mappings(m => m.AutoMappings.Add(CreateAutomappings()) //将创建的AutoPersistenceModel对象添加到AutoMapping中
.ExportTo("c:\\path") //导出映射文件
)
//生成数据库架构
//new SchemaExport(cfg).Create(true, false)创建配置文件。
//这里的Create方法是创建的脚本文件的映射方法,
//第一个参数bool script指定是否生成数据库脚本
//第二个参数bool export指定每次生成的数据库的创建脚本是否执行
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, false))
.BuildSessionFactory();
} }
有了上面的配置代码就可以实现AutoMapping规则了,但是往往我们的配置文件中需要实现映射的接口,通过实现这些接口来定义Entity和Table的相互映射的规则,实现这些接口后将这些类添加到SetUp到相应的AutoMapping中。
1.2.2 实现映射接口
添加好了AutoMapping的配置文件后基本上已经可以实现映射了,但是如果我们没有自定义映射规则的话将会以默认的方式生成相应的表结构,这些生成的表结构也可以通过实现接口来自定义这些规则,具体方法如下。
(1)IClassConvention
通过实现该接口来定义映射的Entity Class到Table的映射转换规则,如果不重写生成规则的话默认会以对象名作为表名。具体定义实现方法如下代码:
- public class DefualtTableNameConvertion : IClassConvention
- {
- /// <summary>
- /// 指定生成的表名或者表名到对象的映射
- /// </summary>
- /// <param name="instance">需要映射的Entity对象</param>
- public void Apply(FluentNHibernate.Conventions.Instances.IClassInstance instance)
- {
- //定义生成表名的规则,实体类名+s
- instance.Table(instance.EntityType.Name + "s");
- }
- }
public class DefualtTableNameConvertion : IClassConvention
{
/// <summary>
/// 指定生成的表名或者表名到对象的映射
/// </summary>
/// <param name="instance">需要映射的Entity对象</param>
public void Apply(FluentNHibernate.Conventions.Instances.IClassInstance instance)
{
//定义生成表名的规则,实体类名+s
instance.Table(instance.EntityType.Name + "s");
}
}
(2)IIdConvention
实现该接口来定义映射的Entity Class中的属性列到Table ID的映射规则,同时也可以指定ID的规则,默认情况下会以“实体名_ID”形式命名Table的ID。
- public class DefaultPrimarykeyConvention : IIdConvention
- {
- /// <summary>
- /// 指定Entity Class到Table ID的生成规则,及ID的规则
- /// </summary>
- /// <param name="instance">生成实体的对象</param>
- public void Apply(FluentNHibernate.Conventions.Instances.IIdentityInstance instance)
- {
- instance.Column(instance.EntityType.Name + "ID");
- instance.GeneratedBy.Native();
- }
- }
public class DefaultPrimarykeyConvention : IIdConvention
{
/// <summary>
/// 指定Entity Class到Table ID的生成规则,及ID的规则
/// </summary>
/// <param name="instance">生成实体的对象</param>
public void Apply(FluentNHibernate.Conventions.Instances.IIdentityInstance instance)
{
instance.Column(instance.EntityType.Name + "ID");
instance.GeneratedBy.Native();
}
}
(3)IReferenceConvention
实现该接口指定Entity Class到Table的外键列映射规则,默认情况下会以“外键对象_ID”形式命名外键列。
- public class DefaultReferenceConvention : IReferenceConvention
- {
- /// <summary>
- /// 指定对象外键的生成规则
- /// </summary>
- /// <param name="instance">外键对象</param>
- public void Apply(IManyToOneInstance instance)
- {
- instance.Column(instance.Name + "ID");
- instance.LazyLoad();
- }
- }
public class DefaultReferenceConvention : IReferenceConvention
{
/// <summary>
/// 指定对象外键的生成规则
/// </summary>
/// <param name="instance">外键对象</param>
public void Apply(IManyToOneInstance instance)
{
instance.Column(instance.Name + "ID");
instance.LazyLoad(); }
}
(4)IPropertyConvention
Entity Class属性到Table列名称的生成规则及加载规则,同时也可以定义数据库列类型的生成的规则,默认情况下会以属性名作为Table的列名。
- public class DefualtStringLengthConvertion : IPropertyConvention
- {
- /// <summary>
- /// 配置Table列的名称及类型
- /// </summary>
- /// <param name="instance">对象的属性</param>
- public void Apply(FluentNHibernate.Conventions.Instances.IPropertyInstance instance)
- {
- //设置列的字符串长度为50
- instance.Length(50);
- }
- }
public class DefualtStringLengthConvertion : IPropertyConvention
{
/// <summary>
/// 配置Table列的名称及类型
/// </summary>
/// <param name="instance">对象的属性</param>
public void Apply(FluentNHibernate.Conventions.Instances.IPropertyInstance instance)
{
//设置列的字符串长度为50
instance.Length(50);
}
}
(5)IHasOneConvention
Entity Class一对一映射的规则及列的生成规则,同时也可以规定外键对象的加载和操作方式,默认情况下会以“对象_ID”形式命名。
- public class DefualtHasOneConvertion : IHasOneConvention
- {
- /// <summary>
- /// 一对一映射中的外键列及对从表的操作的类型
- /// </summary>
- /// <param name="instance">关系对象</param>
- public void Apply(IOneToOneInstance instance)
- {
- //指定外键列的列名规则
- instance.ForeignKey(instance.EntityType.Name + "ID");
- //指定主表对从表的操作
- instance.Cascade.SaveUpdate();
- instance.LazyLoad();
- }
- }
public class DefualtHasOneConvertion : IHasOneConvention
{
/// <summary>
/// 一对一映射中的外键列及对从表的操作的类型
/// </summary>
/// <param name="instance">关系对象</param>
public void Apply(IOneToOneInstance instance)
{
//指定外键列的列名规则
instance.ForeignKey(instance.EntityType.Name + "ID");
//指定主表对从表的操作
instance.Cascade.SaveUpdate();
instance.LazyLoad();
}
}
(6)IHasManyConvention
Entity Class一对多映射的规则及列的生成规则,同时也可以规定外键对象的加载和操作方式,默认情况下会以“对象_ID”形式命名。
- public class DefaultHasManyConvention : IHasManyConvention
- {
- /// <summary>
- /// 一对多对象的生成规则
- /// </summary>
- /// <param name="instance"></param>
- public void Apply(IOneToManyCollectionInstance instance)
- {
- instance.Key.Column(instance.EntityType.Name + "ID");
- instance.Cascade.AllDeleteOrphan();
- instance.LazyLoad();
- }
- }
public class DefaultHasManyConvention : IHasManyConvention
{
/// <summary>
/// 一对多对象的生成规则
/// </summary>
/// <param name="instance"></param>
public void Apply(IOneToManyCollectionInstance instance)
{
instance.Key.Column(instance.EntityType.Name + "ID");
instance.Cascade.AllDeleteOrphan();
instance.LazyLoad();
}
}
(7)IHasManyToManyConvention
Entity Class多对多映射的规则及列的生成规则,默认情况下会以“对象_ID”形式命名列名,“对象To对象”形式命名表名。
- public class HasManyToManyConvention : IHasManyToManyConvention
- {
- /// <summary>
- /// 多对多映射的规则
- /// </summary>
- /// <param name="instance">多对多关系实例</param>
- public void Apply(IManyToManyCollectionInstance instance)
- {
- //指定表名的生成规则,将表名按字符排序较小的一方表名在前方,表名较大的放到后面
- instance.Table(instance.EntityType.Name.ToString()+instance.ChildType.Name.ToString());
- //关联列的一方的命名方式
- instance.Key.Column(instance.EntityType.Name.ToString()+"ID");
- //关系列的另一方的命名方式
- instance.Relationship.Column(instance.ChildType.Name.ToString()+"ID");
- }
- }
public class HasManyToManyConvention : IHasManyToManyConvention
{
/// <summary>
/// 多对多映射的规则
/// </summary>
/// <param name="instance">多对多关系实例</param>
public void Apply(IManyToManyCollectionInstance instance)
{
//指定表名的生成规则,将表名按字符排序较小的一方表名在前方,表名较大的放到后面
instance.Table(instance.EntityType.Name.ToString()+instance.ChildType.Name.ToString());
//关联列的一方的命名方式
instance.Key.Column(instance.EntityType.Name.ToString()+"ID");
//关系列的另一方的命名方式
instance.Relationship.Column(instance.ChildType.Name.ToString()+"ID");
}
}
1.2.3 编写Unit Test测试映射
上文对AutoMapping的映射规则做了详细的讨论,并且添加了映射中的AutoMapping的映射规则的代码,映射的规则其实相当的简单只需要实现相应的映射规则即可,如果不重写映射规则的话将会按照默认的方式生成数据库表结构,所以在创建表结构的时候需要按照一定的规则创建表结构,然后按照自己创建的表结构的规则创建相应的映射规则配置文件,如上文的代码,接下来我们编写Unit Test来测试AutoMapping。
规则创建完成后需要首先运行一次AutoMapping文件,将配置文件设置为如下代码:
- public ISessionFactory CreateSessionFactory()
- {
- return Fluently
- .Configure() //创建或者指定数据库的配置xml,这里使用的是自动创建的方法
- //指定数据库的映射方法,其实它的底层使用的是反射来实现的映射
- .Database(
- MsSqlConfiguration
- .MsSql2005
- .ConnectionString(
- "Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60")
- //指定连接字符串
- .ShowSql()
- )
- //配置映射规则
- .Mappings(m => m.AutoMappings.Add(CreateAutomappings()) //将创建的AutoPersistenceModel对象添加到AutoMapping中
- .ExportTo("c:\\path") //导出映射文件
- )
- //生成数据库架构
- //new SchemaExport(cfg).Create(true, false)创建配置文件。
- //这里的Create方法是创建的脚本文件的映射方法,
- //第一个参数bool script指定是否生成数据库脚本
- //第二个参数bool export指定每次生成的数据库的创建脚本是否执行
- .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
- .BuildSessionFactory();
- }
public ISessionFactory CreateSessionFactory()
{
return Fluently
.Configure() //创建或者指定数据库的配置xml,这里使用的是自动创建的方法
//指定数据库的映射方法,其实它的底层使用的是反射来实现的映射
.Database(
MsSqlConfiguration
.MsSql2005
.ConnectionString(
"Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60")
//指定连接字符串
.ShowSql()
)
//配置映射规则
.Mappings(m => m.AutoMappings.Add(CreateAutomappings()) //将创建的AutoPersistenceModel对象添加到AutoMapping中
.ExportTo("c:\\path") //导出映射文件
)
//生成数据库架构
//new SchemaExport(cfg).Create(true, false)创建配置文件。
//这里的Create方法是创建的脚本文件的映射方法,
//第一个参数bool script指定是否生成数据库脚本
//第二个参数bool export指定每次生成的数据库的创建脚本是否执行
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
}
这样每次运行时都会检索数据库的表结构并创建相应的数据库表结构,所以在运行一次后要改为.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, false))。
使用单元测试方法来测试一对一的映射如下:
- [TestFixture]
- public class UnitTest1 : Build
- {
- [Test]
- public void TestUsers_UserDetails()
- {
- ISessionFactory sessionFactory = CreateSessionFactory();
- ISession Session = sessionFactory.OpenSession();
- //get user from database
- //User user1 = Session.Load<User>(2);
- //save the User data
- Session.Transaction.Begin();
- //User usreUser = Session.Get<User>(2);
- User user = new User()
- {
- Name = "Jack",
- No = "12321"
- };
- UserDetail userDetails = new UserDetail()
- {
- Age = 12,
- BirthDate = DateTime.Now.Date,
- Height = 240,
- Sex = 1
- };
- user.UserDetails = userDetails;
- userDetails.User = user;
- Session.Save(user);
- Session.Save(userDetails);
- Session.Transaction.Commit();
- }
- }
[TestFixture]
public class UnitTest1 : Build
{
[Test]
public void TestUsers_UserDetails()
{
ISessionFactory sessionFactory = CreateSessionFactory();
ISession Session = sessionFactory.OpenSession();
//get user from database
//User user1 = Session.Load<User>(2); //save the User data
Session.Transaction.Begin(); //User usreUser = Session.Get<User>(2);
User user = new User()
{
Name = "Jack",
No = "12321"
};
UserDetail userDetails = new UserDetail()
{
Age = 12,
BirthDate = DateTime.Now.Date,
Height = 240,
Sex = 1
};
user.UserDetails = userDetails;
userDetails.User = user;
Session.Save(user);
Session.Save(userDetails);
Session.Transaction.Commit();
}
}
运行该Unit Test Method后生成的数据库表如下图:
运行完后插入的表结构的数据如下图:
编写代码测试多对多的映射关系如下:
- [TestFixture]
- public class UnitTest1:Build
- {
- [Test]
- public void TestUsers_UserDetails()
- {
- ISessionFactory sessionFactory = CreateSessionFactory();
- ISession Session=sessionFactory.OpenSession();
- //get user from database
- //User user1 = Session.Load<User>(2);
- //save the User data
- Session.Transaction.Begin();
- //User usreUser = Session.Get<User>(2);
- User user=new User()
- {
- Name = "Jack",
- No = "12321"
- };
- UserDetail userDetails=new UserDetail()
- {
- Age = 12,
- BirthDate = DateTime.Now.Date,
- Height = 240,
- Sex = 1
- };
- user.UserDetails = userDetails;
- userDetails.User = user;
- Session.Save(user);
- Session.Save(userDetails);
- Session.Transaction.Commit();
- }
- [Test]
- public void TestUsers_ProductProject()
- {
- ISessionFactory sessionFactory = CreateSessionFactory();
- ISession Session = sessionFactory.OpenSession();
- //get user from database
- //User user1 = Session.Load<User>(1);
- //save the User data
- Session.Transaction.Begin();
- Project project = new Project()
- {
- Name = "project1"
- };
- Product product1 = new Product()
- {
- Name = "Product1",
- Color = "Red",
- };
- Product product2 = new Product()
- {
- Name = "Product2",
- Color = "Red"
- };
- product1.Project.Add(project);
- product2.Project.Add(project);
- //Project project1 = new Project()
- //{
- // Name = "project2"
- //};
- project.Product.Add(product1);
- project.Product.Add(product2);
- Session.Save(project);
- Session.Save(product1);
- Session.Save(product2);
- Session.Transaction.Commit();
- }
- [Test]
- public void TestUsers_ProjectProduct()
- {
- ISessionFactory sessionFactory = CreateSessionFactory();
- ISession Session = sessionFactory.OpenSession();
- //get user from database
- //User user1 = Session.Load<User>(1);
- //save the User data
- Session.Transaction.Begin();
- Project project = new Project()
- {
- Name = "project1"
- };
- Project project1 = new Project()
- {
- Name = "project2"
- };
- Product product = new Product()
- {
- Name = "Product1",
- Color = "Red",
- };
- product.Project.Add(project);
- product.Project.Add(project1);
- //project.Product.Add(product);
- //project1.Product.Add(product);
- Session.Save(project);
- Session.Save(project1);
- Session.Save(product);
- Session.Transaction.Commit();
- }
- }
[TestFixture]
public class UnitTest1:Build
{
[Test]
public void TestUsers_UserDetails()
{
ISessionFactory sessionFactory = CreateSessionFactory();
ISession Session=sessionFactory.OpenSession();
//get user from database
//User user1 = Session.Load<User>(2); //save the User data
Session.Transaction.Begin(); //User usreUser = Session.Get<User>(2);
User user=new User()
{
Name = "Jack",
No = "12321"
};
UserDetail userDetails=new UserDetail()
{
Age = 12,
BirthDate = DateTime.Now.Date,
Height = 240,
Sex = 1
};
user.UserDetails = userDetails;
userDetails.User = user;
Session.Save(user);
Session.Save(userDetails);
Session.Transaction.Commit();
} [Test]
public void TestUsers_ProductProject()
{
ISessionFactory sessionFactory = CreateSessionFactory();
ISession Session = sessionFactory.OpenSession();
//get user from database
//User user1 = Session.Load<User>(1); //save the User data
Session.Transaction.Begin();
Project project = new Project()
{
Name = "project1"
};
Product product1 = new Product()
{
Name = "Product1",
Color = "Red",
};
Product product2 = new Product()
{
Name = "Product2",
Color = "Red"
};
product1.Project.Add(project);
product2.Project.Add(project);
//Project project1 = new Project()
//{
// Name = "project2"
//};
project.Product.Add(product1);
project.Product.Add(product2);
Session.Save(project);
Session.Save(product1);
Session.Save(product2);
Session.Transaction.Commit();
}
[Test]
public void TestUsers_ProjectProduct()
{
ISessionFactory sessionFactory = CreateSessionFactory();
ISession Session = sessionFactory.OpenSession();
//get user from database
//User user1 = Session.Load<User>(1); //save the User data
Session.Transaction.Begin();
Project project = new Project()
{
Name = "project1"
};
Project project1 = new Project()
{
Name = "project2"
};
Product product = new Product()
{
Name = "Product1",
Color = "Red",
};
product.Project.Add(project);
product.Project.Add(project1);
//project.Product.Add(product);
//project1.Product.Add(product); Session.Save(project);
Session.Save(project1);
Session.Save(product);
Session.Transaction.Commit();
}
}
运行两个方法后查看生成的相应数据如下:
结语
本文详细讨论了AutoMapping的使用方法,主要讨论了AutoMapping的使用步骤并使用上篇文章中的数据库结构作为实例来演示了AutoMapping代码的实现过程,该Project的源码下载地址为:http://download.csdn.net/detail/zhang_xinxiu/8309201。
虽然使用AutoMapping来实现映射很简单,而且也能够减少代码的冗余,但是在大型项目中并不推荐使用此种方法来映射,因为AutoMapping有太多的不确定性,不够成熟,供查询的资料很少,为了避免风险建议使用FluentNHibernate来映射项目。
版权声明:本文为博主原创文章,未经博主允许不得转载。
【ORM】--FluentNHibernate之AutoMapping详解的更多相关文章
- Python:轻量级 ORM 框架 peewee 用法详解(二)——增删改查
说明:peewee 中有很多方法是延时执行的,需要调用 execute() 方法使其执行.下文中不再特意说明这个问题,大家看代码. 本文中代码样例所使用的 Person 模型如下: class Per ...
- 【ORM】--FluentNHibernate之基本映射详解
最近在做项目的时候用到了NHibernate,使用它并不困难,但是很麻烦.如果我的数据库有几百张表如果想要一个个的映射岂不是很麻烦,所以这种情况下使用NHibernate就会很笨重,虽然 ...
- .NET ORM框架 SqlSuagr4.0 功能详解与实践【开源】
SqlSugar 4.0 ORM框架的优势 为了未来能够更好的支持多库分布式的存储,并行计算等功能,将SqlSugar3.x全部重写,现有的架构可以轻松扩展多库. 源码下载: https://gith ...
- python/ORM操作详解
一.python/ORM操作详解 ===================增==================== models.UserInfo.objects.create(title='alex ...
- 2018.10.7 理解Hibernate的工作原理及其中的ORM详解
复习 hibernate框架 简介j及其搭建: hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库. 1 ...
- Django框架 之 ORM查询操作详解
Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...
- django ORM 外键详解
Django中的外键: 首先,为了方便理解,我们把使用ForeignKey的字段所在的表定义为从表,把ForeignKey中to参数连接的表称为主表. 外键使用的先决条件: 在mysql数据表中,数据 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- ORM详解
讲解对象:ORM详解 作者:融水公子 rsgz 1 前言:开发流程正常只有简单的几步 0.1 配置数据库 0.2 定义模型 0.3 迁移文件 0.4 执行迁移生成数据表 0.5 使用模型类增删改查 2 ...
随机推荐
- Codeforces Round #361 Jul.6th A题 ☺译
A.迈克和手机 当迈克在沙滩上游泳的时候,他意外的把他的手机扔进了水里.不过你甭担心因为他立马买了个便宜些的代替品,这个代替品是老款九键键盘,这个键盘只有十个等大的数字按键,按以下方式排列: 1 2 ...
- 如何让老式浏览器支持html5新增的语义元素
html5新增加了一些语义元素,如header, footer, nav, aritcle, aside,等等. 然而,有些老款浏览器无法识别这些元素,会把它们当成 inline 元素对待,这会导致一 ...
- caffe初步实践---------使用训练好的模型完成语义分割任务
caffe刚刚安装配置结束,乘热打铁! (一)环境准备 前面我有两篇文章写到caffe的搭建,第一篇cpu only ,第二篇是在服务器上搭建的,其中第二篇因为硬件环境更佳我们的步骤稍显复杂.其实,第 ...
- Base64加密工具-iBlogs
简易的Base64加密工具开发步骤 1.编写Java测试桩 import java.io.BufferedReader; import java.io.IOException; import java ...
- excel 导入数值变成科学记数的解决办法.
string conn = "Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"Excel 8.0;HDR=Yes;IM ...
- HTTP POST 提交问题
最近用http+post方式实现了系统间数据交互的需求. 常用的方式是 application/json方式直接post json对象 . 告诉服务器数据格式将会是 { Name : 'John Sm ...
- [Linux] - CentOS中文乱码解决办法
CentOS 7 终端中文乱码解决办法: 1.使用vim编辑locale.config文件: vim /etc/locale.conf 2.将LANG="en_US.UTF-8"修 ...
- cPage分页详细介绍
asp.net中各种数据控件,datalist.gridview.Repeater等分页是最常用的功能,几乎任何一个B/S项目,无论是系统还是网站都会用到.分页时,读取整个数据,直接绑定到控件,都可以 ...
- windows下安装boost库
工作中现在会接触boost,所以我计划两个月之内努力熟悉一下boost.今天在自己win10系统上尝试安装了boost库,下面把遇到的问题总结一下: 1. 下好1.61版本库,在boost目录下运行b ...
- 使用Ajax实现的批量删除操作(C#)
今天做了一个简单的批量删除操作,虽然简单,但是很多问题出现,终究还是技术不够熟练. 现在在这里跟大家分享一下.仅供学习... 1.在前台获取用户点击的信息id,把这里id封装到一个数组里面:(rows ...