2016-12-15 2 views
1

Я работаю с EF Core 1.1 в проекте asp.net mvc core и наткнулся на то, что я думаю, является не оптимальной генерацией SQL. Но эй, я не эксперт, так что я мог бы быть неправильно укомплектовать :)Entity Framework Core model one-to-one

Модели

public class Influencer 
{ 
    public int Id { get; set; } 

    public Instagram Instagram { get; set; } 

    public YouTube YouTube { get; set; } 

    // In the future, more social channels will be added so 
    // this is another concern I have how to architect/model properly 
} 

public class Instagram 
{ 
    public int Id { get; set;} 
    public string UserId { get; set; } 
    // More properties such as bio, image url, website and other stuff 
} 

public class YouTube 
{ 
    public int Id { get; set; } 
    public string ChannelId { get; set; } 
    // More properties such as bio, image url, statistics etc 
} 

UserId и ChannelId являются «естественные ключи» (простите за злоупотребление правильным термином SQL :) и Id свойства «искусственные ключи» в надежде создать интерфейс/базовый класс для просто различных операций, таких как удаление, обновление.

Так что на вопрос - как правильно установить это в modelBuilder?

SQL, я думаю, что должно быть лучше что-то вроде

Instagram 
- Id (PK) 
- UserId (AK) 
- InfluencerId (FK) 
YouTube 
- Id (PK) 
- ChannelId (AK) 
- InfluencerId (FK) 
Influencer 
- Id 

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

О текущем моделировании

modelBuilder 
    .Entity<InstagramChannel>() 
    .HasAlternateKey(i => i.UserId) 
    .HasName("AK_UserId"); 

modelBuilder 
    .Entity<Profile>() 
    .HasOne<Instagram>() 
    .WithOne() 
    .HasForeignKey(typeof(Instagram), "ProfileId") 
    .HasConstraintName("FK_Instagram_Profile") 
    .OnDelete(DeleteBehavior.Cascade); 

Это, однако, генерирует ключ для каждого из социальных платформ на Influencer, такие как Influencer.InstagramId, Influencer.YouTubeId вызывает два изменения в базу данных, когда социальная платформа удаляется.

Редактировать Так маркировка свойств Instagram, YouTube не отображенные произвел SQL, что я искал. Но теперь я не уверен, что я что-то пропустил - возможно, некоторые возможности оптимизации включены в EF, если «родительская таблица» имеет прямое отношение к связанным с ней таблицам. Возможно, это просто делает невозможным для EF оценивать заявление Include(i => i.Instagram), поскольку он, вероятно, хочет сделать это без необходимости соединения.

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

Благодаря

ответ

1

Вы можете достичь своей цели, даже без использования modelBuilder, используя атрибуты:

public class Influencer 
{ 
    public int Id { get; set; } 

    [InverseProperty("Influencer")] 
    public Instagram Instagram { get; set; } 

    [InverseProperty("Influencer")] 
    public YouTube YouTube { get; set; } 
} 

public class Instagram 
{ 
    public int Id { get; set;} 
    public string UserId { get; set; } 

    public int InfluencerId { get; set; } 

    [ForeignKey("InfluencerId")] 
    public virtual Influencer Influencer { get; set; } 
} 

public class YouTube 
{ 
    public int Id { get; set; } 
    public string ChannelId { get; set; } 

    public int InfluencerId { get; set; } 

    [ForeignKey("InfluencerId")] 
    public virtual Influencer Influencer { get; set; } 
} 

Вы можете удалить InfluencerId свойства, если вам не нравится их (я предпочитаю иметь явное поле идентификатора быть в состоянии установить int-value там вместо назначения Influencer экземпляров и чтения их из БД только для этого).

Кроме того, вы можете удалить virtual ключевые слова, потому что EF ядро ​​(в настоящее время) не требуют их (но это также не поддерживает LazyLoading, поэтому я предпочитаю держать «виртуальный» в случае, если это потребуется позже)

+0

Спасибо!Попробуем это, и он выглядит чистым - менее подробный, чем синтаксис конструктора модели. Можно ли добавить уникальное ограничение, используя аннотации данных? – joacar

+0

Нет, в настоящее время EF Core не поддерживает атрибут «Index» (но есть [проблема] (https://github.com/aspnet/EntityFramework/issues/4050) о github о его добавлении) – Dmitry

Смежные вопросы