Nhibernate应用-Text和Ntext数据类型的使用

 前两天用nhibernate的时候用户提交过来一个错误,说一个文本输入框输入字符过长,会被在固定的地方截断,经过试验发现4000个字符8000个字节的时候会被截断。
  看了一下映射文件中的xml配置,发现映射字段如下:
  <property column="InfoContent" type="String" name="InfoContent" length="2147483647" />
  虽然该字段的长度被设置的足够大,但是使用过程中还是被截断了。
  查看了一下nhibernate的源码,发现在实际操作过程中发现nhibernate对string的处理时候自动将string类型按照数据中的nvarchar类型处理,最大长度4000字符,超过后自动截掉。查看了一下nhibernate 1.02的接口类型发现有一个StringClob,是处理长字符串的。
  改变了xml里面的类型设置后,测试通过。
  <property column="InfoContent" type="StringClob" name="InfoContent" length="2147483647" />
 
   和Nhibernate相关的配置一直都是用MyGeneration的Nhibernate Object Mapping 1.1的模板生成的,我对该模板进行了稍微的修改,判断了一下字段的长度,如果长度是Text或者NText的长度就将字段类型修改为“StringClob”,现在共享给大家,希望对大家有帮助。

修改后的模板:(由于这里不能上传附件,下载后保存到mygeneration的nhibernate目录下即可)

##|TYPE Template
##|UNIQUEID 751f78af-5424-4d4e-8676-4712f98788e3
##|TITLE NHibernate Object Mapping 1.1.1
##|NAMESPACE NHibernate
##|OUTPUT_LANGUAGE C#
##|COMMENTS_BEGIN
This is an update of k-dub's NHibernate Object Mapping template.  Generate C# classes or hbm mapping files or both. Can use tables or views. Can specify "read-only". Can generate overridden Equals and GetHashCode methods.  Added support for one-to-many mappings.
##|COMMENTS_END
##|GUI_ENGINE .Net Script
##|GUI_LANGUAGE C#
##|GUI_BEGIN
<%#REFERENCE System.Windows.Forms.dll %>
<%#NAMESPACE System, System.Text, System.Collections, Zeus, Zeus.UserInterface, Zeus.DotNetScript %>

public class GeneratedGui : DotNetScriptGui
{
 public GeneratedGui( ZeusGuiContext context ) : base( context ) {}

