Entity Framework database-first - 不带主键的表

Entity Framework database-first - table without primary key

提问人:sam it 提问时间:9/22/2018 最后编辑:marc_ssam it 更新时间:9/22/2018 访问量:2130

问:

我有数据库第一个 EF 和我,并为实体框架手动创建模型类 - 我没有生成任何模型。

我收到此错误:

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);
   }
}

提前感谢您的任何帮助

C# 实体框架 T-SQL

评论

0赞 TheGeneral 9/22/2018
Sam 欢迎来到 stackoverflow,请花点时间格式化您的代码和您的问题,以便将来

答:

1赞 Steve Py 9/22/2018 #1

EF 需要键定义才能跟踪实体,即使表没有 PK 也是如此。在您的情况下,如果连接表仅包含 2 个 FK,则有几个选项。

选项 1:不加入实体的多对多。 为此,您需要映射用户(以及组中的可选用户)中的组集合,然后设置 HasMany.WithMany 关系。将联接表/列告知 EF,然后可以在没有联接实体的情况下访问集合。 J.F.

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:映射联接实体 (usertogroup)。如果联接表具有其他列(如修改后的跟踪列),则需要这样做。在本例中,您可以在表上映射两个 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);