2017-01-24 4 views
1

У меня возникла странная проблема с EF Core 1.1. Я пытаюсь создать приложение, где некоторые объекты могут быть помечены, поэтому я создал абстрактный общий класс для списка таблиц связей. Проблема в том, что, похоже, EF не поддерживают наличие общих абстрактных классов, в которых работает FK (свойство Id).Ядро Entity Framework не поддерживает общие абстрактные объекты с отношением Meny2Meny?

Вот модели:

public abstract class TaggedEntityBase<T> : EntityBase 
{ 
    public ICollection<T> EntityTags { get; set; } 
    public List<Tag> Tags { get { return EntityTags?.Select(x => x.Tag).ToList(); } } 
} 

public class AddressTag 
{ 
    public long TagId { get; set; } 
    public Tag Tag { get; set; } 
    public long EntityId { get; set; } 
    public Address Entity { get; set; } 
} 

public class Address : TaggedEntityBase<AddressTag> 
{ 
    public string Street { get; set; } 
    public string City { get; set; } 
} 
public class Tag : EntityBase 
{ 
    public string Name { get; set; } 
    public virtual ICollection<AddressTag> AddressTags { get; set; } 
} 

Типового Builder Отображение:

public DbSet<Address> Addresses { get; set; } 
    public DbSet<AddressTag> AddressTag { get; set; } 
    public DbSet<Tag> Tags { get; set; } 

    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<AddressTag>() 
      .ToTable("AddressTag"); 

     modelBuilder.Entity<AddressTag>() 
      .HasKey(t => new { t.EntityId, t.TagId }); 
     modelBuilder.Entity<AddressTag>() 
     .HasOne(pt => pt.Entity) 
      .WithMany(p => p.EntityTags) 
      .HasForeignKey(p => p.EntityId); 
     modelBuilder.Entity<AddressTag>() 
     .HasOne(pt => pt.Tag) 
      .WithMany(p => p.AddressTags) 
      .HasForeignKey(p => p.TagId); 

    } 

Там ошибка, когда EF пытается принести Теги

Необработанного исключения типа «System .Data.SqlClient.SqlException 'произошел в Microsoft.EntityFrameworkCore.dll Дополнительная информация: Недопустимое имя столбца' AddressId '.

У меня даже нет этого удостоверения личности.

Примечание: когда я размещаю явно public ICollection<AddressTag> EntityTags { get; set; } внутри Адрес POCO, то он отлично работает, включая EntityTags.Tag тоже. Спасибо за любую помощь :)

+0

Если бы похож вопрос – miechooy

+0

Образец является неполным. 'EntityBase' класс отсутствует, и' public List Tags {get {return EntityTags? .Select (x => x.Tag) .ToList(); }} 'не компилируется (отсутствует ограничение на' T'). Не могли бы вы обновить сообщение с недостающими частями, чтобы сделать его воспроизводимым? –

ответ

1

Проблема не имеет ничего общего с общими и/или абстрактными базовыми классами сущностей.

Во-первых, чтобы сделать вашу модель образца компиляции, я добавил следующие классы

public abstract class EntityBase 
{ 
    public long Id { get; set; } 
} 

public abstract class EntityTagBase 
{ 
    public long TagId { get; set; } 
    public Tag Tag { get; set; } 
} 

модифицировали AddressTag класс следующим образом:

public class AddressTag : EntityTagBase 
{ 
    public long EntityId { get; set; } 
    public Address Entity { get; set; } 
} 

и добавил where T : EntityTagBase ограничение для TaggedEntityBase<T> класса, чтобы позволить Tag свойство аксессуар внутри Select(x => x.Tag).

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

migrationBuilder.CreateTable(
    name: "Tags", 
    columns: table => new 
    { 
     Id = table.Column<long>(nullable: false) 
      .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 
     AddressId = table.Column<long>(nullable: true), 
     Name = table.Column<string>(nullable: true) 
    }, 
    constraints: table => 
    { 
     table.PrimaryKey("PK_Tags", x => x.Id); 
     table.ForeignKey(
      name: "FK_Tags_Addresses_AddressId", 
      column: x => x.AddressId, 
      principalTable: "Addresses", 
      principalColumn: "Id", 
      onDelete: ReferentialAction.Restrict); 
    }); 

См AddressId колонки и FK для Addresses таблицы? Почему это? Из-за вашей Tags собственности:

public List<Tag> Tags { get { return ...; } } 

Это, вероятно, текущий EF Основной ошибка отображения только для чтения коллекции собственности, но чистый эффект, что он считает один ко многим отношений между Address и Tag, которые, конечно, не является вашим намерение.

В целом я бы рекомендовал сохранить модель сущности чистой и не включать такие свойства «помощника» - как для сбора, так и для ссылочного типа. Они выглядят как свойства навигации, но их нет, и их легко использовать по ошибке внутри запроса, что полностью изменит план выполнения и приведет к неожиданным исключениям или неправильным результатам (в случае, если базовое свойство не загружено). Не говоря о нарушении общего правила, чтобы не создавать свойство, возвращающее List, который не является членом класса, но создается при каждом вызове доступа к свойствам.

Вскоре просто удалите это свойство, и проблема исчезнет. Или, если вы настаиваете, держа его, а затем украсить его с аннотацией NotMapped данных:

[NotMapped] 
public List<Tag> Tags { get { return ...; } } 
+0

Вы совершенно правы. Я понял это по ошибке перед вашим сообщением, но все же, теперь я понимаю, почему это был AddressId, и я могу просто игнорировать отображение. благодаря –