按代码映射零或一关系

时间:2013-12-03 22:47:42

标签: c# .net nhibernate fluent-nhibernate nhibernate-mapping

我有以下数据库结构,我无法更改

CREATE TABLE Users (
    ID INT NOT NULL IDENTITY(1,1),
    PRIMARY KEY(ID)
)

CREATE TABLE UserAvatars (
    UserID INT NOT NULL,
    Width INT NOT NULL,
    Height INT NOT NULL,

    PRIMARY KEY(UserID),
    FOREIGN KEY(UserID) REFERENCES Users(ID),
)

基本上,用户可以拥有零或一个头像(我删除了列以简化示例)。

class User
{
    public int ID { get; protected set; }

    public UserAvatar Avatar { get; set; }
}

class UserAvatar
{
    public User User { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

我使用以下映射:

class UserMapping : ClassMapping<User>
{
    public UserMapping() 
    {
        Id(x => x.ID, m => {
            m.Generator(Generators.Identity);
        });

        OneToOne(x => x.Avatar);
    }
}

class UserAvatarMapping : ClassMapping<UserAvatar>
{
    public UserAvatar() 
    {
        Id(x => x.User, m =>
        {
            m.Generator(Generators.Foreign<User>(u => u.ID));
        });

        Property(x => x.Width);
        Property(x => x.Height);
    }
}

然而,在尝试运行我的应用时,我得到NHibernate.MappingException

  

NHibernate.MappingException:无法编译映射文档:   mapping_by_code ----&GT; NHibernate.MappingException:无法确定   输入:MyApp.Models.UserAvatar,MyApp,用于列:   NHibernate.Mapping.Column(用户)

我无法理解这个神秘的错误。

如何完成User可能有零个或一个头像的映射?

2 个答案:

答案 0 :(得分:2)

ID几乎对于NHibernate(ORM)映射的每个实体都很重要。所以,我们应该扩展Avatar类:

class UserAvatar
{
    // every(stuff) should have its ID
    public int ID { get; protected set; } 
    public User User { get; set; }
    ...

ID值将通过一对一的关系进行管理。所以,现在让我们调整映射。

public UserAvatar() 
{
    Id(x => x.ID);

    HasOne(x => x.User)
      .Constrained()
      .ForeignKey();
    ...

public UserMapping() 
{
    Id(x => x.ID);
    HasOne(s => s.Avatar).Cascade.All();

相关且非常有趣的阅读:

答案 1 :(得分:2)

根据RadimKöhler的指导,解决问题的最终类/映射:

class User
{
    public int ID { get; protected set; }
    public UserAvatar Avatar { get; set; }
}

class UserAvatar
{
    public int UserID { get; protected set; }
    public User User { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

使用以下映射:

class UserMapping : ClassMapping<User>
{
    public UserMapping() 
    {
        Id(x => x.ID, m => {
            m.Generator(Generators.Identity);
        });

        OneToOne(x => x.Avatar, m =>
        {
            m.Cascade(Cascade.All);
            m.Constrained(false);
        });         
    }
}

class UserAvatarMapping : ClassMapping<UserAvatar>
{
    public UserAvatar() 
    {
        Id(x => x.UserID, m =>
        {
            m.Generator(Generators.Foreign<UserAvatar>(u => u.User));
        });

        OneToOne(x => x.User, m =>
        {
            m.Constrained(true);
        });         

        Property(x => x.Width);
        Property(x => x.Height);
    }
}