Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

August 2012 - Posts

NHibernate Pitfalls: Custom Types and Detecting Changes

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

NHibernate supports the declaration of properties of user-defined types, that is, not entities, collections or primitive types. These are used for mapping a database columns, of any type, into a different type, which may not even be an entity; think, for example, of a custom user type that converts a BLOB column into an Image.

User types must implement interface NHibernate.UserTypes.IUserType. This interface specifies an Equals method that is used for comparing two instances of the user type. If this method returns false, the entity is marked as dirty, and, when the session is flushed, will trigger an UPDATE. So, in your custom user type, you must implement this carefully so that it is not mistakenly considered changed. For example, you can cache the original column value inside of it, and compare it with the one in the other instance.

Let’s see an example implementation of a custom user type that converts a Byte[] from a BLOB column into an Image:

   1: [Serializable]
   2: public sealed class ImageUserType : IUserType
   3: {
   4:     private Byte[] data = null;
   5:  
   6:     public ImageUserType()
   7:     {
   8:         this.ImageFormat = ImageFormat.Png;
   9:     }
  10:  
  11:     public ImageFormat ImageFormat
  12:     {
  13:         get;
  14:         set;
  15:     }
  16:  
  17:     public Boolean IsMutable
  18:     {
  19:         get
  20:         {
  21:             return (true);
  22:         }
  23:     }
  24:  
  25:     public Object Assemble(Object cached, Object owner)
  26:     {
  27:         return (cached);
  28:     }
  29:  
  30:     public Object DeepCopy(Object value)
  31:     {
  32:         return (value);
  33:     }
  34:  
  35:     public Object Disassemble(Object value)
  36:     {
  37:         return (value);
  38:     }
  39:  
  40:     public new Boolean Equals(Object x, Object y)
  41:     {
  42:         return (Object.Equals(x, y));
  43:     }
  44:  
  45:     public Int32 GetHashCode(Object x)
  46:     {
  47:         return ((x != null) ? x.GetHashCode() : 0);
  48:     }
  49:  
  50:     public override Int32 GetHashCode()
  51:     {
  52:         return ((this.data != null) ? this.data.GetHashCode() : 0);
  53:     }
  54:  
  55:     public override Boolean Equals(Object obj)
  56:     {
  57:         ImageUserType other = obj as ImageUserType;
  58:  
  59:         if (other == null)
  60:         {
  61:             return (false);
  62:         }
  63:  
  64:         if (Object.ReferenceEquals(this, other) == true)
  65:         {
  66:             return (true);
  67:         }
  68:  
  69:         return (this.data.SequenceEqual(other.data));
  70:     }
  71:  
  72:     public Object NullSafeGet(IDataReader rs, String[] names, Object owner)
  73:     {
  74:         Int32 index = rs.GetOrdinal(names[0]);
  75:         Byte[] data = rs.GetValue(index) as Byte[];
  76:  
  77:         this.data = data as Byte[];
  78:  
  79:         if (data == null)
  80:         {
  81:             return (null);
  82:         }
  83:  
  84:         using (MemoryStream stream = new MemoryStream(this.data ?? new Byte[0]))
  85:         {
  86:             return (Image.FromStream(stream));
  87:         }
  88:     }
  89:  
  90:     public void NullSafeSet(IDbCommand cmd, Object value, Int32 index)
  91:     {
  92:         if (value != null)
  93:         {
  94:             Image data = value as Image;
  95:  
  96:             using (MemoryStream stream = new MemoryStream())
  97:             {
  98:                 data.Save(stream, this.ImageFormat);
  99:                 value = stream.ToArray();
 100:             }
 101:         }
 102:  
 103:         (cmd.Parameters[index] as DbParameter).Value = value ?? DBNull.Value;
 104:     }
 105:  
 106:     public Object Replace(Object original, Object target, Object owner)
 107:     {
 108:         return (original);
 109:     }
 110:  
 111:     public Type ReturnedType
 112:     {
 113:         get
 114:         {
 115:             return (typeof(Image));
 116:         }
 117:     }
 118:  
 119:     public SqlType[] SqlTypes
 120:     {
 121:         get
 122:         {
 123:             return (new SqlType[] { new SqlType(DbType.Binary) });
 124:         }
 125:     }
 126: }

In this case, we need to cache the original Byte[] data because it’s not easy to compare two Image instances, unless, of course, they are the same.

