Кодекс Entity Framework От первого к нулю или одно отношение с отдельной идентичностью - PullRequest
0 голосов
/ 21 января 2019

У меня есть два класса как таковых:

public class Event
{
    [Key]
    [Required]
    public long Id { get; set; }

    [InverseProperty("Event")          
    public virtual Record Record{ get; set; }
}


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

    [ForeignKey("Event")]
    public long? EventId { get; set; }

    public virtual Event Event{ get; set; }
}

Однако я получаю ожидаемые ошибки множественности с этой настройкой.В итоге я хочу получить следующее:

  • Событие, существующее без записи

  • Запись, существующее без события

  • Событие, существующее с записью (и запись в которой хранится идентификатор события)

Возможно ли это и нужно ли использовать FluentApi вместо Data Annotations?

Я не хочу добавлять какие-либо поля или ключи в таблицу событий.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вы были правы, указав только одну из двух сторон отношения как внешний ключ. Сначала я подумал, что обеим сторонам нужен обнуляемый внешний ключ. Однако, если вы сделаете это, то у события 1 может быть внешний ключ для записи 2 с внешним ключом для события 3 с внешним ключом для записи 4 и т. Д.

Очевидно, что в этих ситуациях только одна из двух сторон должна иметь внешний ключ.

Глядя на Настройка отношения один-к-нулю-одному , я вижу, что достаточно:

class Event
{
    public long Id { get; set; }
    public string Name { get; set; }

    // Every Event has zero or one Record
    public virtual Record Record { get; set; }
}
class Record
{
    public long Id { get; set; }
    public string Name { get; set; }

    // Every Record has zero or one Event
    public virtual Event Event { get; set; }
}

И DbContext:

class OneToOneContext : DbContext
{
    public OneToOneContext(): base("OneToOneDemo"){}

    public DbSet<Event> Events { get; set; }
    public DbSet<Record> Records { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Record>()
            .HasOptional(record => record.Event)
            .WithOptionalDependent(ev => ev.Record)
            .WillCascadeOnDelete(false);
    }
}

Свободный API сообщает создателю модели, что каждая запись имеет ноль или одно событие, с ноль или одну запись. Запись объявлена ​​зависимой. Это гарантирует, что запись будет иметь иностранца в этом отношении.

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

Я смог добавить: событие без записи, запись без события, событие с записью и запись с событием:

using (var dbContext = new OneToOneContext())
{
    dbContext.Events.Add(new Event { Name = "Event without Record"});
    dbContext.Records.Add(new Record { Name = "Record without Event" });

    dbContext.Events.Add(new Event
    {
        Name = "Event A with Record",
        Record = new Record { Name = "Record of Event A" },
    });

    dbContext.Records.Add(new Record
    {
        Name = "Record B with Event",
        Event = new Event { Name = "Event of Record B" },
    });

    dbContext.SaveChanges();
}
0 голосов
/ 21 января 2019

В EF 6.x, вам необходимо настроить Fluent API следующим образом:

 modelBuilder.Entity<Record>()
       .HasOptional(x => x.Event)
       .WithOptionalPrincipal(x => x.Record)
       .Map(a => a.MapKey("RecordId"));

В EF Core, Ваша текущая модель настроенадостаточно хорошо!Больше ничего не нужно делать.

...