【问题标题】:How to prevent private properties in .NET entities from being exposed as public via services?如何防止 .NET 实体中的私有属性通过服务公开?
【发布时间】:2009-02-12 22:07:05
【问题描述】:

我正在创建一个 WCF 服务,用于传输通过实体框架创建的实体对象。我有一个映射到用户数据库表的用户实体。我不想向客户端公开某些用户字段(密码、DateCreated 等),但由于它们在数据库中不可为空,因此 Visual Studio 需要映射。将这些属性设置为私有似乎是一个很好的解决方法,但这些属性在被客户端使用时会转换为公共。

有没有办法解决这个问题,或者采取更好的方法?我宁愿避免在数据库级别更改这些字段只是为了让 EF 满意。

【问题讨论】:

    标签: wcf entity-framework


    【解决方案1】:

    这听起来像是隔离应用程序层的绝佳机会。您应该做的是创建特定于 WCF 层的对象,这些对象仅充当外部消费者的数据传输对象 (DTO)。

    因此,在您的 WCF 服务层中,您将对检索用户对象的数据访问层(实体框架)进行调用,并且您应该返回仅使用您想要公开的内容构建的消费者对象。

    如果您这样做,您可以明确控制您对外界可见的内容,还可以从数据存储的角度隐藏有关您正在执行的操作的任何实现细节。

    作为一个非常粗略的例子,在你的实体框架层你可能有这个对象:

    namespace ACME.DataAccessLayer.Entities
    {
        public class User
        {
            public int Id { get; set; }
    
            public string UserName { get; set; }
    
            public string Password { get; set; }
    
            public string Hash { get; set; }
    
            public string FirstName { get; set; }
    
            public string LastName { get; set; }
        }
    }
    
    namespace ACME.DataAccessLayer.Services
    {
        using ACME.DataAccessLayer.Entities;
    
        public class UserService
        {
            public User GetUser(int id)
            {
                using (ACMEDataContext dc = new ACMEDataContext())
                {
                    // psuedo code to return your user with Entity Framework
                    return dc.Users.FirstOrDefault(user => user.Id == id);
                }
            }
        }
    }
    

    然后在您的 WCF 中,您可能会有如下实体:

    namespace ACME.Services.DataTransferObjects
    {
        [DataContract]
        public class User
        {
            [DataMember]
            public int Id { get; set; }
    
            [DataMember]
            public string FirstName { get; set; }
    
            [DataMember]
            public string LastName { get; set; }
        }
    }
    
    Then you would expose a service endpoint that would return back the DTO as such:
    
    namespace ACME.Services
    {
        using ACME.DataAccessLayer.Services;
    
        public class PublicWCFService : IUserService
        {
            public ACME.Services.DataTransferObjects.User GetUser(int userId)
            {
                ACME.DataAccessLayer.Entities.User entityFrameowrkUser = new UserService().GetUser(userId);
    
                return new ACME.Services.DataTransferObjects.User
                           {
                               Id = entityFrameowrkUser.Id,
                               FirstName = entityFrameowrkUser.FirstName,
                               LastName = entityFrameowrkUser.LastName
                           };
            }
        }
    }
    

    现在您要做的只是返回 DTO 对象,该对象不具有您在系统中使用的真实实体中可能拥有的任何属性或方法。

    使用这种方法,您可以安全地将应用程序的层分解为可以轻松共享和扩展的不同层 (DLL)。

    这是一个简单的示例,如果有任何进一步的内容可以使这个示例更加清晰,请告诉我。

    【讨论】:

      【解决方案2】:

      您总是可以在实体对象上实现IXmlSerializable。然后,您将能够指定发送给客户端的内容的结构(显然,客户端会得到不同的表示)。

      或者,如果可以的话,将DataContract attribute 添加到类型中,并将DataMember attribute 添加到您希望通过网络发送的属性。

      【讨论】:

      • 这是最简单的,我相信是完全正确的答案。
      • 非常简单直观...我会试一试。谢谢!
      猜你喜欢
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-22
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多