1

У меня есть следующие модели EntityInverseProperty с миграцией базы данных не работает, когда собственность находится под защитой или внутренняя

public class User 
{ 
     public virtual long Id{get; set;} 
     [InverseProperty("Users")] 
     public virtual ICollection<Tag> Tags { get; protected set; } 
} 

public class Tag 
{ 
     public virtual long Id{get; set;} 
     internal protected virtual ICollection<User> Users { get; set; } 
} 

Это чистое простые много-ко-многому пользователю & Tag Я использую Миграции данных , Когда я выполняю команду Add-Migration или Update-Database , я получаю следующую ошибку: «InversePropertyAttribute в свойстве« Теги »в типе« Kigg.DomainObjects.Entities.User »недопустим. Свойство« Пользователи »недействительно свойства навигации для связанного типа «Kigg.DomainObjects.Entities.Tag». Убедитесь, что свойство существует и является допустимым средством навигации ссылки или коллекции. "

Когда я изменил модификатор доступа свойства «Пользователь» в теге на общедоступный, он отлично работал, и поколение - это то, что я хочу.

С моей точки зрения дизайна Я хочу скрыть свойство Tag.Users и сделать его защищенным или внутренним, чтобы сохранить его для внутреннего использования, поскольку я не хочу публиковать его в общедоступном API.

Примечание: Я не обсуждаю здесь свой проект. Я спрашиваю, возможно ли это сделать, если Tag.Users защищен или внутренне?

+0

Должна быть возможность нацеливать непубличные объекты на аннотации данных с EF 4.3, но я думаю, что эта функция как-то не работает. До EF 4.3 это было невозможно. –

+0

@LadislavMrnka Да это возможно. Проблема связана с миграцией базы данных. Запуск Update-Database или Add-Migration приводит к вышеуказанной ошибке, упомянутой в моем вопросе –

+0

Я достиг того, что хотел сделать, используя Fluent API с миграцией данных. Но все же любопытно узнать, можно ли использовать Data Annotation. –

ответ

0

Я мало знаю об EF5, но вы можете использовать атрибут InternalsVisibleToAttribute, чтобы внутренние элементы были видимыми для конкретной сборки.

2

Я не знаю, как заставить его работать с аннотациями данных, но с Fluent API можно применить и экспериментировать с трюком здесь: http://blog.cincura.net/232731-mapping-private-protected-properties-in-entity-framework-4-x-code-first/

Для модели это будет выглядеть следующим образом:

public class User 
{ 
    public virtual long Id{get; set;} 
    public virtual ICollection<Tag> Tags { get; protected set; } 
} 

public class Tag 
{ 
    public virtual long Id{get; set;} 
    internal protected virtual ICollection<User> Users { get; set; } 

    public class PropertyAccessors 
    { 
     public static readonly Expression<Func<Tag, ICollection<User>>> Users 
      = t => t.Users; 
    } 
} 

Mapping в FluentAPI:

modelBuilder.Entity<User>() 
    .HasMany(u => u.Tags) 
    .WithMany(Tag.PropertyAccessors.Users); 

Это работает и создает ожидаемый многие-ко-многим.

Но я не уверен, что вы можете сделать что-нибудь полезное с этим навигационным свойством. Тот факт, что у вас есть свойство protected и virtual, позволяет мне предположить, что вы в основном хотите поддерживать ленивую загрузку внутри класса сущности или производных классов.

Проблема в том, что, по-видимому (по моим испытаниям), ленивая загрузка не работает ни для чего другого, кроме public. Загруженный тег является прокси-сервером, но навигационная коллекция всегда null (если это свойство не является public).

Более того, даже охотно и явная загрузка не работает:

Вне из Tag класса:

// Eager loading 
var tag = context.Tags.Include(Tag.PropertyAccessors.Users).First(); 

// Explicit loading 
var tag2 = context.Tags.First(); 
context.Entry(tag2).Collection(Tag.PropertyAccessors.Users).Load(); 

Или внутри Tag класса (какой-то метод в Tag который получает контекст передается) :

public DoSomething(MyContext context) 
{ 
    // Eager loading 
    var tag = context.Tags.Include(t => t.Users).First(); 

    // Explicit loading 
    context.Entry(this).Collection(t => t.Users).Load(); 
} 

Во всех случаях я получаю исключение, что свойство Users на сущности Tag не является допустимым навигационным устройством.(Исключение исчезает, как только я делаю свойство public.)

Я не знаю, будут ли выполняться добавления/удаления/обновления. (Сомневаюсь.)

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

+0

Я хочу найти решение, используя DataAnnotation. Я еще не пробовал Data Migrations с Fluent API и не уверен, что он сработает. –

+0

Код Первый никогда не сопоставляет личные или внутренние члены по умолчанию. Вы должны использовать свободный API для их отображения, как показал @Slauma. Вы не можете сделать это с аннотациями данных. Однако, как только вы сопоставляете свойство с использованием свободного API, тогда будет соблюдаться любая аннотация данных по этому свойству. Так, например, если вы добавили атрибут MaxLength в частную собственность, он все равно не будет включен в модель. Но если вы также использовали свободный API для сопоставления свойства, тогда атрибут MaxLength будет считан и использован. –

+0

Используя Fluent API, вы можете сопоставить внутренние свойства в Code First. Я пробовал это, и он работает целую вечность. Для защищенных членов вам нужно сделать то, что @Slauma указано выше. –