ASP.NET Web Forms Extensibility: Handler Factories

An handler factory is the class that implements IHttpHandlerFactory and is responsible for instantiating an handler (IHttpHandler) that will process the current request. This is true for all kinds of web requests, whether they are for ASPX pages, ASMX/SVC web services, ASHX/AXD handlers, or any other kind of file. Also used for restricting access for certain file types, such as Config, Csproj, etc.

Handler factories are registered on the global Web.config file, normally located at %WINDIR%\Microsoft.NET\Framework<x64>\vXXXX\Config for a given path and request type (GET, POST, HEAD, etc). This goes on section <httpHandlers>.

You would create a custom handler factory for a number of reasons, let me list just two:

  • A centralized place for using dependency injection;
  • Also a centralized place for invoking custom methods or performing some kind of validation on all pages.

Let’s see an example using Unity for injecting dependencies into a page, suppose we have this on Global.asax.cs:

   1: public class Global : HttpApplication
   2: {
   3:     internal static readonly IUnityContainer Unity = new UnityContainer();
   4:  
   5:     void Application_Start(Object sender, EventArgs e)
   6:     {
   7:         Unity.RegisterType<IFunctionality, ConcreteFunctionality>();
   8:     }
   9: }

We instantiate Unity and register a concrete implementation for an interface, this could/should probably go in the Web.config file. Forget about its actual definition, it’s not important.

Then, we create a custom handler factory:

   1: public class UnityPageHandlerFactory : PageHandlerFactory
   2: {
   3:     public override IHttpHandler GetHandler(HttpContext context, String requestType, String virtualPath, String path)
   4:     {
   5:         IHttpHandler handler = base.GetHandler(context, requestType, virtualPath, path);
   6:         
   7:         //one scenario: inject dependencies
   8:         Global.Unity.BuildUp(handler.GetType(), handler, String.Empty);
   9:  
  10:         return (handler);
  11:     }
  12: }

It inherits from PageHandlerFactory, which is .NET’s included factory for building regular ASPX pages. We override the GetHandler method and issue a call to the BuildUp method, which will inject required dependencies, if any exist.

An example page with dependencies might be:

   1: public class SomePage : Page
   2: {
   3:     [Dependency]
   4:     public IFunctionality Functionality
   5:     {
   6:         get;
   7:         set;
   8:     }
   9: }

Notice the DependencyAttribute, it is used by Unity to identify properties that require dependency injection. When BuildUp is called, the Functionality property (or any other properties with the DependencyAttribute attribute) will receive the concrete implementation associated with it’s type, as registered on Unity.

Another example, checking a page for authorization. Let’s define an interface first:

   1: public interface IRestricted
   2: {
   3:     Boolean Check(HttpContext ctx);
   4: }

An a page implementing that interface:

   1: public class RestrictedPage : Page, IRestricted
   2: {
   3:     public Boolean Check(HttpContext ctx)
   4:     {
   5:         //check the context and return a value
   6:         return ...;
   7:     }
   8: }

For this, we would use an handler factory such as this:

   1: public class RestrictedPageHandlerFactory : PageHandlerFactory
   2: {
   3:     private static readonly IHttpHandler forbidden = new UnauthorizedHandler();
   4:  
   5:     public override IHttpHandler GetHandler(HttpContext context, String requestType, String virtualPath, String path)
   6:     {
   7:         IHttpHandler handler = base.GetHandler(context, requestType, virtualPath, path);
   8:         
   9:         if (handler is IRestricted)
  10:         {
  11:             if ((handler as IRestricted).Check(context) == false)
  12:             {
  13:                 return (forbidden);
  14:             }
  15:         }
  16:  
  17:         return (handler);
  18:     }
  19: }
  20:  
  21: public class UnauthorizedHandler : IHttpHandler
  22: {
  23:     #region IHttpHandler Members
  24:  
  25:     public Boolean IsReusable
  26:     {
  27:         get { return (true); }
  28:     }
  29:  
  30:     public void ProcessRequest(HttpContext context)
  31:     {
  32:         context.Response.StatusCode = (Int32) HttpStatusCode.Unauthorized;
  33:         context.Response.ContentType = "text/plain";
  34:         context.Response.Write(context.Response.Status);
  35:         context.Response.Flush();
  36:         context.Response.Close();
  37:         context.ApplicationInstance.CompleteRequest();
  38:     }
  39:  
  40:     #endregion
  41: }

