实体框架数据库优先:实体框架不会自动将外键映射到唯一键
本文关键字:框架 实体 映射 一键 唯一 数据库 | 更新日期: 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]))