MS SQL SERVER связь многие ко многим

280
15 января 2018, 06:24

Вопрос следующий. Есть 2 таблицы: МАРШРУТ: Достопримечательность:

В каждый маршрут входит несколько достопримечательностей. По идее надо создать связь один ко многим, но при такой связи в таблице Маршрут будут повторяться координаты для каждой достопримечательности. Как правильно сделать?

Answer 1

В вашем случае связь многие ко многим.

  1. Отдельная таблица для маршрутов.
  2. Отдельная таблица для достопримечательностей.
  3. Отдельная таблица для связи маршрутов и достопримечательностей.
Answer 2

Связь многие-ко-многим - это список одних элементов у другого. Согласно первой нормальной форме список не может быть в строке, только в столбце. Поэтому в нормализованной базе многие-ко-многим реализуются только через третью связующую таблицу (кстати, в ней не нужно вводить суррогатный ключ, а лучше использовать естественный составной из ключей обеих таблиц).

Но некоторые СУБД позволяют нарушать первую нормальную форму, вводя специальный тип "список", "массив" или "множество". В MS SQL такого типа нет, но есть два обходных маневра:

  1. Если, например, количество достопримечательностей в маршруте ограничено сверху каким-то малым числом, то можно сделать в таблице маршрутов столбцы ID1, ID2, ..., IDn для каждой точки маршрута

  2. Список можно эмулировать, сериализовав его в VARCHAR(MAX)

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

Так что лично я рекомендую использовать дополнительную таблицу. Ее, кстати, позднее можно дополнить, добавив туда, например, порядок следования и предположительное время в пути между соседними точками.

Answer 3
Attraction
namespace WindowsFormsApp1
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;
    [Table("Attraction")]
    public partial class Attraction
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Attraction()
        {
            RouteAttraction = new HashSet<RouteAttraction>();
        }
        public int id { get; set; }
        [Required]
        [StringLength(30)]
        public string Name { get; set; }
        [Required]
        public string Description { get; set; }
        [Required]
        public DbGeography Coordinate { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public string CoordinateOGC { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<RouteAttraction> RouteAttraction { get; set; }
    }
}

Route

namespace WindowsFormsApp1
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;
    [Table("Route")]
    public partial class Route
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Route()
        {
            RouteAttraction = new HashSet<RouteAttraction>();
        }
        public int ID { get; set; }
        [Required]
        public DbGeography Coordinates { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public string CoordinatesOGC { get; set; }
        [Required]
        public DbGeography CoordinatesStartingPointsRoute { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public string CoordinatesStartingPointsRouteOGC { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<RouteAttraction> RouteAttraction { get; set; }
    }
}

RouteAttraction

namespace WindowsFormsApp1
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;
    [Table("RouteAttraction")]
    public partial class RouteAttraction
    {
        public int Id { get; set; }
        public int RouteID { get; set; }
        public int AttractionID { get; set; }
        public virtual Attraction Attraction { get; set; }
        public virtual Route Route { get; set; }
    }
}

Model

namespace WindowsFormsApp1
{
    using System;
    using System.Data.Entity;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    public partial class Model3 : DbContext
    {
        public Model3()
            : base("name=Model3")
        {
        }
        public virtual DbSet<Attraction> Attraction { get; set; }
        public virtual DbSet<Route> Route { get; set; }
        public virtual DbSet<RouteAttraction> RouteAttraction { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Attraction>()
                .HasMany(e => e.RouteAttraction)
                .WithRequired(e => e.Attraction)
                .WillCascadeOnDelete(false);
            modelBuilder.Entity<Route>()
                .HasMany(e => e.RouteAttraction)
                .WithRequired(e => e.Route)
                .WillCascadeOnDelete(false);
        }
    }
}

Коллекция вида: Route(CoordinatesOGC->CoordinatesStartingPointsRouteOGC)Attraction(->Name->Description->CoordinateOGC)

Answer 4

Создал 3 таблицу. Получилось следующее:

Подскажите пожалуйста как сделать выборку с помощью LINQ заспроса чтобы у меня получилось коллекция следующего плана : (Координаты пути и координаты точек начала маршрута) - с 1 таблицы (Название, описание, координаты достопримечательности) - со 2 таблицы

READ ALSO
Привет мир на C#

Привет мир на C#

ЗдравствуйтеМне необходимо объединить в функции текст и переменную

238
Помогите разобраться с Charles

Помогите разобраться с Charles

Не могу разобраться как изменять IP в запросах в чарльзеПопробую объяснить - есть софт на C# использую dotnetbrowser

280
Копирование в Excel

Копирование в Excel

Как с помощью javascripta сделать так, чтобы массив текста копировался только в 1 ячейку экселя?

361
Функция JS не определенна [дубликат]

Функция JS не определенна [дубликат]

Данный вопрос уже был задан и имеет решение:

363