The UnauthorizedHandler is an example of an IHttpHandler that merely returns an error code to the client, but does not cause redirection to the login page, it is included merely as an example.

One thing we must keep in mind is, there can be only one handler factory registered for a given path/request type (verb) tuple. A typical registration would be:

   1: <httpHandlers>
   2:     <remove path="*.aspx" verb="*"/>
   3:     <add path="*.aspx" verb="*" type="MyNamespace.MyHandlerFactory, MyAssembly"/>
   4: </httpHandlers>

First we remove the previous registration for ASPX files, and then we register our own.

And that’s it. A very useful mechanism which I use lots of times.

ASP.NET Web Forms Extensibility: Providers

Updated on August 28th to add the Virtual Path provider. Thanks, Matthew Schaad!

Introduction

This will be the first of a number of posts on ASP.NET extensibility. At this moment I don’t know exactly how many will be and I only know a couple of subjects that I want to talk about, so more will come in the next days.

I have the sensation that the providers offered by ASP.NET are not widely know, although everyone uses, for example, sessions, they may not be aware of the extensibility points that Microsoft included. This post won’t go into details of how to configure and extend each of the providers, but will hopefully give some pointers on that direction.

Canonical

These are the most widely known and used providers, coming from ASP.NET 1, chances are, you have used them already. Good support for invoking client side, either from a .NET application or from JavaScript. Lots of server-side controls use them, such as the Login control for example.

Membership

The Membership provider is responsible for managing registered users, including creating new ones, authenticating them, changing passwords, etc. ASP.NET comes with two implementations, one that uses a SQL Server database and another that uses the Active Directory. The base class is Membership and new providers are registered on the membership section on the Web.config file, as well as parameters for specifying minimum password lengths, complexities, maximum age, etc. One reason for creating a custom provider would be, for example, storing membership information in a different database engine.

   1: <membership defaultProvider="MyProvider">
   2:   <providers>
   3:     <add name="MyProvider" type="MyClass, MyAssembly"/>
   4:   </providers>
   5: </membership>

Role

The Role provider assigns roles to authenticated users. The base class is Role and there are three out of the box implementations: XML-based, SQL Server and Windows-based. Also registered on Web.config through the roleManager section, where you can also say if your roles should be cached on a cookie. If you want your roles to come from a different place, implement a custom provider.

   1: <roleManager defaultProvider="MyProvider">
   2:   <providers>
   3:     <add name="MyProvider" type="MyClass, MyAssembly" />
   4:   </providers>
   5: </roleManager>

Profile

The Profile provider allows defining a set of properties that will be tied and made available to authenticated or even anonymous ones, which must be tracked by using anonymous authentication. The base class is Profile and the only included implementation stores these settings in a SQL Server database. Configured through profile section, where you also specify the properties to make available, a custom provider would allow storing these properties in different locations.

   1: <profile defaultProvider="MyProvider">
   2:   <providers>
   3:     <add name="MyProvider" type="MyClass, MyAssembly"/>
   4:   </providers>
   5: </profile>

Basic

OK, I didn’t know what to call these, so Basic is probably as good as a name as anything else. Not supported client-side (doesn’t even make sense).

Virtual Path

The Virtual Path provider allows content to come from sources other than the filesystem (think of a ZIP file, a database, etc). That's the mechanism SharePoint uses.
In order to use it, you must implement the base classes VirtualPathProvider, VirtualFile and VirtualDirectory. Registration is done by code, typically on Global.asax.cs:

   1: protected void Application_Start(Object sender, EventArgs e)
   2: {
   3:     HostingEnvironment.RegisterVirtualPathProvider(new CustomVirtualPathProvider());
   4: }

Session

The Session provider allows storing data tied to the current “session”, which is normally created when a user first accesses the site, even when it is not yet authenticated, and remains all the way. The base class and only included implementation is SessionStateStoreProviderBase and it is capable of storing data in one of three locations:

  • In the process memory (default, not suitable for web farms or increased reliability);
  • A SQL Server database (best for reliability and clustering);
  • The ASP.NET State Service, which is a Windows Service that is installed with the .NET Framework (ok for clustering).

The configuration is made through the sessionState section. By adding a custom Session provider, you can store the data in different locations – think for example of a distributed cache.

   1: <sessionState customProvider=”MyProvider>
   2:   <providers>
   3:     <add name=”MyProvidertype=”MyClass, MyAssembly/>
   4:   </providers>
   5: </sessionState>

