These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: How to ignore null id in entry error
PostPosted: Sun Jun 10, 2007 11:43 pm 
Beginner
Beginner

Joined: Fri Jan 12, 2007 1:08 am
Posts: 41
I am loading data into a table using NHibernate. There will be occasional errors e.g. strings too long for the mapped database column. I want to avoid performing this validation in the code. Instead I want the database exception to be generated and then handled appropriately by the application. The problem is that when the session is flushed I receive the dreaded "null id in entry (don't flush the Session after an exception occurs)" error. Is there anything that I can do to avoid this?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 14, 2007 12:13 pm 
Beginner
Beginner

Joined: Fri Jan 12, 2007 1:08 am
Posts: 41
I was not exactly overwhelmed with responses so I came up with a solution myself. It will only currently work for SQL Server and for classes that use a SingleTableEntityPersister and some of the concerns need to be separted out but it's a start:

Code:
/// <summary>
/// Validates the length of strings in a persistent class.
/// </summary>
public class StringValidator : IStringValidator
{
   private Type _currentType;
   private SingleTableEntityPersister _persister;
   private Dictionary<int, string> _propertyNames;
   private Dictionary<int, string> _columnMappings;
   private Dictionary<string, int> _columnSizes;

   /// <summary>
   /// Determines whether an instance of type T is valid by comparing the length of any strings to the maximum length
   /// defined in the database
   /// </summary>
   /// <typeparam name="T">The type</typeparam>
   /// <param name="instance">The instance</param>
   /// <returns>The result</returns>
   public bool IsValid<T>(T instance)
   {
      if (instance == null) return true;
      Initialize<T>();
      foreach (int position in _columnMappings.Keys)
      {
         if (GetValueLength(_propertyNames[position], instance) > GetMaxLength(_columnMappings[position]))
         {
            return false;
         }
      }
      return true;
   }

   /// <summary>
   /// Determines whether a list of instances of type T are valid by comparing the length of any strings to the maximum length
   /// defined in the database
   /// </summary>
   /// <typeparam name="T">The type</typeparam>
   /// <param name="instanceList">The instance list</param>
   /// <returns>the result</returns>
   public bool IsListValid<T>(IEnumerable<T> instanceList)
   {
      foreach (T instance in instanceList)
      {
         if (!IsValid(instance))
         {
            return false;
         }
      }
      return true;
   }

   /// <summary>
   /// Determines whether initialization is required
   /// </summary>
   /// <typeparam name="T">The type</typeparam>
   /// <returns>The result</returns>
   public bool ShouldInitialize<T>()
   {
      return _currentType == null || typeof(T) != _currentType;
   }

   /// <summary>
   /// Initializes the class if required
   /// </summary>
   /// <typeparam name="T">The type</typeparam>
   public void Initialize<T>()
   {
      if (ShouldInitialize<T>())
      {
         _persister =
            (SingleTableEntityPersister)
            NHibernateSessionManager.Instance.GetSession().SessionFactory.GetClassMetadata(typeof(T));
         _propertyNames = GetPropertyNames();
         _columnMappings = GetStringMappings();
         _columnSizes = GetColumnSizes();
         _currentType = typeof(T);
      }
   }

   /// <summary>
   /// Returns a Dictionary of properties that are strings keyed by the index of the property
   /// </summary>
   /// <returns>The Dictionary</returns>
   public Dictionary<int, string> GetPropertyNames()
   {
      Dictionary<int, string> propertyNames = new Dictionary<int, string>();
      for (int i = 0; i < _persister.PropertyTypes.Length; i++)
      {
         if (_persister.PropertyTypes[i] is StringType)
         {
            propertyNames.Add(i, _persister.PropertyNames[i]);
         }
      }
      return propertyNames;
   }

   /// <summary>
   /// Retiurns a Dictionary of database column names that are mapped to strings, keyed by the index of the property
   /// </summary>
   /// <returns>The Dictionary</returns>
   public Dictionary<int, string> GetStringMappings()
   {
      Dictionary<int, string> columnMapping = new Dictionary<int, string>();
      for (int i = 0; i < _persister.PropertyTypes.Length; i++)
      {
         if (_persister.PropertyTypes[i] is StringType)
         {
            columnMapping.Add(i, _persister.GetPropertyColumnNames(i)[0]);
         }
      }
      return columnMapping;
   }

   /// <summary>
   /// Returns a Dictionary of database column sizes for the varchar data type from the table that type T is mapped
   /// to, keyed by the column name
   /// </summary>
   /// <returns>The Dictioary</returns>
   public Dictionary<string, int> GetColumnSizes()
   {
      Dictionary<string, int> columnSizes = new Dictionary<string, int>();
      ISQLQuery q =
         NHibernateSessionManager.Instance.GetSession().CreateSQLQuery(
            "select c.name, c.max_length from sys.columns c inner join sys.tables t" +
            " on c.object_id = t.object_id where t.name = :p0 and c.system_type_id = 167");
      q.SetString("p0", GetTableName());
      q.AddScalar("name", NHibernateUtil.String);
      q.AddScalar("max_length", NHibernateUtil.Int32);
      IList results = q.List();
      foreach (object[] o in results)
      {
         columnSizes.Add(o[0].ToString(), int.Parse(o[1].ToString()));
      }
      return columnSizes;
   }

   /// <summary>
   /// Removes the database, schema etc. from the table that type T is mapped to
   /// </summary>
   /// <returns>The table name</returns>
   public string GetTableName()
   {
      return _persister.TableName.Substring(_persister.TableName.LastIndexOf('.') + 1);
   }

   /// <summary>
   /// Returns the length of the string for the supplied property in the supplied instance
   /// </summary>
   /// <typeparam name="T">The type</typeparam>
   /// <param name="propertyName">The property name</param>
   /// <param name="instance">The instance</param>
   /// <returns>The length</returns>
   public int GetValueLength<T>(string propertyName, T instance)
   {
      object tmp = typeof(T).GetProperty(propertyName).GetValue(instance, null);
      return tmp == null || tmp.ToString() == null
                ? 0
                : tmp.ToString().Length;
   }

   /// <summary>
   /// Returns the max length in the database for the supplied property
   /// </summary>
   /// <param name="propertyName">The property name</param>
   /// <returns>The length</returns>
   public int GetMaxLength(string propertyName)
   {
      return _columnSizes[propertyName];
   }
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.