使用接口和 EF Fluent API

发布于 2024-12-14 09:26:43 字数 3030 浏览 2 评论 0原文

代码

我将向您展示代码,然后解释问题

接口

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 类型的集合 Roles

实现

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 配置

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 将生成关系模型,其中 < code>User 和 Role (应该是多对多)

我相信这是因为 User 类中,有一个集合类型 ICollection< IRole>而不是 ICollection 类型。

问题

问题是,如何解决这个问题? 如何映射集合public ICollection角色{获取;放;使用 Fluent API EF

Code

I will show you the code and then explain the problem

Interfaces

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

Notice that the interface IUser define a collection Roles of type IRole

Implementation

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

Note that the configuration EntityTypeConfiguration where T is the implementation and not the interface (the EF does not allow to put the interface as T)

Problem

#1 situation:

If you run the application, to generate the relational model, the following error occurs:

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 situation:

If you comment out the line HasMany(r => r.Roles).WithMany(); EF will generate the relational model with no relationship between User and Role (which should be many to many)

I believe this is because the User class, there is a collection type ICollection<IRole> and not of kind ICollection.

Question

The question is, how to solve this problem?
How to map the collection public ICollection<IRole> Roles { get; set; } using Fluent API EF

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绿光 2024-12-21 09:26:43

CodeFirst 不支持映射接口。您需要更改它以引用 Role 具体类。

CodeFirst doesn't support mapping interfaces. You will need to change it to reference the Role concrete class.

恋你朝朝暮暮 2024-12-21 09:26:43

以下是我将如何实现您的接口,以解决贝蒂描述的问题。

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

Here's how I would implement your interfaces in order to work around the problem that Betty described.

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; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文