Resource

A not so known provider, allows you to change the origin of localized resource elements. By default, these come from RESX files and are used whenever you use the Resources expression builder or the GetGlobalResourceObject and GetLocalResourceObject methods, but if you implement a custom provider, you can have these elements come from some place else, such as a database. The base class is ResourceProviderFactory and there’s only one internal implementation which uses these RESX files. Configuration is through the globalization section.

   1: <globalization resourceProviderFactoryType="MyClass, MyAssembly" />

Health Monitoring

Health Monitoring is also probably not so well known, and actually not a good name for it. First, in order to understand what it does, you have to know that ASP.NET fires “events” at specific times and when specific things happen, such as when logging in, an exception is raised. These are not user interface events and you can create your own and fire them, nothing will happen, but the Health Monitoring provider will detect it. You can configure it to do things when certain conditions are met, such as a number of events being fired in a certain amount of time. You define these rules and route them to a specific provider, which must inherit from WebEventProvider. Out of the box implementations include sending mails, logging to a SQL Server database, writing to the Windows Event Log, Windows Management Instrumentation, the IIS 7 Trace infrastructure or the debugger Trace. Its configuration is achieved by the healthMonitoring section and a reason for implementing a custom provider would be, for example, locking down a web application in the event of a significant number of failed login attempts occurring in a small period of time.

   1: <healthMonitoring>
   2:   <providers>
   3:     <add name="MyProvider" type="MyClass, MyAssembly"/>
   4:   </providers>
   5: </healthMonitoring>

Sitemap

The Sitemap provider allows defining the site’s navigation structure and associated required permissions for each node, in a tree-like fashion. Usually this is statically defined, and the included provider allows it, by supplying this structure in a Web.sitemap XML file. The base class is SiteMapProvider and you can extend it in order to supply you own source for the site’s structure, which may even be dynamic. Its configuration must be done through the siteMap section.

   1: <siteMap defaultProvider="MyProvider">
   2:   <providers><add name="MyProvider" type="MyClass, MyAssembly" />
   3:   </providers>
   4: </siteMap>

Web Part Personalization

Web Parts are better known by SharePoint users, but since ASP.NET 2.0 they are included in the core Framework. Web Parts are server-side controls that offer certain possibilities of configuration by clients visiting the page where they are located. The infrastructure handles this configuration per user or globally for all users and this provider is responsible for just that. The base class is PersonalizationProvider and the only included implementation stores settings on SQL Server. Add new providers through the personalization section.

   1: <webParts>
   2:   <personalization defaultProvider="MyProvider">
   3:     <providers>
   4:       <add name="MyProvider" type="MyClass, MyAssembly"/>
   5:     </providers>
   6:   </personalization>
   7: </webParts>

Build

The Build provider is responsible for compiling whatever files are present on your web folder. There’s a base class, BuildProvider, and, as can be expected, internal implementations for building pages (ASPX), master pages (Master), user web controls (ASCX), handlers (ASHX), themes (Skin), XML Schemas (XSD), web services (ASMX, SVC), resources (RESX), browser capabilities files (Browser) and so on. You would write a build provider if you wanted to generate code from any kind of non-code file so that you have strong typing at development time. Configuration goes on the buildProviders section and it is per extension.

   1: <buildProviders>
   2:   <add extension=".ext" type="MyClass, MyAssembly/>
   3: </buildProviders>

New in ASP.NET 4

Not exactly new since they exist since 2010, but in ASP.NET terms, still new.

Output Cache

The Output Cache for ASPX pages and ASCX user controls is now extensible, through the Output Cache provider, which means you can implement a custom mechanism for storing and retrieving cached data, for example, in a distributed fashion. The base class is OutputCacheProvider and the only implementation is private. Configuration goes on the outputCache section and on each page and web user control you can choose the provider you want to use.

   1: <caching>
   2:   <outputCache defaultProvider="MyProvider">
   3:     <providers>
   4:       <add name="MyProvider" type="MyClass, MyAssembly"/>
   5:     </providers>
   6:   </outputCache>
   7: </caching>

Request Validation