 public override void Setup()
 {
  if ( !input.Contains( "chooseTables" ) || !input.Contains( "txtPath" ) ||
    ( !input.Contains( "chkClass" ) && !input.Contains( "chkNaming" ) ) )
  {
   ui.Title = "NHibernate Object Mapping";
   ui.Width = 600;
   ui.Height = 640;
 
   // Grab default output path
   string sOutputPath = "";
   
   if( input.Contains( "defaultOutputPath" ) )
   {
    sOutputPath = input["defaultOutputPath"].ToString();
   }

   // Setup Folder selection input control.
   GuiLabel label1 = ui.AddLabel( "label1", "Select the output path:", "Select the output path in the field below." );
   label1.Width = 200;
   GuiTextBox outputPath = ui.AddTextBox( "outputPath", sOutputPath, "Select the Output Path." );
   outputPath.Width = 450;
   GuiFilePicker selectPath = ui.AddFilePicker( "selectPath", "Select Path", "Select the Output Path.", "outputPath", true );
   selectPath.Top = outputPath.Top;
   selectPath.Width = 100;
   selectPath.Left = outputPath.Left + outputPath.Width + 20;
   
   GuiLabel label2 = ui.AddLabel( "label2", "Namespace: ",  "Provide your objects namespace." );
   label2.Width = 280;
   GuiTextBox classNamespace = ui.AddTextBox( "classNamespace", "Business.Data", "Provide your objects namespace." );    
   classNamespace.Width = 280;
   
            GuiLabel label3 = ui.AddLabel( "label3", "Member variable prefix: ", "Provide your Prefix." );
   label3.Width = 280;
   label3.Top = label2.Top;
   label3.Left = label2.Width + 20;
   GuiTextBox memberPrefix = ui.AddTextBox( "memberPrefix", "m_", "" );
   memberPrefix.Width = 280;
   memberPrefix.Top = classNamespace.Top;
   memberPrefix.Left = classNamespace.Width + 20;
            
   // Setup Database selection combobox.
   GuiLabel label4 = ui.AddLabel( "label4", "Select a database:", "Select a database in the dropdown below." );
   label4.Width = 250;
   GuiComboBox chooseDatabase = ui.AddComboBox( "chooseDatabase", "Select a database." );
   chooseDatabase.Width = 250;
   
   GuiLabel label5 = ui.AddLabel( "label5", "Output type:", "Select one or both." );
   label5.Width = 150;
   label5.Top = label4.Top;
   label5.Left = label4.Width + 20;
   GuiCheckBox chkClass = ui.AddCheckBox( "chkClass", "Create class files.", true, "Create a class file for each table or view selected. (*.cs)" );
   chkClass.Width = 150;
   chkClass.Top = chooseDatabase.Top;
   chkClass.Left = chooseDatabase.Width + 20;
   GuiCheckBox chkMapping = ui.AddCheckBox( "chkMapping", "Create XML mapping files.", true, "Create an XML file for each table or view selected. (*.hbm.xml)" );
   chkMapping.Width = 150;
   chkMapping.Top = chkClass.Top + 20;
   chkMapping.Left = chkClass.Left;
   
   GuiLabel label6 = ui.AddLabel( "label6", "Read Only:", "Create as read only?" );
   label6.Width = 150;
   label6.Top = label5.Top;
   label6.Left = label5.Left + label5.Width + 20;
   GuiCheckBox chkReadOnly = ui.AddCheckBox( "chkReadOnly", "Create as read-only.", false, "Create object and mapping to have read-only access." );
   chkReadOnly.Width = 150;
   chkReadOnly.Top = chkClass.Top;
   chkReadOnly.Left = chkClass.Left + chkClass.Width + 20;
   
   GuiCheckBox chkDefaultEmptyConstructor = ui.AddCheckBox( "chkDefaultEmptyConstructor", "Create a default (empty) constructor.  Required.", true, "Create a default constructor with empty fields." );
   chkDefaultEmptyConstructor.Top = chkMapping.Top + 20;
   GuiCheckBox chkRequiredFieldsConstructor = ui.AddCheckBox( "chkRequiredFieldsConstructor", "Create a constructor with all required (non-null) fields as parameters.", true, "Create a constructor with all required (non-null) fields as parameters" );
   chkRequiredFieldsConstructor.Top = chkDefaultEmptyConstructor.Top + 20;
   GuiCheckBox chkIncludePKInReqFieldsCtorArgs = ui.AddCheckBox( "chkIncludePKInReqFieldsCtorArgs", "Include primary key in required fields constructor.", false, "Include primary key in the parameter list for the required fields constructor." );
   chkIncludePKInReqFieldsCtorArgs.Top = chkRequiredFieldsConstructor.Top + 20;
   GuiCheckBox chkEqualsHashCode = ui.AddCheckBox( "chkEqualsHashCode", "Create Equals and GetHashCode.", false, "Generate Equals and GetHashCode methods." );
   chkEqualsHashCode.Top = chkIncludePKInReqFieldsCtorArgs.Top + 20;
 
 
   // Setup Tables selection multi-select listbox.
   GuiLabel label7 = ui.AddLabel( "label7", "Select tables:", "Select tables from the listbox below." );
   label7.Top = chkEqualsHashCode.Top + 20;
   GuiListBox chooseTables = ui.AddListBox( "chooseTables", "Select tables." );
   chooseTables.Height = 120;
 
   // Setup Views selection multi-select listbox.
   GuiLabel label8 = ui.AddLabel( "label8", "Select views:", "Select views from the listbox below." );
   GuiListBox chooseViews = ui.AddListBox( "chooseViews", "Select views." );
   chooseViews.Height = 120;
   
   // Attach the onchange event to the cmbDatabases control.
   setupDatabaseDropdown( chooseDatabase );
   chooseDatabase.AttachEvent( "onchange", "chooseDatabase_onchange" );
 
   ui.ShowGui = true;
  }
  else
  {
   ui.ShowGui = false;
  }
 }
 
 public void setupDatabaseDropdown( GuiComboBox Databases )
 {
  try
  { 
   if( MyMeta.IsConnected )
   {
    Databases.BindData( MyMeta.Databases );
    if( MyMeta.DefaultDatabase != null )
    {
     Databases.SelectedValue = MyMeta.DefaultDatabase.Alias;
     bindTables( Databases.SelectedValue );
     bindViews( Databases.SelectedValue );
    }
   }
  }
  catch
  {
  }
 }
 
 public void bindTables( string sDatabase )
 {
  int count = 0;
 
  GuiListBox lstTables = ui["chooseTables"] as GuiListBox;
  
  try
  { 
   IDatabase db = MyMeta.Databases[sDatabase];
   lstTables.BindData( db.Tables );
  }
  catch
  {
  }
 }
 
 public void bindViews( string sDatabase )
 {
  int count = 0;
 
  GuiListBox lstViews = ui["chooseViews"] as GuiListBox;
  
  try
  { 
   IDatabase db = MyMeta.Databases[sDatabase];
   lstViews.BindData( db.Views );
  }
  catch
  {
  }
 }
 
 public void chooseDatabase_onchange( GuiComboBox control )
 {
  int count = 0;

  GuiComboBox cmbDatabases = ui["chooseDatabase"] as GuiComboBox;
 
  bindTables( cmbDatabases.SelectedText );
  bindViews( cmbDatabases.SelectedText );
 }
 
}
##|GUI_END
##|BODY_MODE Markup
##|BODY_ENGINE .Net Script
##|BODY_LANGUAGE C#
##|BODY_TAG_START <%
##|BODY_TAG_END %>
##|BODY_BEGIN
<%#NAMESPACE System.IO, System.Text, System.Text.RegularExpressions, System.Globalization %><%
public class GeneratedTemplate : DotNetScriptTemplate
{
 private ArrayList _selectedTables;
 private ArrayList _selectedViews;
 private string _dbName;
 private string _tableName;
 private string _className;
 private string _exportPath;
 private string _fileName;
 private string _nameSpace;
 private string _prefix;
 private bool _createClassFiles;
 private bool _createXmlFiles;
 private bool _createReadOnly;
 private bool _generateEqualsHashCode;
 private bool _generateDefaultCtor;
 private bool _generateRequiredFieldsCtor;
 private bool _includePKInReqFieldsCtorArgs;
 
