Entity Framework database-first - таблица без первичного ключа - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть база данных 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);
   }
}

Заранее благодарен за любую помощь

1 Ответ

0 голосов
/ 22 сентября 2018

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 требует Ключ для отслеживания сущностей, поэтому в этих случаях вы используете ту же технику для обозначения всех необходимых столбцов, которые позволяют ему отличать одну строку от любой и все остальные.Если вы создаете ключ с набором столбцов, они должны быть уникальными в таблице, иначе вы получите неожиданные результаты.(например, чтение или запись неправильной строки в таблице.)

Чтобы получить группы для пользователя: user.UserGroups.Select(x => x.Group);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...