A big change introduced in ASP.NET 4 (and refined in 4.5, by the way) is the introduction of extensible request validation, by means of a Request Validation provider. This means we are not limited to either enabling or disabling event validation for all pages or for a specific page, but we now have fine control over each of the elements of the request, including cookies, headers, query string and form values. The base provider class is RequestValidator and the configuration goes on the httpRuntime section.

   1: <httpRuntime requestValidationType="MyClass, MyAssembly" />

Browser Capabilities

The Browser Capabilities provider is new in ASP.NET 4, although the concept exists from ASP.NET 2. The idea is to map a browser brand and version to its supported capabilities, such as JavaScript version, Flash support, ActiveX support, and so on. Previously, this was all hardcoded in .Browser files located in %WINDIR%\Microsoft.NET\Framework(64)\vXXXXX\Config\Browsers, but now you can have a class inherit from HttpCapabilitiesProvider and implement your own mechanism. Register in on the browserCaps section.

   1: <browserCaps provider="MyClass, MyAssembly" />

Encoder

The Encoder provider is responsible for encoding every string that is sent to the browser on a page or header. This includes for example converting special characters for their standard codes and is implemented by the base class HttpEncoder. Another implementation takes care of Anti Cross Site Scripting (XSS) attacks. Build your own by inheriting from one of these classes if you want to add some additional processing to these strings. The configuration will go on the httpRuntime section.

   1: <httpRuntime encoderType="MyClass, MyAssembly" />

Conclusion

That’s about it for ASP.NET providers. It was by no means a thorough description, but I hope I managed to raise your interest on this subject. There are lots of pointers on the Internet, so I only included direct references to the Framework classes and configuration sections.

Stay tuned for more extensibility!

NHibernate Pitfalls: QueryOver and Deep Expressions

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

When using the QueryOver API, unlike LINQ, when applying restrictions, you only have access to direct properties of the target entity type. If you need to access deeper nested properties – those from associated entities – you have to explicitly join. This does not apply to the property representing the foreign key, however. Let’s see an example:

   1: //this will not work
   2: session.QueryOver<Order>().Where(x => x.Customer.Name == "Some Name").List();
   3:  
   4: //this will work
   5: session.QueryOver<Order>().JoinQueryOver(x => x.Customer).Where(x => x.Name == "Some Name").List();
   6:  
   7: //this will also work because Id is the foreign key
   8: session.QueryOver<Order>().Where(x => x.Customer.Id == CustomerId).List();

In general, the QueryOver API is more complex to use than the LINQ one, the advantage is that it allows better composition of dynamic queries.

What Makes SharePoint SharePoint

Introduction

SharePoint is ASP.NET, it is well known. Yet, sometimes, it may be difficult to understand why/how some features work, because we don’t usually see them in regular ASP.NET development. However, all of them are build upon standard ASP.NET/IIS functionality, which you can easily duplicate on non-SharePoint environments. Here are some clues.

Pages That Do Not Exist On The Filesystem

Most of your SharePoint content does not exist in the filesystem (the “14 hive”), but instead is stored in a content database. How come, then, are we able to access them through a standard URL? In order to achieve this, SharePoint uses a Virtual Path Provider. This is an interesting and mostly underused mechanism that exists since ASP.NET 2.0, which allows obtaining a file stream dynamically. Typical examples are loading pages from a database or from a compressed file. The provider SharePoint uses is called Microsoft.SharePoint.ApplicationRuntime.SPVirtualPathProvider and it is set by the Microsoft.SharePoint.ApplicationRuntime.SPRequestModule module, which, in turn, is set on the Web.config file.

Common Files On All Sites

All SharePoint sites feature the _layouts, wpresources folders and its pages and web services, however, these do not physically exist for every site, but only on the 14 hive. There’s a call to TransferRequest inside the Microsoft.SharePoint.ApplicationRuntime.SPRequestModule module which internally redirects to the proper location while preserving the browser URL whenever these paths are being accessed.

Event Handlers, Code Blocks On Markup Are Disabled

As you may know, event handler declarations such as OnClick=”…” on markup files (ASPX, ASCX, Master) are prohibited if these files are not located on the 14 hive. Also, the CompilationMode and AutoEventWireup attributes are also not allowed, as are code blocks (<% … %> and <%= … %>). This is caused by applying a custom page parser filter, Microsoft.SharePoint.ApplicationRuntime.SPPageParserFilter, which is registered on the Web.config file, on the pages section.

The owssvr.dll Module

