我正在用servicestack编写用户服务,当请求用户资源时,我想以各自的URL形式返回实体集合。资源是所请求用户的朋友。
我当前的用户实体
[RestService("/users")]
[RestService("/users/{Id}")]
[Alias("Users")]
public class User
{
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
public string CellPhoneNumber { get; set; }
public string EmailAddress { get; set; }
public DateTime CreatedDate { get; set; }
}
基本上,在我的SQLite数据库中,我会有一个名为“Friendships”的表来表达关系。该表应该像这样工作
ID PK INT NOT NULL
UserID1 FK INT NOT NULL
UserID2 FK INT NOT NULL
我需要一个“友谊”实体来表达这个吗?如何添加/更改我的用户实体以使ServiceStack将其与友谊集合一起返回?
我认为有可能成为像这样的友谊实体
[RestService("/users/{Id}/friends")]
[Alias("Friendships")]
public class Friendship
{
[AutoIncrement]
public int Id { get; set; }
public int UserId1 { get; set; }
public int UserId2 { get; set; }
}
在处理请求时,返回用户朋友的资源URL集合。我不知道如何继续前进,可以使用一些提示/建议。
产生的实施
我最终将我的Friendships表保留在数据库中,但没有实现FriendshipService类,而是使用类似于mythz建议的内容。
[RestService("/users/{Id}/friends")]
public class UserFriends
{
public int Id { get; set; }
}
正如你所看到的,我保留了mythz'UserFriends实体。我的服务类虽然符合我的需要但有所不同。他/她提出的解决方案没有解决的问题是所讨论的用户实体可以是UserId1或UserId2。这就是我的服务类解决问题的方法。
public class UserFriendsService : RestServiceBase<UserFriends>
{
public IDbConnectionFactory DbFactory { get; set; }
public override object OnGet(UserFriends request)
{
if (request.Id != default(int))
{
User user = DbFactory.Exec(dbCmd => dbCmd.GetById<User>(request.Id));
var friendIds = DbFactory
.Exec(dbCmd => dbCmd.Where<Friendship>("UserId1", request.Id).Select(fs => fs.UserId2))
.Union(DbFactory.Exec(dbCmd => dbCmd.Where<Friendship>("UserId2", request.Id)).Select(fs => fs.UserId1));
List<User> friends = DbFactory.Exec(dbCmd => dbCmd.GetByIds<User>(friendIds));
return friends;
}
else
{
return DbFactory.Exec(dbCmd => dbCmd.Select<User>());
}
}
}
我可以通过使用所选的ID并在初始查询中使用dbCmd.GetById<User>()
来选择用户实体而不是朋友ID,但我认为这会使代码更复杂且难以阅读。< / p>
答案 0 :(得分:1)
您应该尝试从外部API隐藏服务的实现细节。在这种情况下,我会为每个朋友返回一个用户DTO列表,例如:
[RestService("/users/{Id}/friends")]
public class UserFriends {
public Id { get; set; }
}
public class UserFriendsService : ServiceBase<UserFriends> {
public IDbConnectionFactory DbFactory { get; set; }
public object Run(UserFriends request) {
return DbFactory.Exec(dbCmd => dbCmd.Select<User>(
@"SELECT u.* FROM Users u INNER JOIN Friendships f ON (u.Id = f.UserId2)
WHERE f.UserId1 = {0}", request.Id));
}
}
注意:并非适合所有人,但我的首选是将所有ServiceStack响应包装在Typed Response DTO中。这为客户端提供了一致的约定/类型API(即,他们可以预测每个服务的响应),并包括对typed Validation的支持。
public class UserFriendsResponse {
public List<User> Results { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}