代码之家  ›  专栏  ›  技术社区  ›  Ladislav Mrnka

EF4.0-映射到带有私有字段的只读属性

  •  12
  • Ladislav Mrnka  · 技术社区  · 14 年前

    是否可以用EF4.0映射以下POCO类?

    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>
    

    我想知道在EF4.0中是否有一些访问等价物?目前,只有将受保护的setter添加到mydata属性时,我才能映射类:

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

    它可以工作,但对于遗留类,它意味着更新所有没有setter的属性。

    编辑:

    我更新了最后一个代码示例,因为它也不适用于私有setter。必须至少保护setter。如果setter是私有的或不存在,则引发以下异常:

    System.InvalidOperationException:无效操作异常: 映射和元数据信息可以 找不到EntityType “MyNamespace.MyClass”。

    2 回复  |  直到 12 年前
        1
  •  6
  •   Dan VanWinkle tvanfosson    12 年前

    这是针对代码优先的POCO对象的,用于帮助Shimmy和其他想知道如何首先处理代码的人。

    我认为您可能不理解实体框架是如何工作的。这也花了我一段时间来理解。

    实体框架通过使用代理类对POCO对象进行子类化来工作,代理类用于序列化和反序列化对象。这意味着,如果您有一个私有的set方法或属性(或者它全部丢失),则子类方法无法设置该属性。希望实体框架使用的setter和属性必须是受保护的或公共的。

    如果您希望延迟加载复杂的属性,那么还必须使这些属性成为虚拟的,这样实体框架也可以代理这些属性。如果您希望预先加载它们,则必须使用include方法。

    要完全回答您的问题,是的,您必须将setter属性添加到您希望Entity Framework为您设置的所有属性中。不,实体框架不提供映射没有setter的属性的方法。

    nhibernate的工作方式有点不同,它覆盖了所有的属性,我相信它在它生成的子类中使用私有变量,设置私有变量,然后被覆盖的属性返回私有变量。也就是说,nhibernate不需要在属性本身上设置setter,而实体框架实际上设置了属性。这样做对实体框架的好处是它返回您创建的实际POCO对象,而不是像nhibernate这样的子类对象。获得子类对象的唯一时间是使用延迟加载的复杂属性时,实体框架返回代理子类。当您实际检索数据时,代理会再次将自己设置为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;
            }
        }
    }
    
        2
  •  5
  •   Ladislav Mrnka    13 年前

    我玩过这个小游戏,我的结论是:

    • 我无法映射根本没有setter的遗留类型。
    • 我可以映射具有私有setter的类型,但我也必须在edmx中设置setter可访问性。仅仅在poco类中定义setter是不够的——edmx必须知道这一点。