Fluent NHibernate Wiki
Im>JamesGregory
No edit summary
Im>JamesGregory
No edit summary
Line 410: Line 410:
 
This scenario is where you may have a base class in your domain that you use to simplify your entities, you've moved common properties into it so you don't have to recreate them on every entity; typically this would be the Id and perhaps some audit information. So lets start with a model that has a base class we'd like to ignore.
 
This scenario is where you may have a base class in your domain that you use to simplify your entities, you've moved common properties into it so you don't have to recreate them on every entity; typically this would be the Id and perhaps some audit information. So lets start with a model that has a base class we'd like to ignore.
   
  +
<source lang="csharp">
<pre name="code" class="c-sharp">
 
 
namespace Entities
 
namespace Entities
 
{
 
{
Line 428: Line 428:
 
public virtual string Species { get; set; }
 
public virtual string Species { get; set; }
 
}
 
}
  +
}
}</pre>
 
  +
</source>
   
Relatively simple model here, we've got an `Entity` base class that defines the `Id`, then the `Person` and `Animal` entities. We have no desire to have `Entity` mapped by NHibernate, so we need a way to tell the auto mapper to ignore it.
+
Relatively simple model here, we've got an Entity base class that defines the Id, then the Person and Animal entities. We have no desire to have Entity mapped by NHibernate, so we need a way to tell the auto mapper to ignore it.
   
 
For those individuals from traditional XML mapping land, this is what we're going to be recreating:
 
For those individuals from traditional XML mapping land, this is what we're going to be recreating:
   
  +
<source lang="csharp">
<pre name="code" class="xml">
 
&lt;class name="Person"&gt;
+
<class name="Person">
&lt;id name="Id" type="Int32"&gt;
+
<id name="Id">
&lt;generator class="identity" /&gt;
+
<generator class="identity" />
&lt;/id&gt;
+
</id>
 
 
&lt;property name="FirstName" /&gt;
+
<property name="FirstName" />
&lt;property name="LastName" /&gt;
+
<property name="LastName" />
&lt;/class&gt;
+
</class>
 
 
&lt;class name="Animal"&gt;
+
<class name="Animal">
&lt;id name="Id" type="Int32"&gt;
+
<id name="Id">
&lt;generator class="identity" /&gt;
+
<generator class="identity" />
&lt;/id&gt;
+
</id>
   
&lt;property name="Species" /&gt;
+
<property name="Species" />
&lt;/class&gt;</pre>
+
</class>
  +
</source>
   
  +
We'll start with this automapping setup:
We need to initialise the NHibernate configuration, and supply it with any auto mappings we're going to create. To do that we'll combine the [auto mapper](AutoMapping) with our FluentConfiguration.
 
   
  +
<source lang="csharp">
<pre name="code" class="c-sharp">
 
  +
AutoMap.AssemblyOf<Entity>
Fluently.Configure()
 
 
.Where(t => t.Namespace == "Entities");
.Database(SQLiteConfiguration.Standard.InMemory)
 
  +
</source>
.Mappings(m =&gt;
 
m.AutoMappings.Add(
 
AutoPersistenceModel
 
.MapEntitiesFromAssemblyOf&lt;Entity&gt;()
 
.Where(t => t.Namespace == "Entities")
 
))
 
.BuildSessionFactory();</pre>
 
   
 
If we were to run this now, we wouldn't get the mapping we desire. Fluent NHibernate would see Entity as an actual entity and map it with Animal and Person as subclasses; this is not what we desire, so we need to modify our auto mapping configuration to reflect that.
The key part is inside the `AutoMappings.Add` call, which is where we're telling the automapper to map anything in the `Entities` namespace from the assembly that contains our `Entity` base-class.
 
   
 
After <code>AutoMap.AssemblyOf<Entity>()</code> we need to alter the conventions that the auto mapper is using so it can identify our base-class.
If we were to run this now, we wouldn't get the mapping we desire. Fluent NHibernate would see `Entity` as an actual entity and map it with `Animal` and `Person` as subclasses; this is not what we desire, so we need to modify our auto mapping configuration to reflect that.
 
   
  +
<source lang="csharp">
After `MapEntitiesFromAssemblyOf<Entity>()` we need to alter the conventions that the auto mapper is using so it can identify our base-class.
 
  +
AutoMap.AssemblyOf<Entity>()
  +
