Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I was so far and yet so close. Of course, it turns out we can access the dependent property from the IDataReader in the NullSafeGet method.</p> <p>A complete(-ish) solution is here:</p> <p>Firstly let us define a fluent mapping:</p> <pre><code> public class AMap : ClassMap&lt;A&gt; { public AMap() { Id(x =&gt; x.Id); Map(x =&gt; x.SomeString); Map(x =&gt; x.SpecialProperty) .CustomType(typeof (DependentProperty)) ; } static object DeserialiseSpecialProperty(string SomeString, byte[] specialProperty) { // ... } static byte[] SerialiseSpecialProperty(object specialProperty) { // ... } } </code></pre> <p>Now, implement DependentProperty.</p> <pre><code>public class DependentProperty: IUserType { // change SqlTypes appropriatelly if your backing field is something else public SqlType[] SqlTypes { get { return new[] {new SqlType(DbType.Binary)}; } } public Type ReturnedType { get { return typeof (object); } } public bool IsMutable { get { return false; } } public int GetHashCode(object x) { if (x == null) return 0; return x.GetHashCode(); } public object NullSafeGet(IDataReader rs, string[] names, object owner) { var SomeString = (string)rs.GetValue(1); object obj = NHibernateUtil.Binary.NullSafeGet(rs, names[0]); return AMap.DeserialiseSpecialProperty(SomeString, (byte[])obj); } public void NullSafeSet(IDbCommand cmd, object value, int index) { if (value == null) ((IDataParameter) cmd.Parameters[index]).Value = DBNull.Value; else ((IDataParameter)cmd.Parameters[index]).Value = AMap.DeserialiseSpecialProperty(value); } public object DeepCopy(object value) { return value; } public object Replace(object original, object target, object owner) { return original; } public object Assemble(object cached, object owner) { return cached; } public object Disassemble(object value) { return value; } bool IUserType.Equals(object x, object y) { return object.Equals(x, y); } } </code></pre> <p>Notes:</p> <ol> <li><p>The IUserType implementation is based on a template from <a href="http://nhibernate.info/blog/2009/10/15/mapping-different-types-iusertype.html" rel="nofollow noreferrer">a nhibernate.info tutorial</a>. It should be fine for value types, but if you are doing anything complex with reference types or deep object graphs, you may have to provide different implementations for the various methods. </p></li> <li><p>Due to directly accessing the IDataReader this is <strong>VERY BRITTLE</strong>. Changes to the order of mappings in AMap will most likely require you to update the index accessed. Quite possibly other changes to AMap (and maybe even A) could also break this implementation. </p> <p>This is unpleasant, yes, but then so is having to store persistence fields (and custom serialiser/deserialiser baggage) directly in your business objects and having them called every time the external property is get/set'd. I would argue that a broken index should be picked up by your persistence validation and this implementation should lead to a generally cleaner separation of business/persistence concerns.</p></li> <li><p>Combine this with (pimp my post?) <a href="https://stackoverflow.com/questions/1213728/is-it-possible-to-use-sqlite-manifest-typing-features-in-nhibernate">sqlite's manifest typing capabilities</a> and you can do some very cool dynamic typing stuff :)</p></li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload