我和我都拥有数据库EF,并为Entity Framework手动创建模型类-我没有生成任何模型。
我收到此错误:
ModelValidationException未处理HResult = -2146233088消息=在模型生成期间检测到一个或多个验证错误:UserToGroup EntityType'UserToGroup'没有定义键。定义此EntityType的键。 UserToGroup EntityType EntitySet'UserToGroup'基于未定义键的'UserToGroup'类型。
模型类:
public class Group
{
[key]
public int ID { get; set; }
public string Name { get; set; }
public int ClubId { get; set; }
}
public class User
{
[key]
public int ID { get; set; }
public string Name { get; set; }
public string email { get; set; }
}
public class UserToGroup
{
public int GroupID { get; set; }
public int UserID { get; set; }
}
在数据库脚本表UserToGroup
中:
CREATE TABLE [dbo].[usertogroup]
(
[groupid] [INT] NOT NULL,
[userid] [INT] NOT NULL,
CONSTRAINT [IX_UserToGroup]
UNIQUE NONCLUSTERED ([groupid] ASC, [userid] ASC)
)
ON [PRIMARY]
GO
ALTER TABLE [dbo].[usertogroup] WITH CHECK
ADD CONSTRAINT [FK_UserToGroup_Group]
FOREIGN KEY([groupid]) REFERENCES [dbo].[group] ([id])
GO
ALTER TABLE [dbo].[usertogroup] CHECK CONSTRAINT [FK_UserToGroup_Group]
GO
ALTER TABLE [dbo].[usertogroup] WITH CHECK
ADD CONSTRAINT [FK_UserToGroup_User]
FOREIGN KEY([userid]) REFERENCES [dbo].[user] ([id])
GO
ALTER TABLE [dbo].[usertogroup] CHECK CONSTRAINT [FK_UserToGroup_User]
GO
我的课堂背景:
public class myContext : DbContextBase
{
public const string ConnectionStringName = @"xxxxxx";
public myContext() : base(ConnectionStringName)
{ }
public DbSet<Group> Group { get; set; }
public DbSet<User> User { get; set; }
public DbSet<User> UserToGroup { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
在此先感谢您的帮助
答案 0 :(得分:1)
EF需要一个键定义才能跟踪实体,即使该表没有PK。如果您的联接表仅包含2个FK,则您有两种选择。
选项1:多对多,无需加入实体。 为此,您可以映射用户(以及用户(可选)中的用户)的组集合,然后设置HasMany.WithMany关系。您告诉EF有关连接表/列的信息,然后可以在没有连接实体的情况下访问集合。 即
public class User
{
// User columns...
public ICollection<Group> Groups { get; set; } = new List<Group>();
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
ToTable("user");
HasKey(x => x.UserId)
.Property(x => x.UserId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasMany(x => x/Groups)
.WithMany() // if Group has no Users collection, otherwise .WithMany(x => x.Users)
.Map(x =>
{
x.ToTable("usertogroup");
x.MapLeftKey("userId");
x.MapRightKey("groupId");
});
}
}
要获取用户组:
user.Groups;
选项2:映射加入实体(用户到组)。如果联接表具有其他列(例如,修改的跟踪列),则需要这样做。在这种情况下,您需要在表上映射两个FK组合的键。
public class User
{
// User columns...
public virtual ICollection<UserToGroup> UserGroups { get; set; } = new List<UserToGroup>();
}
public class UserToGroup
{
public int UserId { get; set; }
public int GroupId { get; set; }
public virtual User User { get; set; }
public virtual Group Group { get; set; }
}
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
ToTable("user");
HasKey(x => x.UserId)
.Property(x => x.UserId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasMany(x => x.UserGroups)
.WithRequired(x => x.User);
}
public class UserGroupConfiguration : EntityTypeConfiguration<UserGroup>
{
public UserGroupConfiguration()
{
ToTable("usertogroup");
HasKey(x => new { x.UserId, x.GroupId });
}
}
这告诉EF如何将用户映射到组关联。有时您可能想要映射未定义PK的表。 EF需要一个Key来跟踪实体,因此在这些情况下,您将使用相同的技术来指定所有必需的列,以使其能够将一行与任何一行以及所有其他行区分开。如果您创建具有一组列的键,则必须确保它们在表中的唯一性,否则您将得到意想不到的结果。 (例如读取或写入表中的错误行。)
要获取用户的组:
user.UserGroups.Select(x => x.Group);