2013-12-03 2 views
2

У меня есть следующая структура базы данных, которая я не могу изменить:Mapping кодом ноль-Or-One отношения

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 ----> NHibernate.MappingException: не удалось определить тип для: MyApp.Models.UserAvatar, MyApp, для столбцов: NHibernate.Mapping.Column (Пользователь)

Я не могу понять смысл этой загадочной ошибки.

Как выполнить сопоставление, где User может иметь ноль или один аватар?

ответ

2

Идентификатор очень важен для каждого объекта, отображаемого NHibernate (ORM). Итак, мы должны расширить класс Avatar:

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

Значение идентификатора будет определяться взаимно-однозначным отношением. Итак, теперь давайте настроим отображение.

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

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

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

Связанные и очень интересно читать:

+0

Спасибо за это, я постараюсь это завтра, когда я на работу. Есть ли у вас ссылка на сопоставление по коду (не беглое nhibernate)? Не беспокойтесь, если вы этого не сделаете. – Matthew

+0

Да, есть истории, как использовать сопоставление по коду. Один-к-одному здесь: http://notherdev.blogspot.cz/2012/01/mapping-by-code-onetoone.html, * index * из них находится здесь: http://notherdev.blogspot.cz /2012/02/nhibernates-mapping-by-code-summary.html –

+0

Спасибо @Radim, это очень помогло в решении проблемы. Я собираюсь опубликовать свое решение, которое использует сопоставление по коду. – Matthew

2

Забрав из guidence Радим Колера, конечных классов/отображения, решаемой проблемы:

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

Очень интересно;) –

Смежные вопросы