Entity Framework 4 - сопоставление закрытых свойств с CTP5 (сначала код) в контексте, не знающем о персистентности

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

Есть ли другой способ?

Я нашел этот хороший блог сообщение, но мне не удалось заставить его работать. Вот модель:

public class Institute
{
    /**
        Code omitted
    **/

    protected virtual ICollection<InstituteText> InnerInstituteTexts { get; set; }

    private InstituteTextSet _TextSets;

    public InstituteTextSet Texts 
    {
        get 
        {
            if (_TextSets == null)
                _TextSets = new InstituteTextSet(InnerInstituteTexts);

            return _TextSets;
        }
    }
}

Код сопоставления:

var instituteTextExpression = ObjectAccessor<Institute>.CreateExpression<ICollection<InstituteText>>("InnerInstituteTexts");

institute.HasMany(instituteTextExpression)
    .WithRequired()
    .HasForeignKey(t => t.InstituteId);

где CreateExpression определяется как:

public static Expression<Func<T, TResult>> CreateExpression<TResult>(string propertyOrFieldName)
{
    ParameterExpression param = Expression.Parameter(typeof(T), "propertyOrFieldContainer");
    Expression body = Expression.PropertyOrField(param, propertyOrFieldName);
    LambdaExpression lambda = Expression.Lambda(typeof(Func<T, TResult>), body, param);

    return (Expression<Func<T, TResult>>) lambda;
}

я получаю ошибку:

Метод инициализации Studentum.Core.Tests.InstituteTests.Initialize вызвал исключение. System.TypeInitializationException: System.TypeInitializationException: инициализатор типа для Studentum.Core.FluentCoreRepositoryFactory выдал исключение. ---> System.InvalidOperationException: настроенное свойство «InnerInstituteTexts» не является объявленным свойством в сущности «Институт». Убедитесь, что оно не было явно исключено из модели и является допустимым примитивным свойством.


comment
Я знаю, что это не тот ответ, который вы ищете, но знаете ли вы, что NHibernate поддерживает этот сценарий из коробки и без хаков?   -  person Diego Mijelshon    schedule 09.03.2011
comment
Мы использовали NHibernate в тестовом проекте вместе с фреймворком Fluent mapping. Вы пробовали это? wiki.fluentnhibernate.org/Fluent_mapping_private_properties   -  person Kralizek    schedule 09.03.2011
comment
@Kralizek: Как уже говорилось, это поддерживается из коробки с отображениями XML. С Fluent, наверное, сложнее (я им не пользуюсь), но я не это предлагал.   -  person Diego Mijelshon    schedule 09.03.2011
comment
@DiegoMijelshon: извините! я неправильно понял ваш комментарий. Я думал, вы спрашивали, поддерживает ли NHibernate этот сценарий, а не предлагали его. В любом случае, мы отказались от NH из-за каких-то странных требований к классам (все должно быть виртуальным, нельзя использовать собственные коллекции и т. Д.). По сути, мы чувствовали, что NH заставили нас приспособить нашу модель к ее потребностям. Идея нам не понравилась, и, к счастью, у EF4 не такие требования. Мы вполне довольны классическим EF4, но EF4.1 даже лучше для плавных сопоставлений и для нового поверхностного API. Единственная проблема - это закрытые свойства.   -  person Kralizek    schedule 09.03.2011
comment
@Kralizek: по моему опыту, все наоборот: NH не вызывает ничего странного, кроме виртуальных свойств (которые также требуются EF, если вы хотите ленивую загрузку, BTW), и он очень расширяемый. EF чрезвычайно жесткий и не поддерживает самые простые вещи (например, перечисления). Но делайте то, что вам подходит :-)   -  person Diego Mijelshon    schedule 09.03.2011
comment
Мне удалось успешно сопоставить частные примитивные свойства в EF Code First, используя подход, аналогичный приведенному выше, но не пробовал свойство ассоциации. Одна из рекомендаций - посмотреть, можете ли вы сделать это в Entity Framework, ориентированном на модель (т.е. в EDMX). Если вы можете, то по крайней мере, вы будете знать, что то, что вы пытаетесь выполнить, на самом деле поддерживается EF и что ваши усилия найти способ сделать это в Code First не тщетны. Если он работает в EDMX, вы всегда можете экспортировать свою модель Code First в EDMX, чтобы продолжить работу с желаемой структурой.   -  person Dan Mork    schedule 19.06.2011
comment
Сопоставление частных свойств действительно поддерживается. Проблема заключается в отсутствии инструмента для сопоставления этих свойств с использованием CF и подхода построителя моделей.   -  person Kralizek    schedule 20.06.2011
comment
Ваше приложение может не иметь достаточного разрешения на отражение для доступа к непубличным участникам. Это веб-приложение?   -  person Akash Kava    schedule 15.09.2011
comment
это так, но мы уже много работаем над отражением. Разве у меня не должно быть исключения безопасности, если я этого не сделал?   -  person Kralizek    schedule 15.09.2011
comment
@Kralizek, нет, вы не получите исключения безопасности, вы уже получаете исключение, что член не (публично) определен, по умолчанию ASP.NET разрешает только отражение публичных членов, вы не можете получить доступ к внутренним, частным или защищенным членам , это не имеет ничего общего с Entity Framework. Тот же класс в той же сборке может получить доступ к непубличным членам, но DLL Entity Framework находится где-то еще, и он может не иметь доступа к непубличным членам вашей dll.   -  person Akash Kava    schedule 16.09.2011
comment
@Akash Kava: Исключения, которые вы получаете, размышляя о непубличных членах в ограниченном контексте, очень разные (см. MemberAccessException). Я считаю, что это другая ошибка, возможно, какой-то код (EF или другой) ищет членов только с BindingFlags.Public.   -  person Michael Petito    schedule 18.09.2011


