Подтвердить что ты не робот

EF 4.0 - сопоставление свойств readonly с частным полем

Можно ли сопоставить следующий класс POCO с EF 4.0?

public class MyClass
{
  private string _myData;

  public MyClass() 
  { }

  public MyClass(string myData)
  {
    _myData = myData;
  }

  public string MyData
  {
    get
    {
      return _myData;
    }
  }
}

В NHibernate я думаю, что это возможно, когда я использую атрибут Access при сопоставлении, например:

<class name="MyClass" table="MyTable">
  <property name="MyData" access="field.camelcase-underscore" column="MyCol" type="string" length="50" />
</class>

Интересно, есть ли эквивалент Access в EF 4.0? В настоящее время я могу отображать класс только в том случае, если я добавлю защищенный установщик в свойство MyData:

  public string MyData
  {
    get
    {
      return _myData;
    }
    protected set
    {
      _myData = value;
    }
  }

Это работает, но для устаревших классов это означает обновление всех свойств, у которых нет настроек.

Edit:

Я обновил последний пример кода, потому что он также не работает с частным установщиком. Сеттер должен быть, по крайней мере, защищен. Если сеттер является закрытым или не существует, следующее исключение:

System.InvalidOperationException: Информация о картировании и метаданных может не найдено для EntityType 'MyNamespace.MyClass'.

4b9b3361

Ответ 1

Я играл с этим немного, и мой вывод:

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

Ответ 2

Это для объектов Code First POCO, чтобы помочь Shimmy и другим интересоваться, как все это работает с Code First

Я думаю, что вы можете просто не понимать, как работает Entity Framework. Это заняло у меня некоторое время, чтобы схватить тоже.

Entity Framework работает путем подклассификации объектов POCO с помощью прокси-класса, который используется для сериализации и десериализации ваших объектов. Это означает, что если у вас есть метод или свойство частного набора (или он отсутствует вместе), метод подкласса не может установить свойство. Установки и свойства, которые вы хотите использовать инфраструктуру Entity, ДОЛЖНЫ быть либо защищенными, либо публичными.

Если вы хотите, чтобы ваши сложные свойства были загружены лениво, вы также должны сделать их виртуальными, поэтому Entity Framework также может проксировать их. Если вы хотите загрузить их, вы должны использовать метод Include.

Чтобы полностью ответить на ваш вопрос, да, вам нужно пойти и добавить свойства сеттера ко всем вашим свойствам, которые вы хотите установить для вас. Нет. Entity Framework не предоставляет вам способ сопоставления свойств, которые не имеют установщика.

NHibernate работает по-другому, поскольку он переопределяет все ваши свойства, и я считаю, что он использует частные переменные в подклассах, которые он создает, устанавливает частные переменные, а переопределенные свойства возвращают частные переменные. A.K.A., NHibernate не нуждается в настройщике самого свойства, тогда как Entity Framework фактически устанавливает свойство. Преимущество Entity Framework заключается в том, что он возвращает фактический объект POCO, который вы создали, а не подклассифицированный объект, такой как NHibernate. Единственный раз, когда вы получаете объект подкласса, - это когда вы используете ленивые загруженные сложные свойства, где Entity Framework возвращает подкласс-подкласс. Когда вы действительно извлекаете данные, прокси снова устанавливает свой класс POCO.

Ваш сеттер должен быть общедоступным или защищенным, как вы его в своем вопросе:

public class MyClass
{
    private string _myData;

    public MyClass() { }

    public MyClass(string myData)
    {
        // In case there is specialized logic, you should call the property setter here
        // unless the property is a virtual property. You should never call any virtual
        // methods or properties in your constructor.
        MyData = myData;
    }

    public string MyData
    {
        get
        {
            return _myData;
        }
        protected set
        {
            _myData = value;
        }
    }
}