InverseProperty с переносом базы данных не работает, если свойство защищено или является внутренним - PullRequest
1 голос
/ 26 марта 2012

У меня есть следующие модели сущностей

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; }
}

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

Когда я изменил модификатор доступа для свойства Users в Tag на publicон работал нормально, и генерация - это то, что мне нужно.

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

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

Ответы [ 2 ]

2 голосов
/ 26 марта 2012

Я не знаю, как заставить его работать с аннотациями данных, но с 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;
    }
}

Отображение в 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 голосов
/ 26 марта 2012

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

...