 public GeneratedTemplate( ZeusContext context ) : base( context ) {}

 public override void Render()
 {
  _dbName = input["chooseDatabase"].ToString();
  _selectedTables = input["chooseTables"] as ArrayList;
  _selectedViews = input["chooseViews"] as ArrayList;
  _exportPath = input["outputPath"].ToString();
  _nameSpace = input["classNamespace"].ToString();
  _prefix = input["memberPrefix"].ToString();
  _createClassFiles = (bool)input["chkClass"];
  _createXmlFiles = (bool)input["chkMapping"];
  _createReadOnly = (bool)input["chkReadOnly"];
  _generateEqualsHashCode = (bool)input["chkEqualsHashCode"];
  _generateDefaultCtor = (bool) input["chkDefaultEmptyConstructor"];
  _generateRequiredFieldsCtor = (bool) input["chkRequiredFieldsConstructor"];
  _includePKInReqFieldsCtorArgs = (bool) input["chkIncludePKInReqFieldsCtorArgs"];
  
  foreach( string _newTable in _selectedTables )
  {
   ITable _workingTable = MyMeta.Databases[_dbName].Tables[_newTable];
   _tableName = _workingTable.Alias.Replace( " ", "" );
   _className = ToPascalCase( _tableName );
   if( _createClassFiles )
   {
    GenerateClassFile( _workingTable.Columns );
   }
   if( _createXmlFiles )
   {
    GenerateMappingFile( _workingTable.Columns );
   }
  }
  
  foreach( string _newView in _selectedViews )
  {
   IView _workingView = MyMeta.Databases[_dbName].Views[_newView];
   _tableName = _workingView.Alias.Replace( " ", "" );
   _className = ToPascalCase( _tableName );
   if( _createClassFiles )
   {
    GenerateClassFile( _workingView.Columns );
   }
   if( _createXmlFiles )
   {
    GenerateMappingFile( _workingView.Columns );
   }
  }
 }
 
 private void GenerateClassFile( IColumns Columns )
 {
  output.writeln( "/*" );
  output.writeln( "insert license info here" );
  output.writeln( "*/" );
  output.writeln( "using System;" );
  output.writeln( "using System.Collections;" );
  output.writeln( "" );
  output.write( "namespace " );
  output.writeln( _nameSpace );
  output.writeln( "{" );
  output.writeln( "/t/// <summary>" );
  output.writeln( "/ttGenerated by MyGeneration using the NHibernate Object Mapping template" );
  output.writeln( "/t/// </summary>" );
  output.writeln( "/t[Serializable]" );
  output.write( "/tpublic sealed class " );
  output.writeln( _className );
  output.writeln( "/t{" );
  
  BuildPrivateMembers( Columns );
  
  if( _generateDefaultCtor )
   BuildDefaultConstructor( Columns );
  
  if( _generateRequiredFieldsCtor )
   BuildRequiredFieldsCtor( Columns );
  
  BuildPublicAccessors( Columns );
//  BuildPublicFunctions( Columns );
  
  if( _generateEqualsHashCode )
   BuildEqualsHashCodeOverrides( Columns );
  
  output.writeln( "/t}" );
  output.writeln( "}" );
  
  _fileName = _className + ".cs";
  output.save( Path.Combine( _exportPath, _fileName ), false );
  output.clear();
 }
 
 private void GenerateMappingFile( IColumns Columns )
 {
  BuildHBMDefinition( Columns );
  
  _fileName = _className + ".hbm.xml";
  output.save( Path.Combine( _exportPath, _fileName ), false );
  output.clear();
 }
 
 private void BuildDefaultConstructor( IColumns Columns )
 {
  %>
  #region Default ( Empty ) Class Constuctor
  /// <summary>
  /// default constructor
  /// </summary>
  public <%= _className %>()
  {<%
  foreach( IColumn field in Columns )
  {
   string fieldName = ColumnToMemberVariable( field );
   string fieldType = ( field.IsInForeignKey && !field.IsInPrimaryKey ? ColumnFKToClassName( field) : ColumnToNHibernateType( field ) );
   
   if( fieldType.EndsWith( "[]" ) )
   {%>
   <%= fieldName %> = new <%= fieldType %>{}; <%
   }
   else
   {
    switch( fieldType )
    {
     case "string":%>
   <%= fieldName %> = String.Empty; <%
      break;
     case "DateTime":%>
   <%= fieldName %> = DateTime.MinValue; <%
      break;
     case "bool":%>
   <%= fieldName %> = false; <%
      break;
     case "decimal":
     case "float":
     case "short":
     case "int":
     case "long":%>
   <%= fieldName %> = 0; <%
      break;
     default:%>
   <%= fieldName %> = new <%= fieldType %>(); <%
      break;
    }
   }
   
   if( field.IsInForeignKey && field.IsInPrimaryKey )
   {
    //Here, there are foreign key relationships to this column,
    //so there are collections in this class that represent those relationships.
    //Initialize them. 
    foreach( IForeignKey fk in field.ForeignKeys )
    {
     output.writeln("");
     output.write("/t/t/t");
     output.write( _prefix );
     output.write( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) );
     output.write( "List = new ArrayList(); " );
    }
   }
  }
  
  output.writeln( "" );
  output.writeln( "/t/t}" );
  output.writeln( "/t/t#endregion // End of Default ( Empty ) Class Constuctor" );  
 }
 
