How to map part of aspnet_Users table using Fluent NHibernate
I'm trying to get Fluent NHibernate 1.0 RTM to map a User entity for me so that I have access to UserId and UserName inside my ASP.NET MVC application via NHibernate.
I have:
public class User
{
public virtual Guid UserId { get; protected set; }
public virtual string UserName { get; protected set; }
}
It represents the aspnet_Users table with only the relevant columns to be mapped. This is the only entity that is not being automapped. Here is my mapping:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.UserId);
Map(x => x.UserName);
WithTable("aspnet_Users");
}
}
Everything else is getting automapped with conventions.
Here are my PrimaryKeyConvention and TableNameConvention:
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance开发者_如何学Python instance)
{
instance.Column(instance.Property.ReflectedType.Name + "Id");
instance.UnsavedValue(System.Guid.Empty.ToString());
instance.GeneratedBy.GuidComb();
}
}
public class TableNameConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table(Inflector.Net.Inflector.Pluralize(instance.EntityType.Name));
}
}
The Mapping process fails right after executing the ClassMap code (which comes before all automapping), followed by the TableNameConvention code, followed by the PrimaryKeyConvention code. The failure is in PrimaryKeyConvention because instance.Property is null. I tried to do an if(instance.Property != null) but that terminates the mapping process early with a "the required attribute 'class' is missing" error. I also had an if (instance.EntityType != typeof(User)) in the TableNameConvention, but took out when it was making no difference.
What is going on here? First of all, why is the AutoMapping processes calling the conventions for the ClassMap? Second, why is the PrimaryKenConvention getting passed an instance.Property == null? How can I get this to work so that the mapping process moves on and maps the rest of my entities using AutoMapping + conventions?
Note, I had this all working for months under an earlier version of FNH prior to the refactor for 1.0 RTM.
I've figured out the answer to this.
public UserMap()
{
Id(x => x.UserId);
Map(x => x.UserName);
Table("aspnet_Users");
}
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.Column(instance.EntityType.Name + "Id");
instance.UnsavedValue(System.Guid.Empty.ToString());
instance.GeneratedBy.GuidComb();
}
}
public class TableNameConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table(Inflector.Net.Inflector.Pluralize(instance.EntityType.Name));
}
}
Note that the PrimaryKeyConvention sets the Column name using instance.EntityName rather that instance.Property. The latter was null for the UserMap, so it would crash.
This approach is better than using a conditional statement on (null != instance.Property) and keeping the instance.Property.ReflectedType.Name line, but both work. If you choose to go that route, you have to explicitly set the Column names in the UserMap:
public UserMap()
{
Id(x => x.UserId).Column("UserId")
.GeneratedBy.Assigned();
Map(x => x.UserName).Column("UserName");
Table("aspnet_Users");
}
I don't use the auto-mapping myself, but I think you need to map User by implementing IAutoMappingOverride. Something like:
public class UserMap : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.Id(x => x.UserId);
mapping.Map(x => x.UserName);
mapping.WithTable("aspnet_Users");
}
}
精彩评论