2014-03-17 2 views
0

У меня есть следующие объекты в моем проекте, который я хочу отобразить с помощью NHibernate Атрибуты:NHibernate: карта класса с несколькими полями наследования

public interface IContent 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 

public interface IUser 
{ 
    int Id { get; set; } 
} 

[Class] 
public class Book : IContent 
{ 
    [Id(...), Column(...), Generator(...)] 
    public virtual int Id { get; set; } 

    public virtual string Name { get; set; } 
} 

[Class] 
public class Collection : IContent 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
} 

[Class] 
public class Reader : IUser 
{ 
    [Id(...), Column(...), Generator(...)] 
    public virtual int Id { get; set; } 

    [Property] 
    public virtual string Email { get; set; } 
} 

[Class] 
public class ReaderGroup : IUser 
{ 
    [Id(...), Column(...), Generator(...)] 
    public virtual int Id { get; set; } 

    [ManyToMany(...)] 
    public virtual ISet<Reader> Readers { get; set; } 
} 

А теперь я хочу, чтобы реализовать единый механизм контроля доступа:

public class AccessPermission 
{ 
    [Id(...), Column(...), Generator(...)] 
    public virtual int Id { get; set; } 

    public virtual IContent Object { get; set; } 

    public virtual IUser Subject { get; set; } 
} 

хитрость заключается в том, что есть два поля, которые принимают различные типы значений: Object и Subject. Я ранее использовал атрибуты и Subclass, но тогда было только одно поле с унаследованными типами, а не два или более.

Есть ли разумный способ реализовать такой случай?

+0

Можете ли вы описать, как вы моделируете это в базе данных? Есть несколько способов подойти к этому. –

+0

Это новый проект, поэтому я просто создаю классы и позволяю NHibernate создавать схему для меня. Любой подход на стороне базы данных будет выполняться. – Impworks

ответ

1

NHibernate не очень хорошо играет с интерфейсами, так как он работает, создавая прокси классов, наследуя ваши сущности (следовательно, вы должны определить все свои поля как virtual).

Что бы я сделал, вместо ваших интерфейсов здесь, используйте абстрактные классы, например.

public abstract class User 
{ 
    public virtual int Id { get; protected set; } 
    public virtual IEnumerable<AccessPermission> AccessPermissions { get; protected set; } 
} 

Затем (используя Fluent NHibernate)

public class UserMap : ClassMap<User> 
{ 
    public UserMap() 
    { 
     this.Id(x => x.Id); 
     this.HasMany(x => x.AccessPermissions); 
     this.DiscriminateSubClassesOnColumn("Type"); 
    } 
} 

и для подклассов:

public class ReaderMap : SubClassMap<Reader> 
{ 
    public ReaderMap() 
    { 
     this.DiscriminatorValue("Reader"); 
     this.Map(x => x.Email); 
    } 
} 

для AccessPermission:

public class AccessPermissionMap : ClassMap<AccessPermission> 
{ 
    public AccessPermissionMap() 
    { 
     this.Id(x => x.Id); 
     this.References(x => x.Object); 
     this.References(x => x.Subject); 
    } 
} 

Тогда NH делает все тяжелая работа для вас и выясните, какой подкласс для создания экземпляра на основе идентификатора FK в вашем AccessPermission

+0

В вашем примере «Пользователь» содержит список объектов «AccessPermission». Это похоже на обращение к мне ответственности. Может ли быть решение, в котором ни один из классов не знает «AccessPermission»? – Impworks

+0

Ну, в первую очередь вы всегда можете установить их защищенными, а не публичными. Я думаю, что это сработает. –

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