 private void BuildRequiredFieldsCtor( IColumns Columns )
 {
  //If there are no required fields, don't make a ctor.
  //Doing so will give a compiler error, since the result will
  //have the same signature as the default ctor.
  if( CountRequiredFields( Columns ) == 0 )
   return;
 
  output.writeln( "" );
  output.writeln( "/t/t#region Required Fields Only Constructor" );
  output.writeln( "/t/t/// <summary>" );
  output.writeln( "/t/t/// required (not null) fields only constructor" );
  output.writeln( "/t/t/// </summary>" );
  output.write( "/t/tpublic " );
  output.write( _className );
  output.writeln( "(" );

  bool first = true;
  foreach( IColumn col in Columns )
  {
   if( !col.IsNullable && ( !col.IsInPrimaryKey || _includePKInReqFieldsCtorArgs ) )
   {
    if( !first )
    {
     output.writeln( ", " );
    }
    output.write( "/t/t/t" );

    if( col.IsInForeignKey && !col.IsInPrimaryKey )
     output.write( ColumnFKToClassName( col ) );
    else
     output.write( ColumnToNHibernateType( col ) );
     
    output.write( " " + ColumnToArgumentName( col ) );
    first = false;
   }
  }
  output.writeln( ")" );
  output.writeln( "/t/t/t: this()" );
  output.writeln( "/t/t{" );

  foreach( IColumn col in Columns )
  {
   if( col.IsInPrimaryKey && !_includePKInReqFieldsCtorArgs )
   {
    //Skip the primary key field, if instructed to do so.
    continue;
   }

   output.write( "/t/t/t" );
   
   if( !col.IsNullable && ( !col.IsInPrimaryKey || _includePKInReqFieldsCtorArgs ) )
   {
    output.write( ColumnToMemberVariable( col ) );
    output.write( " = " );
    output.write( ColumnToArgumentName( col ) );    
    output.writeln( ";" ); 
   }
   else
   {
    string fieldType = ( col.IsInForeignKey && !col.IsInPrimaryKey
     ? ColumnFKToClassName( col )
     : ColumnToNHibernateType( col ) );
   
    switch( fieldType )
    {
     default:
      output.write( ColumnToMemberVariable( col ) );
      output.writeln( " = null;" );
      break;      
     case "string":
      output.write( ColumnToMemberVariable( col ) );
      output.writeln( " = String.Empty;" );
      break;
     case "DateTime":
      output.write( ColumnToMemberVariable( col ) );
      output.writeln( " = DateTime.MinValue;" );
      break;
     case "bool":
      output.write( ColumnToMemberVariable( col ) );
      output.writeln( " = false;" );
      break;
     case "decimal":
     case "float":
     case "short":
     case "int":
     case "long":
      output.write( ColumnToMemberVariable( col ) );
      output.writeln( " = 0;" );
      break;
    }
   }
  }
  output.writeln( "/t/t}" );
  output.writeln( "/t/t#endregion // End Required Fields Only Constructor" );
 }
 
 private void BuildFullConstructor( IColumns Columns )
 {
  %>#region Full Constructor
  /// <summary>
  /// full constructor
  /// </summary>
  public <%= _className %>(<%
  bool first = true;
  foreach( IColumn field in Columns )
  {
   if( !first ) output.write( ", " );
   output.write( ( field.IsInForeignKey && !field.IsInPrimaryKey ? ToPascalCase( field.ForeignKeys[0].PrimaryTable.Alias.Replace( " ", "" ) ) : ColumnToNHibernateType( field ) ) + " " + ColumnToArgumentName( field ) );
   first = false;
  }%>)
  {<%
    foreach( IColumn col in Columns )
    {
     %>
   <%= ColumnToMemberVariable( col ) %> = <%= ColumnToArgumentName( col ) %>; <%
    }
   %>
  }
  #endregion // End Full Constructor<%
 }
 
 private void BuildEqualsHashCodeOverrides( IColumns Columns )
 {
  %>
  #region Equals And HashCode Overrides
  /// <summary>
  /// local implementation of Equals based on unique value members
  /// </summary>
  public override bool Equals( object obj )
  {
   if( this == obj ) return true;
   if( ( obj == null ) || ( obj.GetType() != this.GetType() ) ) return false;
   <%= _className %> castObj = (<%= _className %>)obj; <%
  if( CountUniqueFields( Columns ) == 0 )
  {%>
   return castObj.GetHashCode() == this.GetHashCode()<%
  }
  else
  {%>
   return ( castObj != null )<%
   foreach( IColumn c in Columns )
   {
    if( c.IsInPrimaryKey )
    {
    %> &&
    ( this.<%= ColumnToMemberVariable( c ) %> == castObj.<%= ColumnToPropertyName( c ) %> )<%
    }
   }
  } %>;
  }
  
  /// <summary>
  /// local implementation of GetHashCode based on unique value members
  /// </summary>
  public override int GetHashCode()
  {
   <% if( CountUniqueFields( Columns ) == 0 )
   {
    %>return this.GetType().FullName.GetHashCode();
    <%
   }
   else
   {%>
   int hash = 57; <%
    foreach( IColumn c in Columns )
    {
     if( c.IsInPrimaryKey )
     {
   %>
   hash = 27 * hash * <%= ColumnToMemberVariable( c ) %>.GetHashCode();<%
     }
    }
    %>
   return hash; <%
   }%>
  }
  #endregion
  <%
 }
 
