【问题标题】:poco object Accessibilitypoco 对象可访问性
【发布时间】:2011-08-25 23:54:59
【问题描述】:

我正在使用我用实体框架编写的 poco 对象。
我想了解用作数据字段的成员的可访问性级别(从数据库映射到表中字段的成员:
对于名为 P 的实体:

public class P {
    public virtual long Id{get;set;}
    public virtual string Name{get;set;}
    public virtual long CompanyId{get;set;}
    public virtual Company Company{get;set;}
}

成员必须是公开的吗?
成员必须是虚拟的吗?
成员可以是私有的吗?

会员可访问性的规则是什么?

【问题讨论】:

    标签: c# .net entity-framework accessibility


    【解决方案1】:

    取决于您使用的通信技术。使用 WCF(使用DataContractSerializer)时,您可以将可访问性设置为您喜欢的任何内容,并将[DataMember] 属性放在任何私有、受保护或公共字段或属性之上。这些将在传输 poco 时被序列化。如果您使用XmlSerializer,则只有公共属性会被序列化,您可以排除带有[XmlIgnore] 属性的属性。

    关于virtual:virtual 与可访问性无关,而更多地与OOP 相关,它为派生类提供了覆盖声明的属性/方法的可能性。这取决于您需要/喜欢的设计。

    因此,首先考虑您的类所需的字段/属性的可访问性以及要使用的序列化技术。

    【讨论】:

    • 对不起,我没有提到这个问题是关于实体框架而不是关于 wcf 服务的。
    【解决方案2】:

    如果您想将 POCO 对象与 Entity Framework 一起使用以便自动跟踪它们,则必须满足许多要求,这些要求在 here 中列出。

    特别针对您的问题,如果您希望您的类支持延迟加载,则必须将属性声明为 publicvirtual(因为 EF 将从您的类派生一个代理类并覆盖属性以提供功能。 )

    【讨论】:

    • 否,因为外部类也需要访问属性。
    • “课外”是什么意思?
    【解决方案3】:

    public 访问修饰符将类型和类型的成员标记为可从外部库访问。这意味着如果您在程序集 A 中有一个类型,并且您从程序集 B 添加了对它的引用,这意味着您可以从程序集 B 中公开的类型中访问该类型/成员。还有其他访问修饰符(阅读它们@987654321 @)。

    了解访问修饰符如何改变类型的行为是面向对象设计的重要组成部分。

    virtual 成员允许类型提供特定功能的默认实现。例如,如果我有一个类型:

    public class Logger {
        protected virtual void Write(string message) {
            Console.Write(message);
        }
    }
    

    我可以有一个类型:

    public class DebugLogger : Logger {
    
    }
    

    该类型会将Write 的默认实现公开为方法Logger.Write。我可以(可选)覆盖此行为:

    public class DebugLogger : Logger {
        protected override void Write(string message) {
            Debug.Print(message);
        }
    }
    

    使用virtual/override 的这种用法允许类选择性地自定义它们的行为,并且当使用对Logger 实例的简单引用调用Write 时,将调用正确的实现(因此,在后一种情况下被覆盖的方法)。

    private 成员用于包含不应暴露在父类型之外的成员。例如。属性的支持字段几乎总是私有的。

    我遵循的一般规则是:

    1. public 成员公开了我希望可从外部类型/程序集使用的特定功能。
    2. protected 成员公开了我希望仅从继承类型中可用的特定功能。
    3. private 成员将我想要包含的功能隐藏到父类型中。例如。我想要使​​用一种特定于该类型并且没有任何好处被公开的方法。例如。我想从外部访问等控制的状态突变方法。

    其他:

    1. internal 允许我将成员标记为仅在包含它们的程序集中可访问。当您需要公开特定于包含程序集的构建器方法等内容时,这很有用,您不想将其标记为公共但不能用作私有成员。
    2. 我很少用protected internal

    希望有帮助!

    【讨论】:

    • 对不起,我没有提到这个问题是关于实体框架而不是关于 wcf 服务的
    【解决方案4】:

    这很大程度上取决于您使用的方法。

    模型/数据库优先:

    • Members don't have to be public 但它有一些后果。 POCO 属性 getter 和 setter 必须具有与 EDMX 中定义的相同的可访问性(显示在链接的答案中)。如@dlev 提供的链接中所述,更改可访问性很可能会破坏跟踪代理、延迟加载或两者。
    • 成员不必是virtual。如果你想要延迟加载,你必须标记所有映射的导航属性virtual。如果您想要跟踪代理,您必须标记所有其他属性virtual

    代码优先(仅 EFv4.1):

    • 在这种情况下情况更糟。成员必须是public。在特殊情况下,当实体与上下文或映射配置成员位于同一程序集中时,可以是internal(我跳过InternalsVisibleTo,因为它不是很好的场景)。如果映射配置是实体的嵌套类,成员也可以是privateprotected,但这强烈破坏了 POCO 的整体含义,因为 POCO 实体必须包含 EF 依赖的嵌套类。关键是映射是在代码中完成的,它受可访问性规则的影响。
    • virtual 关键字与模型和数据库优先方法中的含义相同。

    virtual 关键字是必需的,因为 EF 将在运行时创建从实体类型派生的新类型。这种类型称为代理,它会覆盖属性 getter 和 setter 中的行为。在延迟加载的情况下,它会添加对Load 操作的调用,这会在第一次访问时触发关系加载。在更改跟踪代理的情况下,它会通知 ObjectStateManager / DbChangeTracker 对附加实体的每次更改。如果不使用跟踪代理,EF 必须使用快照跟踪,它会在保存期间评估对附加实体的所有更改,这被认为是较慢的操作。

    【讨论】:

      猜你喜欢
      • 2011-05-07
      • 2011-09-11
      • 1970-01-01
      • 2021-03-05
      • 2018-12-18
      • 2017-06-16
      • 1970-01-01
      • 2022-01-22
      • 2011-02-25
      相关资源
      最近更新 更多