Работа с интерфейсами и EF Fluent API - PullRequest
2 голосов
/ 09 ноября 2011

Код

Я покажу вам код, а затем объясню проблему

Интерфейсы

public interface IUser
{
    Guid ID { get; set; }
    string Name { get; set; }
    ICollection<IRole> Roles { get; set; }
}

public interface IRole
{
    Guid ID { get; set; }
    string Name { get; set; }
}

Обратите внимание, что интерфейс IUser определяет коллекциюРоли типа IRole

Реализация

public class Role : IRole
{
    public Guid ID { get; set; }
    public string Name { get; set; }
}

public class User : IUser
{
    public Guid ID { get; set; }
    public string Name { get; set; }
    public ICollection<IRole> Roles { get; set; }
}

EF Fluent API Configuration

public class RoleConfiguration : EntityTypeConfiguration<Role>
{
    public RoleConfiguration()
    {
        HasKey(p => p.ID)
            .Property(p => p.ID);

        Property(p => p.Name)
            .IsRequired()
            .HasMaxLength(70);
    }
}


public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        HasKey(p => p.ID)
            .Property(p => p.ID)
                .IsRequired();

        Property(p => p.Name)
            .HasMaxLength(60)
            .IsRequired();

        HasMany(r => r.Roles).WithMany();
    }
}

Обратите внимание, что конфигурация EntityTypeConfiguration, где T - реализация, ине интерфейс (EF не позволяет поставить интерфейс как T)

Проблема

# 1 Ситуация:

Если выЗапустите приложение, чтобы сгенерировать реляционную модель, возникает следующая ошибка:

The navigation property 'Roles' is not a declared property on type 'User'. Verify that it has not been explicitly excluded from the model and that it is a valid navigation property.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: The navigation property 'Roles' is not a declared property on type 'User'. Verify that it has not been explicitly excluded from the model and that it is a valid navigation property.

Source Error: 


Line 58:         public IQueryable<Project> GetAll(int pageIndex, int pageSize, params Expression<Func<Project, object>>[] includeProperties)
Line 59:         {
Line 60:             return includeProperties.Aggregate<Expression<Func<Project, object>>,
Line 61:                 IQueryable<Project>>(Context.Projects, (current, includeProperty) => current.Include(includeProperty)).OrderBy(p => p.Name).Skip(pageIndex).Take(pageSize);
Line 62:         }

# 2 ситуация:

Если вы закомментируете строку HasMany(r => r.Roles).WithMany(); EFсгенерирует реляционную модель без связи между User и Role (что должно быть много ко многим)

Я считаю, что это потому, что в классе User существует тип коллекции ICollection<IRole> ине добрый ICollection.

Вопрос

Вопрос в том,Как решить эту проблему?Как отобразить коллекцию public ICollection<IRole> Roles { get; set; } с помощью Fluent API EF

Ответы [ 2 ]

3 голосов
/ 13 ноября 2011

CodeFirst не поддерживает сопоставление интерфейсов.Вам нужно будет изменить его, чтобы он ссылался на конкретный класс Role.

0 голосов
/ 27 марта 2013

Вот как я бы реализовал ваши интерфейсы, чтобы обойти проблему, описанную Бетти.

public class Role : IRole
{
    public Guid ID { get; set; }
    public string Name { get; set; }
}

public class User : IUser
{
    public Guid ID { get; set; }
    public string Name { get; set; }

    // Explicit implementation of the IUser.Roles property.
    // Exists to satisfy the IUser interface but is not normally used.
    // Used only when the client code types this object the interface, IUser.
    // Otherwise ignored.
    ICollection<IRole> IUser.Roles 
    { 
        get { return this.Roles as ICollection<IRole>; }
        set { this.Roles = value as ICollection<Role>; }
    }

    // This property will be used in most cases.
    // Used when the client code types this object as the concrete type, User.
    public ICollection<Role> Roles { get; set; }
}
...