質問

So I have a class:

  public class objWalkdown {
    private objWalkdown_ID _walkdownId = new objWalkdown_ID();
    public virtual objWalkdown_ID Id {
      get { return _walkdownId; }
      set { _walkdownId = value; }
    }
    public virtual String facility {
      get { return _walkdownId.facility; }
      set { _walkdownId.facility = value; }
    }
    public virtual String walkdown {
      get { return _walkdownId.walkdown; }
      set { _walkdownId.walkdown = value; }
    }
    public virtual String activity {
      get { return _walkdownId.activity; }
      set { _walkdownId.activity = value; }
    }
    public virtual Boolean complete { get; set; }
    public virtual Byte[] filedata { get; set; }
  }

That utilizes a composite id setup in another class:

[Serializable]
  public class objWalkdown_ID {
    public virtual String facility { get; set; }
    public virtual String walkdown { get; set; }
    public virtual String activity { get; set; }
  }

From my research this serialized composite key is required in order to facilitate lazy loading on a property (i.e. a regular composite key setup will not work),shown here is my Fluent NNibernate mapping class:

  public class objWalkdown_ORM : ClassMap<objWalkdown> {
    public objWalkdown_ORM() {
      Id(x => x.Id);
      Map(x => x.facility);
      Map(x => x.walkdown);
      Map(x => x.activity);
      Map(x => x.complete);
      Map(x => x.filedata)
        .CustomType("BinaryBlob")
        .LazyLoad();
      Table("tbPDFs");
    }
  }

And this 100% works when NHibernate was hooked up to my SQLite test database, but when moved to SQL Server 2008 things broke a bit. The only real DB changes being the SQLite BINARY type to the SQL Server 2008 VARBINARY(MAX) type. However with lazy loading disabled everything works on both sides, it's only when my property is tagged with the lazy loading option that things start to break. Here is a sample of how I'm accessing the data:

public Stream getWalkdown(String Facility, String Walkdown, String Activity) {
//Use NHibernate Session setup "Per-Request"
  ISession session = (ISession)HttpContext.Current.Items["NHSession"];
//Build composite Id
  objWalkdown_ID id = new objWalkdown_ID() { facility = Facility, walkdown = Walkdown, activity = Activity };
//Get the entity
  objWalkdown walkdown = session.Get<objWalkdown>(id);
//Lazy Load File Data and return a memory stream
  return new MemoryStream(walkdown.filedata);
}

Please focus on the lazy loading portion and don't ask me to not use it, the purpose of this question is to determine exactly what is wrong with the lazy loading. Like I stated, using SQLite this functions 100%. It will also work under both SQLite and SQL Server 2008 if the lazy loading is removed, so I don't think it's the actual data types on the back end.

The specific error I encounter, when inspecting the walkdown object (prior to the lazy load) is "System.InvalidOperationException - Invalid attempt to read when no data is present". However there definitely is data present. So I'm thinking this is an issue with the NHibernate proxy.

Here is a stack trace:

   at System.Data.SqlClient.SqlDataReader.ReadColumnHeader(Int32 i)
   at System.Data.SqlClient.SqlDataReader.IsDBNull(Int32 i)
   at NHibernate.Driver.NHybridDataReader.IsDBNull(Int32 i)
   at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name)
   at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
   at NHibernate.Persister.Entity.AbstractEntityPersister.InitializeLazyPropertiesFromDatastore(String fieldName, Object entity, ISessionImplementor session, Object id, EntityEntry entry)
   at NHibernate.Persister.Entity.AbstractEntityPersister.InitializeLazyProperty(String fieldName, Object entity, ISessionImplementor session)
   at NHibernate.Intercept.AbstractFieldInterceptor.InitializeField(String fieldName, Object target)
   at NHibernate.Intercept.AbstractFieldInterceptor.Intercept(Object target, String fieldName, Object value)
   at NHibernate.Intercept.DefaultDynamicLazyFieldInterceptor.Intercept(InvocationInfo info)
   at objWalkdownProxy.get_filedata()

I hope someone can give me some advice on a proper solution. I already have a work around, but it involves HQL and eagerly loading an entity when I require the file data, which is not what I want to be doing.

役に立ちましたか?

解決

Unfortunately, the answer was... a glitch. Something went wrong or corrupted the table in MSSQL2008. During my testing/debugging I created a brand new table with the exact same specifications and everything works 100%.

One thing I would like to note though, is that during my research I found out that a Primary Key in MSSQL2008 can only be 900 bytes in size, and that if I ever wanted to have NHibernate generate my schema for me I should really put a .Length(900) on the Id field.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top