Ответы (1)


Первое, что пришло в голову, это InternalsVisibleTo атрибут сборки. Это позволяет вам называть «дружественные» сборки, которые также имеют доступ к внутренним членам. Я не был уверен, будет ли это работать с EF CodeFirst, но я попробовал, и, похоже, он работает нормально. Вам придется немного изменить сборку модели, но я думаю, что это разумное изменение.

Сначала вам нужно изменить декларацию свойства на protected internal:

 protected internal virtual ICollection<InstituteText> InnerInstituteTexts { get; set; }

Затем в сборке модели добавьте атрибут сборки InternalsVisibleTo в файл AssemblyInfo.cs с именем сборки сопоставления.

[assembly: InternalsVisibleTo("MappingAssemblyName")]

Наконец, вы можете определить отображение свойства в сборке сопоставления, как любое другое общедоступное свойство.

institute.HasMany(i => i.InnerInstituteTexts)
    .WithRequired()
    .HasForeignKey(t => t.InstituteId);
person Michael Petito    schedule 16.09.2011
comment
Я читал об этом решении, но не нарушает ли это требование контекста постоянства, не осознающего, поскольку сборка, содержащая объекты, должна ссылаться на сборку, содержащую сопоставления. - person Kralizek; 19.09.2011
comment
Это имя вашей сборки сопоставления в атрибуте сборки. Однако он не ссылается на сборку (нет проблемы с циклической зависимостью), классы сопоставления, структуру сущностей или что-либо, специфичное для персистентности. Я бы сказал, что с практической точки зрения это все еще оставляет вашу модель в неведении. Если вы хотите получить очень технический уровень осведомленности, можно заявить, что в вашей модели уже представлены подробности о персистентности, потому что вы должны создать все сопоставленные свойства virtual. - person Michael Petito; 19.09.2011
comment
Это путь. Я немного разочарован тем, что функция, поддерживаемая в EF4, не поддерживается в Code-First. - person Kralizek; 20.09.2011