我使用 EF 创建了数据库表,并希望在 FriendInvites.SenderUserId 之间创建外键 FriendInvites.cs:
public class FriendInvites
{
[Key]
public int Id { get; set; }
//Foreign key to UserInfo userId
public string SenderUserId { get; set; } = string.Empty;
//Navigation property
public UserInfo SenderId { get; set; }
public string TargetUserId { get; set; } = string.Empty;
public UserInfo TargetId { get; set; }
}
和 UserInfo.UserId 用户信息.cs:
public class UserInfo
{
[Key]
public string UserId { get; set; } = string.Empty;
[Required]
public string UserName { get; set; } = string.Empty;
//Navigation property to GroupInvites
public ICollection<GroupInvites> GroupInvites;
//Navigation property to GroupsCreatorsList
public ICollection<GroupsCreatorsList> CreatorOfGroups;
//Navigation property to GroupMemberList
public ICollection<GroupMemberList> GroupMembers;
public ICollection<FriendInvites> SenderUsers;
public ICollection<FriendInvites> TargetUsers;
}
然而,它并没有达到预期的效果。我尝试在 SQL Server Management Studio 中创建这个外键,但也失败了。然后我发现这是由于数据类型不匹配造成的; UserInfo.UserId 定义为 nvarchar(450),而 FriendInvites.SenderUserId 定义为 nvarchar(max)。我更改了 SQL Server 中的数据类型,这使我能够成功创建外键。
随后,我尝试在 OnModelCreating() 方法中显式指定数据类型:
modelBuilder.Entity<FriendInvites>()
.Property(e => e.SenderUserId).HasColumnType("nvarchar(450)");
modelBuilder.Entity<FriendInvites>()
.Property(e => e.TargetUserId).HasColumnType("nvarchar(450)");
但该列继续创建为 nvarchar(max)。我不确定为什么会发生这种情况,特别是因为之前一切都运行良好(我在引用 UserInfo.UserId 主键的不同表中创建了外键)。”
这是具有 UserInfo.UserId 列外键的其他类的示例:
public class GroupsCreatorsList
{
[Key]
public Guid GroupId { get; set; }
[Required]
public string GroupName { get; set; } = string.Empty;
//Foreighn key to UserInfo.UserId
public string CreatorId { get; set; } = string.Empty;
//Navigation property to UserInfo
public UserInfo Creator { get; set; }
//Navigation property to GroupInvites
public ICollection<GroupInvites> GroupInvites { get; set; }
//Navigation property to GroupMemberList
public ICollection<GroupMemberList> GroupMembers { get; set; }
}
这是外键的设置:
modelBuilder.Entity<UserInfo>()
.HasMany(e => e.CreatorOfGroups)
.WithOne(e => e.Creator)
.HasForeignKey(e => e.CreatorId)
.IsRequired();
你建议我做什么?
首先,如果您好奇为什么 EF 选择
NVARCHAR(450)
,那就是关于最大索引长度!
我之前遇到过这个有趣的问题,我在 EF core repo 上创建了一个问题,你可以在这里查看:
https://github.com/dotnet/efcore/issues/31167
简而言之,由于 SQL Server 索引的最大长度为 900 个字符,EF 决定将其中一半设置为 450 个字符,因此 EF 认为该列可能还有另一个复合索引。但您可以使用
HasMaxLength
以编程方式更改长度。
您提到您手动更改了数据库架构来为表设置外键,这是不好的并且会影响 EF 处理迁移。
我的建议是,如果可能的话,恢复有关这些表的最近迁移,并尝试通过在主键和外键上设置 HasMaxLength 来再次创建迁移。
不过,从性能的角度来看,我不喜欢将
string
属性设置为主键。因此,您可以使用 long
设置另一个 IDENTITY(1,1)
列作为 ID,然后在用户名上放置唯一索引。如果根据你的逻辑可能的话,再一次。