Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

.net - EF 4.0 - mapping to readonly property with private field

Is it possible to map following POCO class with EF 4.0?

public class MyClass
{
  private string _myData;

  public MyClass() 
  { }

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

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

In NHibernate I think it is possible when I use Access attribute in mapping like:

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

I wonder if there is some Access equivalent in EF 4.0? Currently I'm able to map the class only if I add protected setter to the MyData property:

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

It works but for legacy classes it means update all properties which don't have setter.

Edit:

I have updated the last code example because it also doesn't work with private setter. Setter has to be at least protected. If the setter is private or doesn't exists following exception is thrown:

System.InvalidOperationException: Mapping and metadata information could not be found for EntityType 'MyNamespace.MyClass'.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is for Code First POCO objects, to help out Shimmy and others wondering how all this works with Code First

I think that you may just not be understanding how Entity Framework works. This took me a while to grasp too.

Entity Framework works by Subclassing your POCO objects with a proxy class, which is used to serialize and deserialize your objects. This means that if you have a private set method or property (or it is missing all together), there is no way for the subclassed method to set the property. The setters and the properties that you want Entity framework to use MUST be either protected or public.

If you want your complex properties to be loaded lazily, you must also make those virtual, so Entity Framework can proxy those as well. If you want to eager load them, you must use the Include method.

To fully answer your question, yes, you have to go and add the setter properties to all of your properties that you want Entity Framework to set for you. No, Entity Framework does not provide a way for you to map properties that don't have a setter.

NHibernate works a bit differently in that it overrides all of your properties and I believe that it uses private variables in the subclasses it generates, sets the private variables, and the overridden properties then return the private variables. A.K.A., NHibernate doesn't need a setter on the property itself, whereas Entity Framework actually sets the property. The benefit to Entity Framework doing this is that it returns the actual POCO object that you created, not the subclassed object like NHibernate. The only time that you get a subclassed object is when you are using lazy loaded complex properties, where Entity Framework returns the proxy subclass. When you actually retrieve the data, the proxy sets itself to your POCO class again.

Your setter should be public or protected, like you have it in your question:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...