在Web API中使用实体的部分和投影

时间:2013-04-18 19:29:04

标签: entity-framework breeze

我正在使用带有Web API的breeze。我没有很好地掌握如何“过滤列”或如何不将公开表和整个表暴露给我的Web API。我使用实体框架作为我的来源,John Papa在这里解决了我的两个问题:http://www.johnpapa.net/spajs04/#comment-113761并且确认是Ward Bell的一个很好的解决方案。有人可以告诉我如何使用实体框架创建一个可在我的webapi中查询的部分或投影,并且可以使用breeze吗?

这是我在webapi中的当前功能

[HttpGet]
public IQueryable<Contact> GetContacts()
{
    return _contextProvider.Context.Contact;
}

这是我目前的课程:

public class Contact
{
    [Key]
    public Guid ID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string NickName { get; set; }
    public string JobTitle { get; set; }
    public DateTime BirthDate { get; set; }
    public bool Gender { get; set; }
    public string SSN { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateUpdated { get; set; }

    public virtual ICollection<Address> Address { get; set; }
}

我希望有一个可查询的webapi函数,它是我当前的类 WITHOUT SSN字段。一个“数据库优先”实体的解决方案,不涉及更改我的数据库或添加“视图”将是伟大的。

5 个答案:

答案 0 :(得分:6)

当您尝试减少有效负载时,客户端投影很好。当您必须确保某些数据(例如SSN)真正安全地从客户端隐藏时,您需要服务器端。

@james建议 - 使用[NonSerialized](或JSON.NET[JsonIgnore]属性) - 当SSN 从不时,这是一种简单有效的方法去客户端。

如果在授权的情况下客户端可以看到SSN(例如,用户查看自己的SSN或有权查看SSN的人权),则太不灵活了。 JSON.NET IContractResolver为您提供了极大的灵活性,可以根据授权规则动态决定哪些属性可以跨越服务边界。

有些人可能会考虑使用序列化程序解决这个问题太多了。他们可能会对您展示的服务器端投影表示满意,@ chris_dotnet。顺便说一下,从投影中返回IQueryable仍然有意义,这样客户端就可以通过过滤查询来减少网络负载。

其他人更愿意定义DTO(ContactDTO)并通过网络序列化。

[HttpGet]
    public IQueryable GetContacts()
    {
      return _contextProvider.Context.Contacts
        .Select(p =>
            new ContactDto
            {
                FirstName = p.FirstName,
                ID = p.ID,
                LastName = p.LastName
            });
    }

IQueryable比投影版本更强大,因为过滤可以在数据层而不是服务器层上进行。

在客户端,您可以定义ContactDto类型的元数据,也可以使用JsonResultsAdapterContactDto数据映射到Contact Breeze实体。

使用JsonResultsAdapter预先假定您确实需要Contact类型 - 在服务器上的业务模型中形成的类型 - 在客户端上已知。

您可能不希望从服务中公开服务器端Contact形状。许多人对此非常强烈。如果您是其中一个人,那么最好定义一个代表实体的“DTO模型”,以便在客户端上看到它们。这意味着学习为DTO模型创建元数据,并在服务器上编写映射逻辑,以便在DTO和业务模型之间移动。

您可以看到所有这些都可以成为一个大话题。这是我将在Breeze文档中尽快讨论的内容。考虑这个答案,尝试一下即将发生的事情。外卖是......你可以选择隐藏用户不应该看到的数据。

答案 1 :(得分:2)

感谢John提供此信息,我看了一下,这对客户端过滤很有帮助。我发现我可以从客户端和/或服务器端执行此操作。

客户端微风:

var query = EntityQuery.from("Customers")
.select("ID, FirstName, LastName");

服务器端:

    [HttpGet]
    public IQueryable<Contact> GetContacts()
    {
        var contactList = _contextProvider.Context.Contacts
        .ToList()
        .Select(p =>
            new Contact
            {
                FirstName = p.FirstName,
                ID = p.ID,
                LastName = p.LastName
            })
        .AsQueryable(); // actually IQueryable is not useful after "ToList()"

        return contactList ;
    }

答案 2 :(得分:1)

克里斯 - 在演讲中有一个例子,演讲者和会话部分。我返回那些我没有返回描述字段(用于会话)或生物字段(用于发言者)的投影。检查出来并使用相同的样式不显示您的Employee类的SSN字段

答案 3 :(得分:1)

您无法将属性标记为[NonSerialized]

[NonSerialized] 
 public string SSN { get; set; }

答案 4 :(得分:1)

我刚刚找到了另一种根据标准忽略列的解决方案。只需添加属于感兴趣模型的部分类(我的模型生成)并使用ShouldSerialize%PropertyName%

namespace ProvSys.Models
{
    partial class tblEmployees
    {
        public static bool ShouldSerializeResetPassword()
        {
            // Only hand over ResetPassword Field for admin role
            return (ProvSysRepository.IsAdmin);
        }
    }
}

在此示例中,ResetPassword表的tblEmployees属性仅在用户处于管理员角色时才会传输。