The SharePoint Foundation RPC Protocol allows some interesting functionality on contents such as lists and document libraries, on any site. It is invoked by sending requests to an URL with the format http://[site_name]/_vti_bin/owssvr.dll?Cmd=Method_name[&Parameter1=Value1&Parameter2=Value2...]. This is a native ISAPI global module (meaning, written in C/C++ and leveraging the Win32 API plus the Internet Server API) called SharePoint14Module which is registered on the %WINDIR%\System32\inetsrv\config\applicationHost.config file.

Conclusion

This was just a basic description of some of the features that are less known. As always, your feedback and questions/corrections are greatly appreciated!

Restricting Access to Properties in NHibernate

Update: unlike what I always thought, "protected internal" means "protected" OR "internal", so this technique is really not that necessary. Thanks to all the commenters who brought that to my attention!

One common requirement is that internal properties of a class can be accessed from other classes on the same assembly. Using NHibernate, you generally cannot use private or internal properties, unless you don’t need to use lazy loading. That is because the NHibernate proxy generator creates dynamically a class for each of your lazy entities, and it does this by subclassing them. The generated classes exist in another assembly, and private and internal properties cannot be accessed from outside the class/assembly on which they are declared.

One solution for this problem is to use internal interfaces for exposing these properties to the same assembly. Consider this example:

   1: public class MyEntity
   2: {
   3:     public virtual Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         protected set;
   7:     }
   8: }

As you can see, the SensitiveProperty can be publicly read but can only be changed from inside the MyEntity class or one inherited from it.

Let’s introduce an internal interface:

   1: interface ISecureModifiable
   2: {
   3:     Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         set;
   7:     }
   8: }

We need to refactor MyEntity so as to realize this interface:

   1: public class MyEntity
   2: {
   3:     public virtual Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         protected set;
   7:     }
   8:  
   9:     Int32 ISecureModifiable.SensitiveProperty
  10:     {
  11:         get
  12:         {
  13:             return(this.SensitiveProperty);
  14:         }
  15:         set
  16:         {
  17:             this.SensitiveProperty = value;
  18:         }
  19:     }
  20: }

Now, all classes in the same assembly as MyEntity and ISecureModifiable can access the SensitiveProperty property, but no other class can – excluding reflection, of course:

   1: MyEntity e = ...;
   2: ISecureModifiable s = e as ISecureModifiable;
   3: s.SensitiveProperty = 100;

Because the interface ISecureModifiable is internal to the assembly on which it is declared, it won’t even be visible from the outside.

NHibernate Pitfalls: Inheritance and Proxies

This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

If you use inheritance and lazy loading, you may end up with the following situation:

  • You want to access a lazy loaded property of a base class type, of which you don’t know the exact type;
  • You want to do different operations depending on the actual type.

That is usually expressed by this mapping:

   1: public class MyEntity
   2: {
   3:     public virtual SomeBaseClass SomeProperty
   4:     {
   5:         get;
   6:         set;
   7:     }
   8: }
   9:  
  10: public abstract SomeBaseClass
  11: {
  12: }
  13:  
  14: public class SomeConcreteClass : SomeBaseClass
  15: {
  16: }
  17:  
  18: public class AnotherConcreteClass : SomeBaseClass
  19: {
  20: }

And by this code:

The problem is, SomeProperty may not be neither a SomeConcreteClass nor a AnotherConcreteClass. That is because NHibernate creates a proxy for SomeBaseClass
   1: MyEntity e = ...;
   2:  
   3: if (e.SomeProperty is SomeConcreteClass)
   4: {
   5: }
   6: else if (e.SomeProperty is AnotherConcreteClass)
   7: {
   8: }
(read, a derived class), which, because .NET does not support multiple inheritance, cannot also inherit from SomeConcreteClass or AnotherConcreteClass. This property is only loaded upon first access, so, until then, NHibernate has no idea of which class to instantiate, so it will instead create this proxy.

The solution is to use the no-proxy option on the mapping:

   1: mapper.Class<MyEntity>(c =>
   2: {
   3:     c.ManyToOne(x => x.SomeProperty, x =>
   4:     {
   5:         x.Lazy(LazyRelation.NoProxy);
   6:     });
   7: }

This way, NHibernate delays loading of the property, as before, but, instead of returning a proxy to the base class, it will instead return one for the concrete class.

You can find more information on this post by Ayende: http://ayende.com/blog/4378/nhibernate-new-feature-no-proxy-associations.

More Posts