1

我正在尝试让 Fluent NHibernate 1.0 RTM 为我映射一个用户实体,以便我可以通过 NHibernate 访问我的 ASP.NET MVC 应用程序中的 UserId 和 UserName。

我有:

public class User
{
    public virtual Guid UserId { get; protected set; }
    public virtual string UserName { get; protected set; }
}

它表示仅包含要映射的相关列的 aspnet_Users 表。这是唯一没有被自动映射的实体。这是我的映射:

public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(x => x.UserId);
        Map(x => x.UserName);
        WithTable("aspnet_Users");
    }
}

其他一切都在使用约定进行自动映射。

这是我的 PrimaryKeyConvention 和 TableNameConvention:

public class PrimaryKeyConvention : IIdConvention
{
    public void Apply(IIdentityInstance 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));
    }
}

映射过程在执行 ClassMap 代码(在所有自动映射之前)之后立即失败,然后是 TableNameConvention 代码,然后是 PrimaryKeyConvention 代码。失败出现在 PrimaryKeyConvention 中,因为 instance.Property 为空。我试图做一个 if(instance.Property != null) 但这会提前终止映射过程,并出现“缺少所需的属性‘类’”错误。我在 TableNameConvention 中也有一个 if (instance.EntityType != typeof(User)),但是当它没有任何区别时取出。

这里发生了什么?首先,为什么 AutoMapping 进程调用 ClassMap 的约定?其次,为什么 PrimaryKenConvention 会通过 instance.Property == null?我怎样才能让它工作,以便映射过程继续进行并使用 AutoMapping + 约定映射我的其余实体?

请注意,在重构 1.0 RTM 之前,我已经在早期版本的 FNH 下工作了几个月。

4

2 回答 2

1

我已经想出了这个问题的答案。

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));
    }
}

请注意,PrimaryKeyConvention 使用 instance.EntityName 而不是 instance.Property 设置列名称。后者对于 UserMap 是空的,所以它会崩溃。

这种方法比在 (null != instance.Property) 上使用条件语句并保留 instance.Property.ReflectedType.Name 行要好,但两者都有效。如果您选择走那条路线,则必须在 UserMap 中显式设置列名称:

public UserMap()
{
    Id(x => x.UserId).Column("UserId")
                     .GeneratedBy.Assigned();
    Map(x => x.UserName).Column("UserName");
    Table("aspnet_Users");
}
于 2010-01-28T20:25:03.387 回答
0

我自己不使用自动映射,但我认为您需要通过实现IAutoMappingOverride来映射 User 。就像是:

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");
    }
}
于 2010-01-26T19:23:22.943 回答