实体框架数据库优先:实体框架不会自动将外键映射到唯一键

本文关键字:框架 实体 映射 一键 唯一 数据库 | 更新日期: 2023-09-27 17:56:16

假设以下两个表:

CREATE TABLE [dbo].[Users]
(
    [UserId] VARCHAR(36) NOT NULL PRIMARY KEY, /*Using GUID IDs for better identification*/ 
    [Email] NVARCHAR(50) NOT NULL UNIQUE, 
    ......
)
CREATE TABLE [dbo].[UserLogins]
(
   [Email] NVARCHAR(50) NOT NULL PRIMARY KEY,
   [Password] VARCHAR(32) NOT NULL,
   .....
   CONSTRAINT [UserLogins_Users_FK] FOREIGN KEY(Email) REFERENCES [Users](Email) ON DELETE CASCADE
)

从数据库使用 EF 自动映射时,Users表不会映射到UserLogins表。假设无法反转唯一键和主键,并且我需要这样做以节省非常小的存储区域,因为VARCHAR(36)小于NVARCHAR(50),强制EF自动映射这两个表的正确解决方案是什么?

实体框架数据库优先:实体框架不会自动将外键映射到唯一键

尝试先使用代码(它在我的本地计算机上测试成功):

  public class Users
{
    public int UserId { get; set; }
    public string Emails { get; set; }
    public UserLogins UserLogins { get; set; }
}
public class UserLogins
{
    public string Email { get; set; }
    public string Password { get; set; }
    public ICollection<Users> Users { get; set; }
}
public class UsersMap : EntityTypeConfiguration<Users>
{
    public UsersMap()
    {
        this.HasKey(x => x.UserId);
        this.Property(x => x.Emails).HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute() { IsUnique = true }));
        this.HasRequired(x => x.UserLogins).
            WithMany(x => x.Users).HasForeignKey(x => x.Emails);
    }
}
public class UserLoginMap : EntityTypeConfiguration<UserLogins>
{
    public UserLoginMap()
    {
        this.HasKey(x => x.Email);
    }
}
public class TotalDbContext : DbContext
{
    public TotalDbContext()
        : base("Name=total")
    { 
    }
    public DbSet<Users> Users { get; set; }
    public DbSet<UserLogins> UserLogins { get; set; }
    protected override void OnModelCreating(DbModelBuilder model)
    {
        model.Configurations.Add(new UsersMap());
        model.Configurations.Add(new UserLoginMap());

    }
}

然后它将创建下面的代码:

 public override void Up()
    {
        CreateTable(
            "dbo.UserLogins",
            c => new
                {
                    Email = c.String(nullable: false, maxLength: 128),
                    Password = c.String(),
                })
            .PrimaryKey(t => t.Email);
        CreateTable(
            "dbo.Users",
            c => new
                {
                    UserId = c.Int(nullable: false, identity: true),
                    Emails = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.UserId)
            .ForeignKey("dbo.UserLogins", t => t.Emails, cascadeDelete: true)
            .Index(t => t.Emails, unique: true);
    }

它将创建如下表:

CREATE TABLE [dbo].[UserLogins] (
[Email] [nvarchar](128) NOT NULL,
[Password] [nvarchar](max),
CONSTRAINT [PK_dbo.UserLogins] PRIMARY KEY ([Email]))

 CREATE TABLE [dbo].[Users] (
[UserId] [int] NOT NULL IDENTITY,
[Emails] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY ([UserId]) )

 CREATE UNIQUE INDEX [IX_Emails] ON [dbo].[Users]([Emails])
 ALTER TABLE [dbo].[Users] ADD CONSTRAINT [FK_dbo.Users_dbo.UserLogins_Emails] FOREIGN KEY ([Emails]) REFERENCES [dbo].[UserLogins] ([Email]) ON DELETE CASCADE
 CREATE TABLE [dbo].[__MigrationHistory] (
[MigrationId] [nvarchar](150) NOT NULL,
[ContextKey] [nvarchar](300) NOT NULL,
[Model] [varbinary](max) NOT NULL,
[ProductVersion] [nvarchar](32) NOT NULL,
CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey]))