 private void BuildPrivateMembers( IColumns Columns )
 {
  if( Columns.Count > 0 )
  {
   %>
  #region Private Members
  private bool <%= _prefix %>isChanged;
<%  
  foreach( IColumn field in Columns )
  {
   if( field.IsInForeignKey )
   {
    if ( !field.IsInPrimaryKey )
    {
     // A column that's in a fk but not in the pk is an actual foreign key,
     // a many-to-one relationship.  So the member variable is a class instance.
    %>
  private <%= ToPascalCase( field.ForeignKeys[0].PrimaryTable.Alias.Replace( " ", "" ) ) %> <%= ColumnToMemberVariable( field ) %>; <%
    }
    else
    {
     //A column that's in a fk and in the pk represents a fk relationship
     //from another table, a one-to-many relationship.  (This might be
     //a bad assumption for a table with a composite primary key.)
     //So we have to add the pk member variable itself...
     %>
  private <%= ColumnToNHibernateType( field ) %> <%= ColumnToMemberVariable( field ) %>; <%
     
     //... and then we have to add collections for the foreign tables.
     foreach( IForeignKey fk in field.ForeignKeys )
     {
      output.writeln("");
      output.write( "/t/tprivate IList " );
      output.write( _prefix );
      output.write( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) );
      output.write( "List; " );      
     }
    }
   }
   else
   {%>
  private <%= ColumnToNHibernateType( field ) %> <%= ColumnToMemberVariable( field ) %>; <%
   }
  }
%>  
  #endregion
<%
  }
 }
 
 private void BuildInternalAccessors( IColumns Columns )
 {
  if( Columns.Count > 0 )
  {
  %>#region Internal Accessors for NHibernate
  <%
   foreach( IColumn field in Columns )
   {
    string fieldAccessor = ColumnToNHibernateProperty( field );
    string fieldName = ColumnToMemberVariable( field );
   %>
  #region <%= fieldAccessor %>
  /// <summary>
  /// <%= field.Description %>
  /// </summary>
  internal <%= ColumnToNHibernateType( field ) %> <%= fieldAccessor %>
  {
   get { return <%= fieldName %>; }
   set { <%= fieldName %> = value; }
  }
  #endregion
  <%
   }
%>
  #endregion // Internal Accessors for NHibernate <%
  }
 }
 
 private void BuildPublicAccessors( IColumns Columns )
 {
  if( Columns.Count > 0 )
  {
   %>
  #region Public Properties
   <%
   
   foreach( IColumn field in Columns )
   {
    string fieldAccessor = ColumnToPropertyName( field );
    string fieldName = ColumnToMemberVariable( field );
    string fieldType = ( field.IsInForeignKey && !field.IsInPrimaryKey ? ToPascalCase( field.ForeignKeys[0].PrimaryTable.Alias.Replace( " ", "" ) ) : ColumnToNHibernateType( field ) );
    
    output.writeln( "" );
    output.writeln( "/t/t/// <summary>" );

    foreach( string s in field.Description.Split( new char[] { '/n' } ) )
    {
     output.writeln( "/t/t/// " + s );
    }
    output.writeln( "/t/t/// </summary>" );

    output.writeln( "/t/tpublic " + fieldType + " " + fieldAccessor );
    output.writeln( "/t/t{" );
    output.writeln( "/t/t/tget { return " + fieldName + "; }" );

    if( !_createReadOnly )
    {
     //if(!((field.IsInPrimaryKey && field.IsAutoKey) || field.IsComputed))
     //{
      switch( fieldType )
      {
       default:
        output.writeln( "/t/t/tset" );
        output.writeln( "/t/t/t{" );
        
        if( !field.IsNullable && !IsValueType( fieldType ) )
        {
         output.writeln( "/t/t/t/tif( value == null )" );
         output.writeln( "/t/t/t/t/tthrow new ArgumentOutOfRangeException(/"Null value not allowed for " + fieldAccessor + "/", value, /"null/");" );
         output.writeln( "" );
        }
        output.write( "/t/t/t/t" );
        output.write( _prefix );
        output.write( "isChanged |= ( " );
        output.write( fieldName );
        output.writeln( " != value ); " );
        
        output.write( "/t/t/t/t" );
        output.write( fieldName );
        output.writeln( " = value;" );

        output.writeln( "/t/t/t}" );
        break;
       case "byte": %>
   set 
   { <%if( !field.IsNullable )
      {%>
    if( value == null )
     throw new ArgumentOutOfRangeException("Null value not allowed for <%= fieldAccessor %>", value, "null");
    <%}%>
    if( <%if( field.IsNullable ) {%> value != null && <%}%> value.Length > <%= field.CharacterMaxLength.ToString() %>)
     throw new ArgumentOutOfRangeException("Invalid value for <%= fieldAccessor %>", value, value.ToString());
    
    <%= _prefix %>isChanged |= (<%= fieldName %> != value); <%= fieldName %> = value;
   }
<%
        break;
       case "string": %>
   set 
   { <%if( !field.IsNullable )
    {%>
    if( value == null )
     throw new ArgumentOutOfRangeException("Null value not allowed for <%= fieldAccessor %>", value, "null");
    <%}%>
    if( <%if( field.IsNullable ) {%> value != null && <%}%> value.Length > <%= field.CharacterMaxLength.ToString() %>)
     throw new ArgumentOutOfRangeException("Invalid value for <%= fieldAccessor %>", value, value.ToString());
    
    <%= _prefix %>isChanged |= (<%= fieldName %> != value); <%= fieldName %> = value;
   }<%      
        break;
     }
    //}
   }%>
  }
   <%
    if( field.IsInForeignKey && field.IsInPrimaryKey )
    {
     //This means that there are collections implementing
     //one-to-many relationships based on this column.  So
     //we need accessors for those collections, too.
     foreach( IForeignKey fk in field.ForeignKeys )
     {
      output.writeln("");
      output.write( "/t/tpublic IList " );
      output.write( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) );
      output.writeln( "List" ); 
      output.writeln( "/t/t{" );
      output.writeln( "/t/t/tget" );
      output.writeln( "/t/t/t{" );
      output.write( "/t/t/t/treturn " );
      output.write( _prefix );
      output.write( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) );
      output.writeln( "List;" );
      output.writeln( "/t/t/t}" );
      output.writeln( "/t/t/tset" );
      output.writeln( "/t/t/t{" );
      output.write( "/t/t/t/t" );
      output.write( _prefix );
      output.write( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) );
      output.writeln( "List = value;" );
      output.writeln( "/t/t/t}" );
      output.writeln( "/t/t}" );
     }
    }
   }
   
   %>
  /// <summary>
  /// Returns whether or not the object has changed it's values.
  /// </summary>
  public bool IsChanged
  {
   get { return <%= _prefix %>isChanged; }
  }
    
  #endregion
