Hi,
I've been trying to determine if this is a problem with my code, Castle, or NHibernate, so far I am not sure but I would like to think it is not my code.
Basically everything was working fine but not a fast as I would like, so doing some research I found lazy loading and using a read only scope may help. I setup a SessionScope for read only, and the lazy loading. So far, so good. (The SessionScope Code may look familiar)
Code:
public class CustomReadOnlyScope : SessionScope
{
protected override void PerformDisposal(ICollection sessions)
{
PerformDisposal(sessions, false, true);
}
}
And an example of one of my ActiveRecord Classes. They are all set up similar.
Code:
[ActiveRecord(Table=FSAppService.MODULE_TABLE,
Lazy=true)]
public class CARModule : CustomActiveRecordBase<CARModule>
{
private long id;
private String name;
private String description;
private CARApplication application;
private IList versionModules = new ArrayList();
public CARModule()
{
}
[PrimaryKey(PrimaryKeyType.Custom,
FSAppService.MODULEID_FIELD,
CustomGenerator=typeof(MagicGenerator))]
public virtual long Id
{
get{ return id; }
set{ id = value; }
}
[Property(FSAppService.NAME_FIELD)]
public virtual String Name
{
get{ return name; }
set{ name = value; }
}
[Property(FSAppService.DESCRIPTION_FIELD,
ColumnType="StringClob")]
public virtual String Description
{
get{ return description; }
set{ description = value; }
}
[BelongsTo(FSAppService.APPLICATIONID_FIELD)]
public virtual CARApplication Application
{
get{ return application; }
set{ application = value; }
}
[HasMany(typeof(CARVersionModule),
Inverse=true,
Cascade=ManyRelationCascadeEnum.AllDeleteOrphan,
Lazy=true)]
public virtual IList VersionModules
{
get{ return versionModules; }
set{ versionModules = value; }
}
}
I have a bunch of web methods which make use of the ActiveRecord Classes I created. Adding entries, deleting entries all seem to work fine. calls to Castle.ActiveRecord.FindAll() work too. But when I make a call to Find(primaryKey), then things start to break, such as in the following example:
Code:
[WebMethod()]
public long AddModule(string session, string name, string description, long applicationId)
{
DateTime start = new DateTime();
start = DateTime.Now;
CheckPrivilege(session);
if( String.IsNullOrEmpty(name) )
{
throw new ArgumentException("Error: AddModule:\n" +
"Module name cannot be empty");
}
try
{
using(new CustomReadOnlyScope())
{
CARApplication application = CARApplication.Find(applicationId);
CARModule module = new CARModule();
module.Name = name;
if( String.IsNullOrEmpty(description) )
{
module.Description = "";
}
else
{
module.Description = description;
}
module.Application = application;
module.CreateAndFlush();
this.ElaspedTime("AddModule", start);
return module.Id;
}
}
catch(Exception ex)
{
Console.WriteLine("Error: AddModule:\n" +
ex.ToString());
throw;
}
}
and finally the stack trace:
Code:
Error: AddModule:
Castle.ActiveRecord.Framework.ActiveRecordException: Could not perform FindByPrimaryKey for CARApplication. Id: 5000010914 ---> NHibernate.HibernateException: Creating a proxy instance failed ---> System.ArgumentNullException: Argument cannot be null.
Parameter name: method
at System.Reflection.Emit.ILGenerator.Emit (OpCode opcode, System.Reflection.MethodInfo method) [0x00099] in /mono/source/mono-1.2.3/mono-1.2.3/mcs/class/corlib/System.Reflection.Emit/ILGenerator.cs:720
at Castle.DynamicProxy.Builder.CodeBuilder.SimpleAST.MethodTokenExpression.Emit (IEasyMember member, System.Reflection.Emit.ILGenerator gen) [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.SimpleAST.MethodInvocationExpression.Emit (IEasyMember member, System.Reflection.Emit.ILGenerator gen) [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.SimpleAST.AssignStatement.Emit (IEasyMember member, System.Reflection.Emit.ILGenerator gen) [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.AbstractCodeBuilder.Generate (IEasyMember member, System.Reflection.Emit.ILGenerator il) [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.EasyMethod.Generate () [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.EasyProperty.Generate () [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.AbstractEasyType.EnsureBuildersAreInAValidState () [0x00000]
at Castle.DynamicProxy.Builder.CodeBuilder.AbstractEasyType.BuildType () [0x00000]
at Castle.DynamicProxy.Builder.CodeGenerators.BaseCodeGenerator.CreateType () [0x00000]
at Castle.DynamicProxy.Builder.CodeGenerators.ClassProxyGenerator.GenerateCode (System.Type baseClass, System.Type[] interfaces) [0x00000]
at Castle.DynamicProxy.Builder.DefaultProxyBuilder.CreateClassProxy (System.Type theClass, System.Type[] interfaces) [0x00000]
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy (System.Type baseClass, System.Type[] interfaces, IInterceptor interceptor, Boolean checkAbstract, System.Object[] argumentsForConstructor) [0x00000]
at NHibernate.Proxy.CastleProxyFactory.GetProxy (System.Object id, ISessionImplementor session) [0x00000] --- End of inner exception stack trace ---
at NHibernate.Proxy.CastleProxyFactory.GetProxy (System.Object id, ISessionImplementor session) [0x00000]
at NHibernate.Persister.Entity.AbstractEntityPersister.CreateProxy (System.Object id, ISessionImplementor session) [0x00000]
at NHibernate.Impl.SessionImpl.DoLoadByClass (System.Type clazz, System.Object id, Boolean checkDeleted, Boolean allowProxyCreation) [0x00000]
at NHibernate.Impl.SessionImpl.Load (System.Type clazz, System.Object id) [0x00000]
at Castle.ActiveRecord.ActiveRecordBase.FindByPrimaryKey (System.Type targetType, System.Object id, Boolean throwOnNotFound) [0x00000] --- End of inner exception stack trace ---
at Castle.ActiveRecord.ActiveRecordBase.FindByPrimaryKey (System.Type targetType, System.Object id, Boolean throwOnNotFound) [0x00000]
at Castle.ActiveRecord.ActiveRecordBase`1[Custom.Web.Services.AppService.CARApplication].Find (System.Object ) [0x00000]
at Custom.Web.Services.AppService.FSAppService.AddModule (System.String session, System.String name, System.String description, Int64 applicationId) [0x00000]
So, I've looked at this for a while and I'm not sure where my problem is. If it is a Castle problem, a problem with Castle.DynamicProxy.dll, NHibernate. Any insight on this situation would be great and much appreciated.
Thank you,
Louis