MyGeneration 的几个NHibernate模板功能已经很强,但还是存在些问题。例如:Guid主键支持不佳,代码不易修改,不支持中文注释等等。所以我决定自己来改写 此模版。我把一部分通用的函数提取到自己定义的基类中,这样调试和修改都方便另外增加了一部分新功能。
NHibernate里面的关系写起来也很烦人,很容易出错,所以我写了另一个模版专门生成关系代码。只需要把生成的代码拷到映射类文件和.hbm.xml文件中就可以了。
下载
如果你兴趣自己写模版,或者使用中有问题可以查看强大的代码生成工具MyGeneration 。
使用中发现什么问题,或者是有什么好的意见建议请及时和我联系。十分感谢!
下载完成后把DDLLY.MyGenerationTemplate.dll拷贝到MyGeneration的安装路径。把模版文件拷贝到MyGeneration的安装路径下的Templates目录里面的NHibernate目录里。
生成映射文件
运行MyGeneration,选择Edit里面的Default Settings...,进行适当的配置。如图
在Template Browser里面的NHibernate找到"DDL NHibernate Object Mapping"。运行此模版
输出路径表示生成模版的生成路径。启用nullable类型表示在.Net2.0中使用nullable类型,如果。
提示:你可以按住Ctrl或者Shift选择多个表。
Save按钮可以把的你设置存储在注册表中,下次将自动获得保存的设置。
选中你需要生成映射类的表,点Ok按钮。将生成映射文件。你可以在输出路径中找到他们。
下面是我生成的文件
/*NHibernate映射代码模板
/*作者:DDL
/*版本更新和支持:http://renrenqq.cnblogs.com/
/*日期:2006年8月14日
*/
using System;
namespace MyNamePlace
{
/// <summary>
///
/// </summary>
[Serializable]
public sealed class User
{
私有成员
默认( 空 ) 构造函数
公有属性
公有函数
重写Equals和HashCode
}
}
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.0" >
< class name ="MyNamePlace.User,MyAssembly" table ="T_User" >
< id name ="UserId" column ="UserId" type ="Int32" unsaved-value ="0" >
< generator class ="native" />
</ id >
< property column ="UserName" type ="String" name ="UserName" not-null ="true" length ="64" />
< property column ="Password" type ="String" name ="Password" not-null ="true" length ="32" />
< property column ="Email" type ="String" name ="Email" length ="64" />
</ class >
</ hibernate-mapping >
备注:
我的数据库表名以"T_"开头,生成类时我会用"_"后面的内容。例如:T_Parent对应的类是Parent。如果你的表名中没有"_"。将会取表名做类名。
如果你在设计数据表时把字段的描述加上,生成的代码文件的注释中将会有属性的描述。
注意:在把他们加入Visual Studio后别忘了设置为嵌入的资源。
生成关系
在Template Browser里面的NHibernate找到"DDL NHibernate Relation Mapping"。运行此模版
选择你需要的表,需要的关系。点OK。
我们以双向的one-to-many为例
你可以看到下面的生成代码。
< bag name = " Childs " cascade = " all " lazy = " true " inverse = " true " >
< key column = " ParentId " ></ key >
< one - to - many class = " MyNamePlace.Child,MyAssembly " ></ one - to - many >
</ bag >
private IList m_Child = new ArrayList();
public IList Childs
{
get{return m_Child;}
set{m_Child=value;}
}
// Child
< many - to - one name = " Parent " column = " ParentId "
class = " MyNamePlace.Parent,MyAssembly " />
private Parent m_Parent;
public Parent Parent
{
get{return m_Parent;}
set{m_Parent=value;}
}
把他们拷贝到你生成的模版文件里面。“//Parent”后面的拷贝到Parent的映射类文件和.hbm.xml文件中。“//Child”后面的拷贝到Child的映射类文件和.hbm.xml文件中。
注意:需要把Child类和.hbm.xml里的ParentId去掉,不然会出现两个属性映射到一个字段的错误。
DDL NHibernate Relation Mapping模板使用注意:
保持主外键的名称一致,比如T_Parent中主键名为ParetId,T_Child中与其参照的外键名也为ParentId。
主表先选择,Parent-Child关系中先选择Parent,Person-Employee关系中先选择Person。
多对多关系才会用到中间表下拉框。
其他的关系生成操作方法类似,我不再复述。
如果你对关联不是很熟悉请参见NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析。本模版生成的文件都使用NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析一文的典型设置。可以满足绝大部分的情况。当然你也可以适当修改后使用。
模版更新:
增加了对Guid主键的支持,中文的注释,其他代码改善,部分代码提取到自定义的基类。
2006.8.24 修改部分bug
很多人反应模版使用问题,鉴于我这里没有.net1.0或者1.1的环境,所以把代码给出来,可以自己编译一个dll。
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using Dnp.Utils;
using MyMeta;
using Zeus;
using Zeus.DotNetScript;
using Zeus.UserInterface;
namespace DDLLY.MyGenerationTemplate
{
public abstract class DDLNHibernateDotNetScriptTemplate : _DotNetScriptTemplate
{
protected GuiController ui;
protected dbRoot MyMeta;
protected Utils DnpUtils;
public DDLNHibernateDotNetScriptTemplate(IZeusContext context)
: base(context)
{
ui = context.Objects["ui"] as GuiController;
MyMeta = context.Objects["MyMeta"] as dbRoot;
DnpUtils = context.Objects["DnpUtils"] as Utils;
}
/// <summary>
/// 前缀
/// </summary>
protected string _prefix;
/// <summary>
/// 创建XML
/// </summary>
protected bool _CreatingXML = false;
protected string _NullSufix;
protected string ConvertNHibernate(string Type)
{
string retVal = Type;
switch (Type)
{
case "bool":
retVal = "Boolean";
break;
case "byte":
retVal = "Byte";
break;
case "sbyte":
retVal = "SByte";
break;
case "char":
retVal = "Char";
break;
case "decimal":
retVal = "Decimal";
break;
case "double":
retVal = "Double";
break;
case "float":
retVal = "Single";
break;
case "int":
retVal = "Int32";
break;
case "uint":
retVal = "UInt32";
break;
case "long":
retVal = "Int64";
break;
case "ulong":
retVal = "UInt64";
break;
case "short":
retVal = "Int16";
break;
case "ushort":
retVal = "UInt16";
break;
case "string":
retVal = "String";
break;
}
return retVal;
}
//protected string ColumnToMemberVariable(IColumn Column)
//{
// return _prefix + UniqueColumn(Column).ToLower();
//}
//protected string ColumnToPropertyName(IColumn Column)
//{
// return ToPascalCase(UniqueColumn(Column));
//}
//protected string ColumnToArgumentName(IColumn Column)
//{
// return UniqueColumn(Column).ToLower();
//}
//protected string ColumnToNHibernateProperty(IColumn Column)
//{
// return _prefix + UniqueColumn(Column);
//}
// nhibernate doesn't have these, so use the existing types
protected string ColumnToNHibernateType(IColumn Column)
{
string retVal = Column.LanguageType;
switch (retVal)
{
case "sbyte":
retVal = "byte";
break;
case "uint":
retVal = "int";
break;
case "ulong":
retVal = "long";
break;
case "ushort":
retVal = "short";
break;
case "bool":
case "decimal":
case "float":
case "byte":
case "short":
case "int":
case "long":
if (!_CreatingXML)
{
if (Column.IsNullable)
{
retVal = retVal + _NullSufix;
}
}
break;
}
return retVal;
}
///// <summary>
///// 首字母大写
///// </summary>
///// <param name="name"></param>
///// <returns></returns>
//protected string ToLeadingCaps(string name)
//{
// char[] chars = name.ToLower().ToCharArray();
// chars[0] = Char.ToUpper(chars[0]);
// return new string(chars);
//}
/// <summary>
/// 首字母小写
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private string ToLeadingLower(string name)
{
char[] chars = name.ToCharArray();
chars[0] = Char.ToLower(chars[0]);
return new string(chars);
}
/// <summary>
/// 私有成员名
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
protected string ToVariableName(string name)
{
return _prefix + name;
}
/// <summary>
/// 参数名
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
protected string ToArgumentName(string name)
{
return ToLeadingLower(name);
}
///// <summary>
///// 统计必需(不允许空)的的字段个数
///// </summary>
///// <param name="Columns"></param>
///// <returns></returns>
//protected int CountRequiredFields(IColumns Columns)
//{
// return Columns.Count - CountNullableFields(Columns);
//}
///// <summary>
///// 统计允许为空的字段个数
///// </summary>
///// <param name="Columns"></param>
///// <returns></returns>
//protected int CountNullableFields(IColumns Columns)
//{
// int i = 0;
// foreach (IColumn c in Columns)
// {
// if (c.IsNullable)
// {
// i++;
// }
// }
// return i;
//}
/// <summary>
/// 统计唯一字段的个数(非空且为主键)
/// </summary>
/// <param name="Columns"></param>
/// <returns></returns>
protected int CountUniqueFields(IColumns Columns)
{
int i = 0;
foreach (IColumn c in Columns)
{
if (!c.IsNullable && c.IsInPrimaryKey)
{
i++;
}
}
return i;
}
/// <summary>
/// 根据IColumn获得不同的Generator
/// </summary>
/// <param name="Column"></param>
/// <returns></returns>
protected string GetGeneratorString(IColumn Column)
{
if (Column.DataTypeName == "uniqueidentifier")
{
return "guid";
}
if(Column.IsAutoKey)
{
return "native";
}
else
{
return "assigned";
}
}
/// <summary>
/// 表名转换为类名
/// </summary>
/// <param name="tableName"></param>
/// <returns></returns>
protected string TableNameToClassName(string tableName)
{
int index = tableName.LastIndexOf("_");
return tableName.Substring(index + 1);
}
}
}
需要引用以下类库(都在MyGeneration的安装路径里):
Dnp.Utils.dll
DotNetScriptingEngine.dll
MyMeta.dll
PluginInterfaces.dll
Zeus.dll