.Setup(s =>
 
{
 
s.IsBaseType =
 
type =&gt; type == typeof(Entity);
 
})
 
.Where(t => t.Namespace == "Entities");
  +
</source>
   
 
We've added the <code>Setup</code> call in which we replace the <code>IsBaseType</code> setting with our own. This property is used to identify whether a type is simply a base-type for abstraction purposes, or a legitimate storage requirement. In our case we've set it to return `true` if the type is an `Entity`.
<pre name="code" class="c-sharp">
 
Fluently.Configure()
 
.Database(SQLiteConfiguration.Standard.InMemory)
 
.Mappings(m =&gt;
 
m.AutoMappings.Add(
 
AutoPersistenceModel
 
.MapEntitiesFromAssemblyOf&lt;Entity&gt;()
 
.WithSetup(s =&gt;
 
{
 
s.IsBaseType =
 
type =&gt; type == typeof(Entity);
 
})
 
.Where(t => t.Namespace == "Entities")
 
))
 
.BuildSessionFactory();</pre>
 
   
 
With this change, we now get our desired mapping. Entity is ignored as far is Fluent NHibernate is concerned, and all the properties (Id in our case) are treated as if they were on the specific subclasses.
We've added the `WithSetup` call in which we replace the `IsBaseType` convention with our own. This convention is used to identify whether a type is simply a base-type for abstraction purposes, or a legitimate storage requirement. In our case we've set it to return `true` if the type is an `Entity`.
 
 
With this change, we now get our desired mapping. `Entity` is ignored as far is Fluent NHibernate is concerned, and all the properties (`Id` in our case) are treated as if they were on the specific subclasses.
 
   
 
=== Base-type as an inheritance strategy ===
 
=== Base-type as an inheritance strategy ===
   
  +
If you want to have your base-class included in NHibernate, then just don't include the IsBaseType setup we did above! Easy.
What we're going to do is create a simple model that we'll map as a [table-per-subclass][2] inheritance strategy, which is the equivalent of the NHibernate `joined-subclass` mapping.
 
   
  +
=== Configuring the subclassing strategy ===
<pre name="code" class="c-sharp">
 
namespace Entities
 
{
 
public class Person
 
{
 
public virtual int Id { get; set; }
 
public virtual string FirstName { get; set; }
 
public virtual string LastName { get; set; }
 
}
 
   
  +
Fluent NHibernate defaults to using table-per-subclass strategy for automapping inheritance hierarchies. If this is not what you want, then you can configure it using the <code>SubclassStrategy</code> configuration option.
public class Employee : Person
 
{
 
public virtual DateTime StartDate { get; set; }
 
}
 
   
  +
If you just want every hierarchy to be mapped using the same strategy, then you'd use <code>SubclassStrategy</code> like so:
public class Guest : Person
 
  +
  +
<source lang="csharp">
  +
AutoMap.AssemblyOf<Entity>()
  +
.Setup(s =>
 
{
 
{
  +
s.SubclassStrategy = t => SubclassStrategy.Subclass;
public virtual int GuestPassId { get; set; }
 
}
+
});
}</pre>
+
</source>
   
  +
However, if you wanted to customise it on a per-class basis, you'd set it up like so:
Relatively simple model here, we've got an `Person` class that defines the `Id` and name properties, then the `Employee` and `Guest` subclass entities.
 
   
  +
<source lang="csharp">
The XML equivalent is as follows:
 
  +
AutoMap.AssemblyOf<Entity>()
 
  +
.Setup(s =>
<pre name="code" class="xml">
 
 
{
&lt;class name="Person"&gt;
 
  +
s.SubclassStrategy = t => t == typeof(ClassOne) || typeof(ClassTwo);
&lt;id name="Id" type="Int32"&gt;
 
 
});
&lt;generator class="identity" /&gt;
 
  +
</source>
&lt;/id&gt;
 
 
&lt;property name="FirstName" /&gt;
 
&lt;property name="LastName" /&gt;
 
 
&lt;joined-subclass name="Employee"&gt;
 
&lt;key column="PersonId" /&gt;
 
&lt;property name="StartDate" /&gt;
 
&lt;/joined-subclass&gt;
 
 
&lt;joined-subclass name="Guest"&gt;
 
&lt;key column="PersonId" /&gt;
 
&lt;property name="GuestPassId" /&gt;
 
&lt;/joined-subclass&gt;
 
