Лучше использовать две таблицы «многие ко многим» или одну таблицу с тремя ссылками на внешние ключи

#c# #sql #fluent-nhibernate #many-to-many

#c# #sql #свободно-nhibernate #многие-ко-многим #многие ко многим

Вопрос:

Я создаю веб-службу WCF и сопоставляю свою доменную модель с использованием Fluent Nhibernate, и я заметил, что объекты могут быть представлены по-разному, как и данные, стоящие за ними.

По сути, у меня есть три таблицы: одна — таблица собраний, одна — таблица мест собраний, а другая — таблица участников. В принципе, приложение будет работать таким образом, что собрание будет назначено, и участники пойдут, но они также будут голосовать за Место проведения. Таким образом, в основном на многих собраниях много участников, и многие участники имеют много голосов (при условии, что установлено ограничение, так что у них есть только один голос на собрание. Это выглядит так. Итак, чтобы представить это, у меня есть три базовые таблицы и Многие Ко многим (ко многим? Таблица)

 CREATE TABLE Meetings (
    Id INT NOT NULL PRIMARY KEY IDENTITY,
    Name NOT NULL,
    StartTime DATETIME NOT NULL,
    EndTime DATETIME NULL,
)

CREATE TABLE Attendees (
    Id INT NOT NULL PRIMARY KEY IDENTITY,
    Name NOT NULL
)

CREATE TABLE MeetingPlaces (
    Id INT NOT NULL PRIMARY KEY IDENTITY,
    Name NOT NULL,
    Address NULL
)

CREATE TABLE MeetingAttendees (
    Id INT NOT NULL PRIMARY KEY IDENTITY, 
    MeetingId INT NOT NULL, 
    AttendeeId INT NOT NULL, 
    MeetingPlaceId INT NULL, --in case they have no preference

    CONSTRAINT  FK_MeetingAttendees_To_Events FOREIGN KEY (MeetingId) REFERENCES Meetings(Id),
    CONSTRAINT  FK_MeetingAttendees_To_Attendees FOREIGN KEY (AttendeeId) REFERENCES Attendees(Id),
    CONSTRAINT  FK_MeetingAttendees_To_MeetingPlaces FOREIGN KEY (MeetingPlaceId) REFERENCES MeetingPlaces(Id)
)
GO

CREATE UNIQUE INDEX U_IDX_Meeting_Attendees ON MeetingAttendees(MeetingId, AttendeeId)
GO
  

Мой вопрос в том, что лучше использовать эту структуру или создать две отдельные таблицы. Одна представляет участников собрания, а другая представляет голосование участника за участников собрания как таковое:

 CREATE TABLE MeetingAttendees
    Id INT NOT NULL PRIMARY KEY IDENTITY, 
    MeetingId INT NOT NULL, 
    AttendeeId INT NOT NULL, 

    CONSTRAINT  FK_MeetingAttendees_To_Events FOREIGN KEY (MeetingId) REFERENCES Meetings(Id),
    CONSTRAINT  FK_MeetingAttendees_To_Attendees FOREIGN KEY (AttendeeId) REFERENCES Attendees(Id),
)
GO

CREATE UNIQUE INDEX U_IDX_Meeting_Attendees ON MeetingAttendees(MeetingId, AttendeeId)

CREATE TABLE AttendeeVote(
    Id INT NOT NULL PRIMARY KEY IDENTITY,
    MeetingAttendeeId INT NOT NULL,
    MeetingPlaceId INT NULL,

    CONSTRAINT FK_AttendeeVote_To_MeetingAttendees FOREIGN KEY (MeetingAttendeeId) REFERENCES MeetingAttendees(Id),
    CONSTRAINT FK_AttendeeVote_To_MeetingPlaces FOREIGN KEY (MeetingPlaceId) REFERENCE MeetingPlaces(Id)
)
  

Я обеспокоен, потому что я не уверен, насколько Fluent-NHibernate справится с первым решением, а второе, хотя и немного надуманное, кажется более конструктивным.

Ответ №1:

У вас должна быть ассоциативная сущность между каждым отношением «многие ко многим».

Если я правильно понимаю ваш случай:

  • Собрание (информация о собрании)
  • Участник (информация об участнике)
  • MeetingVote (meeting_id, attendee_id, дополнительная информация)
  • MeetingAttendee (meeting_id, attendee_id, дополнительная информация)

Это было бы нормализовано и правильно отображало поведение вашего приложения.

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

Комментарии:

1. В перечисленных вами случаях MeetingVote и MeetingAttendee совпадают, не уверен, что вы видите MeetingVote в вашем примере.

2. Возможно, я неправильно понял ваш вопрос. Таблица MeetingVote будет представлять, когда человек проголосовал за собрание? MeetingAttendee будет представлять, когда кто-то посещал собрание.

3. О, извините, голосование на собрании должно быть голосованием участников. Это когда участник (для собрания) голосует за место, где должно состояться собрание. Таким образом, собрание, участник и место связаны друг с другом моим первым решением.

4. Ааа, хорошо. Предположение, которое я вижу при использовании только одного вспомогательного объекта, заключается в том, что участник должен присутствовать и голосовать за место. Правильно ли это?

5. На самом деле, отличный момент, я полностью пропустил это. Я думаю, что участнику не обязательно идти на собрание, он действительно должен быть «Участником», и их классификация как участника зависит от ассоциативной таблицы. Я полагаю, я могу создать первую ассоциативную таблицу между участниками собрания в качестве участников собрания, тогда вторая будет между участниками собрания и местоположениями в качестве участников собрания. Таким образом, посещение собрания может быть необязательным, и я могу ограничить участника, который принимает участие в одном голосовании, уникальным индексом. Это кажется разумным?