【问题标题】:EF Unidirectional One to Many relationshipEF 单向一对多关系
【发布时间】:2013-12-28 06:10:37
【问题描述】:

我有一个 IdentityUser 类,它有一个名为 Logins 的导航属性,其类型为 Collection

public class IdentityUser : IUser
{
    public IdentityUser();
    public IdentityUser(string userName);

    public virtual ICollection<IdentityUserClaim> Claims { get; }
    public virtual string Id { get; set; }
    public virtual ICollection<IdentityUserLogin> Logins { get; }
    public virtual string PasswordHash { get; set; }
    public virtual ICollection<IdentityUserRole> Roles { get; }
    public virtual string SecurityStamp { get; set; }
    public virtual string UserName { get; set; }
}

IdentityUserLogin 类中有一个名为 User 的导航属性,其类型为 IdentityUser

public class IdentityUserLogin
{
    public IdentityUserLogin();

    public virtual string LoginProvider { get; set; }
    public virtual string ProviderKey { get; set; }
    public virtual IdentityUser User { get; set; }
    public virtual string UserId { get; set; }
}

从这里我可以看出

  1. IdentityUser 可以有 0 到多个 IdentityUserLogin
  2. IdentityUserLogin 必须有一个IdentityUser

我试过了:

        this.HasRequired(t => t.User)
            .WithRequiredPrincipal();

但它正在寻找 IdentityUser_Id 的外键,但它应该使用 UserId(这是 IdentityUserLogin 的属性)

然后我尝试了:

        this.HasRequired(t => t.User)
            .WithMany(t => t.Logins)
            .HasForeignKey(t => t.UserId);

但我收到一条错误消息:

IdentityUserLogin_User_Source::多重性在关系“IdentityUserLogin_User”中的角色“IdentityUserLogin_User_Source”中无效。因为从属角色是指关键属性,所以从属角色的多重性的上限必须是'1'。

有谁知道我如何声明关系并指定外键?

更新 1

这是我的 IdentityUserLogin 地图类:

public class IdentityUserLoginMap : EntityTypeConfiguration<IdentityUserLogin>
{
    public IdentityUserLoginMap()
    {
        // Primary Key
        this.HasKey(t => t.UserId);

        // Properties
        this.Property(t => t.LoginProvider)
            .IsRequired()
            .HasMaxLength(128);

        this.Property(t => t.ProviderKey)
            .IsRequired()
            .HasMaxLength(128);

        this.Property(t => t.UserId)
            .IsRequired()
            .HasMaxLength(128);

        // Table & Column Mappings
        this.ToTable("IdentityUserLogins");
        this.Property(t => t.LoginProvider).HasColumnName("LoginProvider");
        this.Property(t => t.ProviderKey).HasColumnName("ProviderKey");
        this.Property(t => t.UserId).HasColumnName("UserId");

        // Relationships
        this.HasRequired(t => t.User)
            .WithRequiredPrincipal();
    }
}

如你所见,我正在设置一个主键

更新 2

只是为了解释一下,这里是用户表:

CREATE TABLE [dbo].[IdentityUsers](
    [Id] [nvarchar](128) NOT NULL,
    [UserName] [nvarchar](max) NULL,
    [PasswordHash] [nvarchar](max) NULL,
    [SecurityStamp] [nvarchar](max) NULL,
    [Discriminator] [nvarchar](128) NOT NULL,
 CONSTRAINT [PK_dbo.IdentityUsers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
)

IdentityUserLogin 表应如下所示:

CREATE TABLE [dbo].[IdentityUserLogins](
    [LoginProvider] [nvarchar](128) NOT NULL,
    [ProviderKey] [nvarchar](128) NOT NULL,
    [UserId] [nvarchar](128) NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

但是当我在一个新数据库上运行我的代码时,我得到了这个:

CREATE TABLE [dbo].[IdentityUserLogins](
    [UserId] [nvarchar](128) NOT NULL,
    [LoginProvider] [nvarchar](128) NOT NULL,
    [ProviderKey] [nvarchar](128) NOT NULL,
    [IdentityUser_Id] [nvarchar](128) NULL,
 CONSTRAINT [PK_dbo.IdentityUserLogins] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

如您所见,IdentityUser_Id 已过时,它应该使用主键。 这是我的目标:)

【问题讨论】:

    标签: c# entity-framework asp.net-mvc-5


    【解决方案1】:

    您可能会因为未向您的类IdentityUserLogin 提供主键属性而混淆 EF。 我认为在这种情况下,EF 将 UserId 作为您的主键。由于主键不能重复,并且您映射的关系为WithMany,因此它们相互冲突。

    更新 1

    这与您的模型冲突:

    this.HasRequired(t =&gt; t.User).WithRequiredPrincipal();

    因为在课堂上IdentityUser 你有

    public virtual ICollection&amp;ltIdentityUserLogin&gt; Logins { get; set; }

    您需要使用WithMany(t =&gt; t.Logins) 以使您的配置与模型匹配。

    更新 2
    这是您需要的一对一关系

    public class IdentityUser
    {
      ... 
      public virtual IdentityUserLogin Login { get; set; }
      ...
    }

    this.HasRequired(t =&gt; t.User).WithRequiredPrincipal(t =&gt; t.Login);

    【讨论】:

    • 我正在设置一个主键,我已经更新了我的帖子以显示我的映射
    • 但这就是问题所在,您不能使用 UserId 作为主键并具有一对多的关系,因为这需要同一个键出现两次。
    • 那么这证实了我的回答,你不能说UserId 是唯一的,另一方面你告诉EF 1 IdentityUser.Id 可以在IdentityUserLogin.UserId 中多次存在,如果这是你的主键而且你不能有很多。
    • 几件事;没有这样的方法是 ToMany 我假设你的意思是我尝试过的 WithMany(它实际上在帖子中)。另外,如果您没有注意到,这两个类都是默认的 .net 身份类,并且关系存在于数据库中,所以除非我遗漏了什么,否则它们具有 UserId 作为主键和外键,所以它必须是可映射的.
    • 那么您需要在您的 IdentityUser 类中使用 ICollection 登录 IdentityUserLogin 登录
    猜你喜欢
    • 2022-01-23
    • 2017-10-26
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多