&lt;/class&gt;</pre>
 
 
Again we configure NHibernate using the FluentConfiguration:
 
 
<pre name="code" class="c-sharp">
 
Fluently.Configure()
 
.Database(SQLiteConfiguration.Standard.InMemory)
 
.Mappings(m =&gt;
 
m.AutoMappings.Add(
 
AutoPersistenceModel
 
.MapEntitiesFromAssemblyOf&lt;Entity&gt;()
 
.Where(t => t.Namespace == "Entities")
 
))
 
.BuildSessionFactory();</pre>
 
 
This is the same configuration that I used in the first example, except that if you recall the reason we had to change the last example was because it was mapping it as a joined-subclass - that's right, we don't need to do anything now! Our mapping is complete, Fluent NHibernate automatically assumes that any inherited classes (that haven't had their base-type excluded by the `IsBaseType` convention) should be mapped as joined-subclasses.
 
   
 
=== Subclassing FAQs ===
 
=== Subclassing FAQs ===

Revision as of 17:15, 15 August 2009

Fluent NHibernate has a concept called Auto Mapping, which is a mechanism for automatically mapping all your entities based on a set of conventions.

Auto mapping utilises the principal of convention over configuration. Using this principal, the auto mapper inspects your entities and makes assumptions of what particular properties should be. Perhaps you have a property with the name of Id and type of int, the auto mapping will decide that this is an auto-incrementing primary key.

By using the auto mappings, you can map your entire domain with very little code, and certainly no XML. There are still scenarios where it may not be suitable to use the auto mapping, at which point it would be more appropriate to use the ClassMap based fluent mappings; however, for most greenfield applications (and quite a few brownfield ones too) auto mapping will be more than capable.

Getting started

Lets go through how to map a simple domain using the Fluent NHibernate AutoMapper.

Given the following clichéd store domain:

public class Product
{
  public virtual int Id { get; private set; }
  public virtual string Name { get; set; }
  public virtual decimal Price { get; set; }
}

public class Shelf
{
  public virtual int Id { get; private set; }
  public virtual IList<Product> Products { get; private set; }
  
  public Shelf()
  {
    Products = new List<Product>();
  }
}

We've got a product, with an auto-incrementing primary key called Id, and Name and Price properties. The store has some shelves it fills with products, so there's a Shelf entity, which has an Id, and a list of the Product's on it; the Product collection is a one-to-many or HasMany relationship to the Product.

I'm going to make the assumption here that you have an existing NHibernate infrastructure, if you don't then it's best you consult a general NHibernate walkthrough before continuing.

We're going to be using the AutoMap class to do our mapping, which you can use in combination with the fluent configuration API. To begin with we should take a look at the static AutoMap.AssemblyOf<T> method; this method takes a generic type parameter from which we determine which assembly to look in for mappable entities.

AutoMap.AssemblyOf<Product>();

That's it, you've mapped your domain. There are a few customisations you'll want to make before putting this into production though.

Lets go through what's actually happening here. The AutoMap.AssemblyOf<Product> call creates an instance of an AutoPersistenceModel that's tied to the assembly that Product is declared. No mappings are actually generated until we push them into NHibernate, this gives us opportunity to customise them before-hand, which we'll go into later.

We're going to utilise the fluent configuration API to create our SessionFactory.

var sessionFactory = Fluently.Configure()
  .Database(/* database config */)
  .Mappings(m =>
    m.AutoMappings
      .Add(AutoMap.AssemblyOf<Product>()))
  .BuildSessionFactory();

You can see that our AutoMap is sat in the middle of the configuration, inside the Mappings call; this is our way of telling Fluent NHibernate that we're using the auto mapper; there's nothing stopping you from passing in an instance of AutoPersistenceModel that you've configured elsewhere, we're just doing it in-line for brevity.

We're now capable of getting NHibernate to accept our auto mapped entities, there's just one more thing we need to deal with. The auto mapper doesn't know which classes are your entities, and which ones are everything else. The setup we're using above simply maps every class in your assembly as an entity, which isn't going to be very useful; so I'll introduce another method: Where(Func<Type, bool>).

The Where method takes a delegate which is used to limit types based on your own criteria. The most common usage is based on the namespace, but you could also look at the type name, or anything else exposed on the Type instance.

var autoMappings = AutoMap.AssemblyOf<Product>()
  .Where(t => t.Namespace == "Storefront.Entities");

Bringing all that together leaves us with this NHibernate setup:

var sessionFactory = Fluently.Configure()
  .Database(/* database config */)
  .Mappings(m =>
    m.AutoMappings.Add(
      AutoMap.AssemblyOf<Product>()
        .Where(t => t.Namespace == "Storefront.Entities")))
  .BuildSessionFactory();

Or if you prefer it separate:

var model = AutoMap.AssemblyOf<Product>()
  .Where(t => t.Namespace == "Storefront.Entities");

var sessionFactory = Fluently.Configure()
  .Database(/* database config */)
  .Mappings(m => m.AutoMappings.Add(model))
  .BuildSessionFactory();

That's all that you should need. It's all a lot easier than writing out mappings, isn't it?

Components

Sometimes you need components in your domain model, here's how to map them automatically.

Lets imagine this database structure:

table Person (
  Id int primary key,
  Name varchar(200),
  AddressNumber int,
  AddressStreet varchar(100),
  AddressPostCode varchar(8)
)

We want to map that to the following model:

public class Person
{
  public virtual int Id { get; private set; }
  public virtual string Name { get; set; }
  public virtual Address Address { get; set; }
}

public class Address
{
  public int Number { get; set; }
  public string Street { get; set; }
  public string PostCode { get; set; }
}

With this design Address is actually a component, which isn't a full entity, more of a way of providing a clean model to a normalised database structure. Lets start with what we left off with:

AutoMap.AssemblyOf<Person>()
  .Where(type => type.Namespace.EndsWith("Domain");

We've now got the auto mappings integrated with NHibernate, so we need to instruct the auto mapper how to identify components; after the Where call, we can add a call to WithSetup to help the auto mapper identify our components.

.Setup(s =>
{
  s.IsComponentType =
    type => type == typeof(Address);
})

The IsComponentType property we just set is what Fluent NHibernate uses to determine whether a type is one that will be mapped as a component.

It's fairly common that you'll have more than one convention type, you'll need to chain together ORs in your IsComponentType lambda, or check on something more generic like the namespace.

The Address should now be automatically mapped as a component; the auto mapper will pick up the three properties and map them as properties on the component.

If you need to customise the column naming of your component's properties you can set the GetComponentColumnPrefix property:

.Setup(s =>
{
  s.IsComponentType =
    type => type == typeof(Address);
  s.GetComponentColumnPrefix =
    type => type.Name + "_";
})

The convention now specifies that columns should be named TypeName_PropertyName, so Address.Street is now mapped to Address_Street.

Conventions

The mappings produced by Fluent NHibernate are based on a pre-defined set of assumptions about your domain, this allows us to greatly reduce the amount of code you're required to write; sometimes however, the conventions we supply are not to your liking, perhaps you're a control-freak and want to have full say over your design, or more likely you're working against an existing database that has it's own set of standards.

You'd still like to use the auto mapper, but can't because it maps your entities all wrong. Luckily for you we've thought about that, the auto mapper can utilise the conventions just like fluent mappings.

Using the following entities:

public class Product  
{  
  public int Id { get; private set; }  
  public virtual string Name { get; set; }  
  public virtual decimal Price { get; set; }  
}  

public class Shelf  
{  
  public virtual int Id { get; private set; }  
  public virtual IList<Product> Products { get; private set; }  
  
  public Shelf()
  {
    Products = new List<Product>();
  }
}

The standard conventions, it'd map to a database schema like this:

table Product (
  Id int identity primary key,
  Name varchar(100),
  Price decimal,
  Shelf_id int foreign key
)

table Shelf (
  Id int identity primary key
)

Nothing too complicated there, but that might not be the schema you expect. Lets pretend (or not!) that you name the primary key after the table it's in, so our Product identity should be called ProductId; also, you like your foreign key's to be explicitly named _FK, and your strings are always a bit longer than 100.

Remember this fellow?

AutoMap.AssemblyOf<Product>()  
  .Where(t => t.Namespace == "Storefront.Entities");

Lets update it to include some convention overrides. We'll start with the Id name. The conventions we're about to implement are better explained in the conventions page.

AutoMap.AssemblyOf<Product>()
  .Where(t => t.Namespace == "Storefront.Entities")
  .Conventions.Add<PrimaryKeyConvention>();

We've added a convention to the convention discovery mechanism, now let's implement it.

public class PrimaryKeyConvention
  : IIdConvention
{
  public void Apply(IIdentityInstance instance)
  {
    instance.Column(instance.EntityType.Name + "Id");
  }
}

Our PrimaryKeyConvention gets applied to all Ids and sets their column name based on the entity that contains the Id property. Our primary key's will now be generated as TypeNameId; which means our schema now looks like this:

table Product (
  ProductId int identity primary key,
  Name varchar(100),
  Price decimal,
  Shelf_id int foreign key
)

table Shelf (
  ShelfId int identity primary key
)

As you can see, our primary key's now have our desired naming convention. Lets do the other two together, as they're so simple; we'll override the foreign-key naming, and change the default length for strings.

.Conventions.Setup(c =>
{
  c.Add<PrimaryKeyConvention>();
  c.Add<CustomForeignKeyConvention>();
  c.Add<DefaultStringLengthConvention>();
});

public class CustomForeignKeyConvention
  : ForeignKeyConvention
{
  protected override string GetKeyName(PropertyInfo property, Type type)
  {
    if (property == null)
      return type.Name + "_FK";
 
    return property.Name + "_FK";
  }
}

public class DefaultStringLengthConvention
  : IPropertyConvention
{
  public void Apply(IPropertyInstance instance)
  {
    instance.Length(250);
  }
}

That's all there is to it, when combined with the other conventions you can customise the mappings quite heavily while only adding a few lines to your auto mapping.

This is our final schema:

table Product (
  ProductId int identity primary key,
  Name varchar(250),
  Price decimal,
  Shelf_FK int foreign key
)

table Shelf (
  ShelfId int identity primary key
)

Altering entities

Sometimes it's necessary to make slight changes to a specific entity, without wishing to affect anything else; you can do that with the with ForTypesThatDeriveFrom<T> method.

.ForTypesThatDeriveFrom<Shelf>(map =>
{
  map.HasMany(x => x.Products)
    .Cascade.All();
});

The ForTypesThatDeriveFrom method takes a generic parameter that's the entity you want to customise. The parameter is an expression that allows you to alter the underlying mapping that is generated by the auto mapper. You can do just about anything in this call that you can do in the fluent mappings.

In the example above we're setting Cascade.All on the HasMany of Products for the entity Shelf.

You can do this for as many types as you need in your domain; however, baring in mind readability, it may sometimes be more appropriate to use an override or map entities explicitly using the fluent mappings if you find yourself overriding a lot of conventions.

Overrides

Using too many calls to ForTypesThatDeriveFrom can quickly clutter up your auto mapping setup; an alternative is to use an IAutoMappingOverride<T>, which is an interface you can implement to override the mappings of a particular auto-mapped class.

public class PersonMappingOverride
  : IAutoMappingOverride<Person>
{
  public void Override(AutoMap<Person> mapping)
  {
  }
}

This example overrides the auto-mapping of a Person entity. Within the Override method you can perform any actions on the mapping that you can in the fluent mappings.

To use overrides, you need to instruct your AutoMap instance to use them. Typically this would be done in the context of a fluent configuration setup, but I'll just illustrate with the AutoMap on it's own.

AutoMap.AssemblyOf<Person>()
  .Where(type => type.Namespace == "Entities")
  .UseOverridesFromAssemblyOf<PersonMappingOverride>();

It's the UserOverridesFromAssemblyOf<T> call that instructs the AutoPersistenceModel to read any overrides that reside the assembly that contains T.

Ignoring properties

When using the auto mapper sometimes you may want to ignore certain properties on your entity. If it's only for one entity, then you can override the entity or specify an alteration each which allow you to call an IgnoreProperty method.

For example:

.ForTypesThatDeriveFrom<Shelf>(map =>  
{  
  map.IgnoreProperty(x => x.YourProperty);
});

If you need to ignore a property regardless of what type it's present on, you can use the ForAllTypes method, which exposes a similar interface.

.ForAllTypes(map =>  
{  
  map.IgnoreProperty("YourProperty");
});

The difference in this case is that because we don't know the entity at the time of writing our ignore call, we have to specify the name with a string; this is not ideal, but there aren't really any alternatives in this situation.

There are a couple of overloads available when using ForAllTypes.

A single property:

.ForAllTypes(map =>  
{  
  map.IgnoreProperty("YourProperty");
});

Multiple properties:

.ForAllTypes(map =>  
{  
  map.IgnoreProperties("YourProperty", "AnotherProperty");
});

Properties by predicate:

.ForAllTypes(map =>  
{  
  map.IgnoreProperties(x => x.Name.Contains("Something"));
});

That last one is powerful. You can do whatever you like in that predicate against the PropertyInfo instance supplied. You could check if the name contains a particular string, like above, or you could check if the property has a particular attribute on.

Inheritance

There are two main things that you'd want to do with inherited classes, either ignore the base class all together, or map them using an inheritance strategy. I'm going to start with the former, then move on to the latter.

Ignoring base-types

This scenario is where you may have a base class in your domain that you use to simplify your entities, you've moved common properties into it so you don't have to recreate them on every entity; typically this would be the Id and perhaps some audit information. So lets start with a model that has a base class we'd like to ignore.

namespace Entities
{
  public abstract class Entity
  {
    public virtual int Id { get; set; }    
  }

  public class Person : Entity
  {
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
  }

  public class Animal : Entity
  {
    public virtual string Species { get; set; }
  }
}

Relatively simple model here, we've got an Entity base class that defines the Id, then the Person and Animal entities. We have no desire to have Entity mapped by NHibernate, so we need a way to tell the auto mapper to ignore it.

For those individuals from traditional XML mapping land, this is what we're going to be recreating:

<class name="Person">
  <id name="Id">
    <generator class="identity" />
  </id>
  
  <property name="FirstName" />
  <property name="LastName" />
</class>
    
<class name="Animal">
  <id name="Id">
    <generator class="identity" />
  </id>

  <property name="Species" />
</class>

We'll start with this automapping setup:

AutoMap.AssemblyOf<Entity>
  .Where(t => t.Namespace == "Entities");

If we were to run this now, we wouldn't get the mapping we desire. Fluent NHibernate would see Entity as an actual entity and map it with Animal and Person as subclasses; this is not what we desire, so we need to modify our auto mapping configuration to reflect that.

After AutoMap.AssemblyOf<Entity>() we need to alter the conventions that the auto mapper is using so it can identify our base-class.

AutoMap.AssemblyOf<Entity>()
  .Setup(s =>
  {
    s.IsBaseType =
      type =&gt; type == typeof(Entity);
  })
  .Where(t => t.Namespace == "Entities");

We've added the Setup call in which we replace the IsBaseType setting with our own. This property is used to identify whether a type is simply a base-type for abstraction purposes, or a legitimate storage requirement. In our case we've set it to return `true` if the type is an `Entity`.

With this change, we now get our desired mapping. Entity is ignored as far is Fluent NHibernate is concerned, and all the properties (Id in our case) are treated as if they were on the specific subclasses.

Base-type as an inheritance strategy

If you want to have your base-class included in NHibernate, then just don't include the IsBaseType setup we did above! Easy.

Configuring the subclassing strategy

Fluent NHibernate defaults to using table-per-subclass strategy for automapping inheritance hierarchies. If this is not what you want, then you can configure it using the SubclassStrategy configuration option.

If you just want every hierarchy to be mapped using the same strategy, then you'd use SubclassStrategy like so:

AutoMap.AssemblyOf<Entity>()
  .Setup(s =>
  {
    s.SubclassStrategy = t => SubclassStrategy.Subclass;
  });

However, if you wanted to customise it on a per-class basis, you'd set it up like so:

AutoMap.AssemblyOf<Entity>()
  .Setup(s =>
  {
    s.SubclassStrategy = t => t == typeof(ClassOne) || typeof(ClassTwo);
  });

Subclassing FAQs

Abstract base-classes

You'll notice that our Entity class is abstract. This is good practice, but for the record, it is not mandatory. If you're experiencing problems, it's unlikely to be this.

In case you're wondering, making the class abstract is like saying "I'll never create an Entity directly, instead I will create derived classes such as Customer and Order (which inherit from Entity)."

Protected setters

Sometimes you only want your class to be able to set it's own properties, not the outside world. For example, the Id and CreatedAt properties might never need to be set anywhere but in the class itself.

public abstract Entity
{
    public virtual int Id {get; protected set;}
    public virtual DateTime CreatedAt { get; protected set;}

    public Entity()
    {
       CreatedAt = DateTime.Now;
    }
}

Be sure to make these setters protected rather than private. Doing this will ensure they are included in the Auto Mappings.