<%
  }
 }
 
 private void BuildPublicFunctions( IColumns Columns )
 {%>
  #region Public Functions
  
  /// <summary>
  /// mark the item as deleted
  /// </summary>
  public void MarkAsDeleted()
  {
   <%= _prefix %>isDeleted = true;
   <%= _prefix %>isChanged = true;
  }
  
  #endregion<%
 }
 
 private void BuildHBMDefinition( IColumns Columns )
 {
  if( Columns.Count > 0 )
  {
   output.writeln( "<?xml version=/"1.0/" encoding=/"utf-8/" ?>" );
   output.writeln( NHibernateMappingTag() );
   output.writeln( "/t" + NHibernateClassTag( Columns ) );
   output.writeln( "/t/t" + NHibernatePrimaryKeysTag( Columns ) );
   output.writeln( "/t/t" + NHibernateProperties( Columns ) );
   output.writeln( "/t</class>" );
   output.writeln( "</hibernate-mapping>" );
  }
 }
 
 private string NHibernateMappingTag()
 {
   can't handle external mappings ?!?
  string xml = "<hibernate-mapping xmlns=/"http://nhibernate.sourceforge.net/schemas/nhibernate-mapping-2.0.xsd/"";
  //string xml = "<hibernate-mapping xmlns=/"urn:nhibernate-mapping-2.0/"";
   handle schemas, cascade, import, and access methods?
  //return xml + ">";
  return "<hibernate-mapping xmlns=/"urn:nhibernate-mapping-2.0/">";
 }
 
 private string NHibernateClassTag( IColumns Columns )
 {
  //ITable t = Columns[0].Table;
  //IView v = Columns[0].View;
  //string desc = ( t == null ) ? v.Description : t.Description;
  StringBuilder xml = new StringBuilder();
  xml.Append( "<class name=/"" ).Append( _nameSpace ).Append( "." ).Append( _className ).Append( "," ).Append( _nameSpace ).Append( "/"" );
  xml.Append( " table=/"" ).Append( _tableName ).Append( "/"" );
  if( _createReadOnly )
  {
   xml.Append( " mutable=/"false/"" );
  }
  // handle schema override, dynamic insert & update, and proxies?
  xml.Append( ">/r/n" );
  return xml.ToString();
 }
 
 private string NHibernatePrimaryKeysTag( IColumns Columns )
 {
  StringBuilder xml = new StringBuilder();
  int i = 0;
  foreach( IColumn c in Columns )
  {
   if( c.IsInPrimaryKey )
   {
    i++;
   }
  }
  if( i == 0 )
  {
   return "<!-- could not find a primary key for this table/view. NHibernate requires an 'id' element, so you'll have to define one manually. -->";
  }
  if( i == 1 )
  {
   foreach( IColumn c in Columns )
   {
    if( c.IsInPrimaryKey )
    {
     xml.Append( "<id name=/"" ).Append( ColumnToPropertyName( c ) ).Append( "/" column=/"" );
     xml.Append( c.Alias ).Append( "/" type=/"" ).Append( ConvertNHibernate( ColumnToNHibernateType( c ) ) ).Append( "/"" );
     switch( ColumnToNHibernateType( c ) )
     {
      case "decimal":
      case "float":
      case "short":
      case "int":
      case "long":
       xml.Append( " unsaved-value=/"0/">/r/n" );
       break;
      default:
       xml.Append( ">/r/n" );
       break;
     }
     xml.Append( "/t/t/t<generator class=/"" );
     xml.Append( ( c.IsAutoKey ) ?  "native" : "assigned" );
     xml.Append( "/"/>/r/n/t/t</id>" );
    }
   }
  }
  if( i > 1 )
  {
   xml.Append( "<!-- composite primary key support is touchy. View the documentation for syntax. -->" );
  }
  return xml.ToString();
 }
 
 private string NHibernateProperties( IColumns Columns )
 {
  StringBuilder xml = new StringBuilder();
  foreach( IColumn c in Columns )
  {
   if( !c.IsInPrimaryKey )
   {
    // create sets & such for foreign keys !!!
    if( c.IsInForeignKey )
    {
     if( c.ForeignKeys.Count > 1 )
     {
      xml.Append( "<!-- more than one foreign column is mapped to " ).Append( c.Name ).Append( " - you're on your own. -->/r/n/t/t" );
     }
     else
     {
      IForeignKey fk = c.ForeignKeys[0];
      xml.Append( "<many-to-one name=/"" )
         .Append( ColumnToPropertyName( c ) )
         .Append( "/" column=/"" )
         .Append( c.Name );
      xml.Append( "/" class=/"" )
         .Append( _nameSpace )
         .Append( "." )
         .Append( ToPascalCase( fk.PrimaryTable.Alias.Replace( " ", "" ) ) )
         .Append( "," )
         .Append( _nameSpace )
         .Append( "/" />/r/n/t/t" );
     }
    }
    else
    {
     xml.Append( "<property column=/"" ).Append( c.Name );
     
     //20061204 增加的支持text、ntext类型的字段
     if(ColumnToNHibernateType( c ) == "string" && (c.CharacterMaxLength == 1073741823 || c.CharacterMaxLength == 2147483647))
      xml.Append( "/" type=/"" ).Append( "StringClob" ).Append( "/"" );
     else
      xml.Append( "/" type=/"" ).Append( ConvertNHibernate( ColumnToNHibernateType( c ) ) ).Append( "/"" );
     
     if( _createReadOnly )
     {
      xml.Append( " access=/"field/" name=/"" ).Append( ColumnToMemberVariable( c ) ).Append( "/"" );
     }
     else
     {
       xml.Append( " name=/"" ).Append( ColumnToPropertyName( c ) ).Append( "/"" );
     }
     if( !c.IsNullable )
     {
      xml.Append( " not-null=/"true/"" );
     }
     if( c.LanguageType == "string" )
     {
      xml.Append( " length=/"" ).Append( c.CharacterMaxLength ).Append( "/"" );
     }
     xml.Append( " />/r/n/t/t" );
    }
   }
   else 
   { // c.IsInPrimaryKey is true here
    if( c.IsInForeignKey )
    {
     //Here's where we handle one-to-many relations.  A column that is in the PK, and is involved in FK relatioships,
     //means it's the one in the one-to-many.
     
     foreach( IForeignKey fk in c.ForeignKeys )
     {
      //Use a bag, since we don't know the real relationship. 
      xml.Append( "<bag ");
      
      //The name for the collection property in the class. 
      //Made from the class name of the "many" side of the
      //relationship, with "List" appended. 
      xml.Append( "name=/"" )
         .Append( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) )
         .Append( "List/" " );
        
      //This means that persisting the class object that contains this
      //collection will not cause the collection's elements to be persisted.
      //You have to navigate the collection and persist them individually.
      xml.Append( "inverse=/"true/" " );
      
      //Lazy loading.  The collection is not filled until the application needs it.
      xml.Append( "lazy=/"true/" " )
         .Append( ">/r/n" );
      
      //The key element specifies the column in the owning class/table that is the
      //foreign key for the collection's class/table.  Note this code only supports
      //single-column foreign keys. 
      if( fk.ForeignColumns.Count > 1 )
      {
       xml.Append( "<!-- Composite foreign keys are not supported in this template. -->/r/n" );
      }
      else
      {
       xml.Append( "/t/t/t<key column=/"" )
          .Append( fk.ForeignColumns[0].Name )
          .Append( "/" />/r/n" );
      }
      
      //the one-to-many tag specifies the class of the objects in the
      //collection, the "many" side. 
      xml.Append( "/t/t/t<one-to-many class=/"" )
         .Append( _nameSpace )
         .Append( "." )
         .Append( ToPascalCase( fk.ForeignTable.Alias.Replace( " ", "" ) ) )
         .Append( "," )
         .Append( _nameSpace )
         .Append( "/" />/r/n" );
      
      //Close the bag tag and indent for the next column.
      xml.Append( "/t/t</bag>/r/n/t/t" );
     }
    }
   }
  }
  return xml.ToString();
 }
 
 private 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 "text":
    retVal = "StringClob";
    break;
   case "string":
    retVal = "String";
    break;
  }
  
  return retVal;
 }
 
 private string ColumnToMemberVariable( IColumn Column )
 {
  return _prefix + UniqueColumn( Column ).ToLower();
 }
 
 private string ColumnToPropertyName( IColumn Column )
 {
  return ToPascalCase( UniqueColumn( Column ) );
 }
 
 private string ColumnFKToClassName( IColumn c )
 {
  return ToPascalCase( c.ForeignKeys[0].PrimaryTable.Alias.Replace( " ", "" ) );
 }
 
 private string ColumnToArgumentName( IColumn Column )
 {
  return UniqueColumn( Column ).ToLower();
 }
 
 private string ColumnToNHibernateProperty( IColumn Column )
 {
  return _prefix + UniqueColumn( Column );
 }
 
 private string UniqueColumn( IColumn Column )
 {
  string c = Column.Alias.Replace( " ", "" );
  if( Column.Table != null && Column.Table.Alias.Replace( " ", "" ) == c )
  {
   c += "Name";
  }
  if( Column.View != null && Column.View.Alias.Replace( " ", "" ) == c )
  {
   c += "Name";
  }
  return c;
 }
 
 // nhibernate doesn't have these, so use the existing types
 private string ColumnToNHibernateType( IColumn Column )
 {
  string retVal = Column.LanguageType;
  
  switch( Column.LanguageType )
  {
   case "sbyte":
    retVal = "byte";
    break;
   case "uint":
    retVal = "int";
    break;
   case "ulong":
    retVal = "long";
    break;
   case "ushort":
    retVal = "short";
    break;
  }
  
  return retVal;
 }
 
 private bool IsValueType( string type )
 {
  switch( type )
  {
   case "sbyte":
   case "byte":
   case "short":
   case "ushort":
   case "int":
   case "uint":
   case "long":
   case "ulong":
   case "char":
   case "float":
   case "double":
   case "bool":
   case "decimal":
   case "DateTime":
    return true;
    break;
    
   default:
    return false;
    break;
  }
 }
 
 private string ToLeadingCaps( string name )
 {
  char[] chars = name.ToLower().ToCharArray();
  chars[0] = Char.ToUpper( chars[0] );
  return new string( chars );
 }
 
 private string ToLeadingLower( string name )
 {
  char[] chars = name.ToCharArray();
  chars[0] = Char.ToLower( chars[0] );
  return new string( chars );
 }
 
 private string ToPascalCase( string name )
 {
  string notStartingAlpha = Regex.Replace( name, "^[^a-zA-Z]+", "" );
  string workingString = ToLowerExceptCamelCase( notStartingAlpha );
  workingString = RemoveSeparatorAndCapNext( workingString );
  return workingString;
 }
 
 private string RemoveSeparatorAndCapNext( string input )
 {
  string dashUnderscore = "-_";
  string workingString = input;
  char[] chars = workingString.ToCharArray();
  int under = workingString.IndexOfAny( dashUnderscore.ToCharArray() );
  while( under > -1 )
  {
   chars[ under + 1 ] = Char.ToUpper( chars[ under + 1 ], CultureInfo.InvariantCulture );
   workingString = new String( chars );
   under = workingString.IndexOfAny( dashUnderscore.ToCharArray(), under + 1 );
  }
  chars[ 0 ] = Char.ToUpper( chars[ 0 ], CultureInfo.InvariantCulture );
  workingString = new string( chars );
  return Regex.Replace( workingString, "[-_]", "" );
 }

 private string ToLowerExceptCamelCase( string input )
 {
  char[] chars = input.ToCharArray();
  for( int i = 0; i < chars.Length; i++ )
  {
   int left = ( i > 0 ? i - 1 : i );
   int right = ( i < chars.Length - 1 ? i + 1 : i );
   if( i != left && i != right )
   {
    if( Char.IsUpper( chars[i] ) && Char.IsLetter( chars[ left ] ) && Char.IsUpper( chars[ left ] ) )
    {
     chars[i] = Char.ToLower( chars[i], CultureInfo.InvariantCulture );
    }
    else if( Char.IsUpper( chars[i] ) && Char.IsLetter( chars[ right ] ) && Char.IsUpper( chars[ right ] ) )
    {
     chars[i] = Char.ToLower( chars[i], CultureInfo.InvariantCulture );
    }
    else if( Char.IsUpper( chars[i] ) && !Char.IsLetter( chars[ right ] ) )
    {
     chars[i] = Char.ToLower( chars[i], CultureInfo.InvariantCulture );
    }
   }
  }
  chars[ chars.Length - 1 ] = Char.ToLower( chars[ chars.Length - 1 ], CultureInfo.InvariantCulture );
  return new string( chars );
 }
 
 private int CountRequiredFields( IColumns Columns )
 {
  return Columns.Count - CountNullableFields( Columns );
 }
 
 private int CountNullableFields( IColumns Columns )
 {
  int i = 0;
  foreach( IColumn c in Columns )
  {
   if( c.IsNullable )
   {
    i++;
   }
  }
  return i;
 }
 
 private int CountUniqueFields( IColumns Columns )
 {
  int i = 0;
  foreach( IColumn c in Columns )
  {
   if( !c.IsNullable && c.IsInPrimaryKey )
   {
    i++;
   }
  }
  return i;
 }
}
%>
##|BODY_END

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值