EF Core 3. Определение отношения «многие ко многим» с существующей БД - PullRequest
1 голос
/ 27 сентября 2019

У меня есть существующая база данных SQL, которая очень старая и схема не очень хорошая, но я не могу ее изменить, мне приходится с этим жить.

Я новичок в Entity Framework ииспользуя EF Core 3 , чтобы попытаться создать базовое приложение CRUD.У меня трудности с отношениями «многие ко многим».

В приведенном ниже примере я приведу сокращенное / фиктивное представление сценария.

Итак, вБД У меня есть две таблицы [People] и [The_Cars], и есть таблица «связывания», которая называется [People__The_Cars].Да, ужасные имена таблиц ....

Определение каждой таблицы следующее:

CREATE TABLE [dbo].[People](
    [PeopleID] [varchar](10) NOT NULL),
    [Name] [varchar](255) NOT NULL)

Это первичный ключ PeopleID

CREATE TABLE [dbo].[The_Cars](
    [car_id] [int] NOT NULL,
    [car_name] [varchar](255) NOT NULL)

ThisНЕ имеет первичного ключа ....

CREATE TABLE [dbo].[People__The_Cars](
    [People__The_Cars_ID] [int] NOT NULL,
    [car_name] [nvarchar](255) NOT NULL,
    [PeopleID] [nvarchar](255) NOT NULL,

У него есть первичный ключ, но нет внешних ключей.Автомобиль "ФК" идет по названию, а не по удостоверению личности.И типы данных не совпадают [PeopleID is varchar (10) в таблице [People], но nvarchar (255) в этой таблице ссылок].Также используйте varchar vs nvarchar.

В C # я создал несколько классов для представления их с приведенными именами:

Для [Люди]

public class People
    {
        [StringLength(10)]
        [Required]
        public string ID{ get; set; }

        [StringLength(255)]
        [Required]
        public string Name { get; set; }

    public ICollection<People__The_Cars> PeopleCars{ get; set; }
}

для[The_Cars]

public class The_Cars
    {
        [Required]
        public int Id{ get; set; }

        [StringLength(255)]
        [Required]
        public string Name { get; set; }

    public ICollection<People__The_Cars> PeopleCars{ get; set; }
}

для таблицы ссылок

public class People__The_Cars
    {
        [Required]
        public int Id{ get; set; }

        [StringLength(10)]
        [Required]
        public string PeopleId { get; set; }

        [StringLength(255)]
        [Required]
        public string CarName { get; set; }

public People Person{ get; set; }
public The_Cars Car{ get; set; }
}

(аннотации данных отражают типы данных первичной таблицы)

Теперь в классе контекста данных

public class MyContext : DbContext
{
    public OpdxDestinationsContext(DbContextOptions<MyContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<People>(e =>
            {
                e.HasKey(i => i.Id);
                e.Property(i => i.Id).HasColumnName("PeopleID");
            });

        modelBuilder
            .Entity<People__The_Cars>(e =>
            {
                e.HasKey(i => i.Name);
                e.Property(i => i.Id).HasColumnName("People__The_Cars_ID");
                e.Property(i => i.CarName).HasColumnName("car_name");
            });

        modelBuilder
            .Entity<Software_Vendor_Destinations>(e =>
            {
                e.HasKey(i => new {i.PeopleId, i.CarName });
                e.Property(i => i.Id).HasColumnName("Software_Vendor_Destinations_Id");
                e.Property(i => i.CarName).HasColumnName("car_name");
                e.Property(i => i.DestinationId).HasColumnName("PeopleID");
            });

        modelBuilder.Entity<People__The_Cars>()
            .HasOne(x => x.People)
            .WithMany(m => m.PeopleCars)
            .HasForeignKey(x => x.CarName);

        modelBuilder.Entity<People__The_Cars>()
            .HasOne(x => x.Car)
            .WithMany(m => m.PeopleCars)
            .HasForeignKey(x => x.PeopleId);

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<People> People{ get; set; }

    public DbSet<Cars> Cars{ get; set; }
}

Итак, несколько вопросов.

  • Я использовал «HasKey» для таблиц без ключей.Они должны сделать.Это плохая практика, или я должен быть правдивым и использовать HasNoKey, когда кто-то отсутствует.
  • Как мне тогда установить отношение «многие ко многим» с этими объектами?«Таблица связей» на самом деле предназначена для определения отношения «многие к одному ко многим» в БД и не кажется мне чем-то, что я хочу раскрыть в своих сущностях.

Так много всего, что нужно изучить...

1 Ответ

0 голосов
/ 27 сентября 2019

На мой взгляд, вам лучше использовать то же имя столбца в Db, что и в классе, представляющем таблицу db.поэтому я бы не стал это делать:

e.Property(i => i.ID).HasColumnName("People__The_Cars_ID");
e.Property(i => i.CarName).HasColumnName("car_name");

также вы можете игнорировать ID People__The_Cars, игнорируя его, а также удалить атрибут [Required]:

e.Ignore(i => i.ID);

, тогда я рекомендую вам определитьотношение вашей соединительной таблицы, например, ниже

, если CarName уникально:

e.HasOne(o => o.Car).WithMany(m => m.PeopleCars).HasForeignKey(f => f.CarName);
e.HasOne(o => o.Person).WithMany(m => m.PeopleCars).HasForeignKey(f => f.PeopleID);

в противном случае, иметь свойство int Named CarID:

public class People__The_Cars
{
    public int ID { get; set; }

    [StringLength(10)]
    [Required] public string PeopleID { get; set; }

    [StringLength(255)]
    [Required]
    public string CarName { get; set; }

    [Required]
    public int CarID { get; set; }

    public People Person { get; set; }
    public The_Cars Car { get; set; }
}

, а затем определить отношениемежду ними как ниже:

 e.HasOne(o => o.Car).WithMany(m => m.PeopleCars).HasForeignKey(f => f.CarName);
 e.HasOne(o => o.Person).WithMany(m => m.PeopleCars).HasForeignKey(f => f.CarID);
...