如何防止.NET实体中的私有属性通过服务公开为公共属性?

时间:2009-02-12 22:07:05

标签: wcf entity-framework

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

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

2 个答案:

答案 0 :(得分:3)

这听起来很好地隔离了应用程序的各个层次。您应该做的是创建特定于WCF层的对象,这些对象仅作为外部消费者的数据传输对象(DTO)。

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

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

作为一个非常粗糙的示例,您可以在Entity Framework层中拥有此对象:

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),这些层可以轻松共享和扩展。

这是一个简单的例子,所以请告诉我是否有更进一步的内容可以使这个例子更加清晰。

答案 1 :(得分:2)

您始终可以在实体对象上实现IXmlSerializable。然后,您将能够指示发送给客户端的结构(显然,客户端将获得不同的表示)。

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