1

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データベースには、関係を表す「友情」というテーブルがあります。テーブルはこのようにうまく機能するはずです

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の代わりにユーザーエンティティを選択することもできますが、それではコードがより複雑になり、読みにくくなると思います。

4

1 に答える 1

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応答を型付き応答DTOでラップすることです。これにより、クライアントに一貫した規則/型付​​きAPIが提供され(つまり、クライアントは各サービスの応答を予測できます)、型付き検証のサポートが含まれます。

public class UserFriendsResponse {
    public List<User> Results { get; set; }
    public ResponseStatus ResponseStatus { get; set; }
}
于 2012-07-15T19:15:24.693 に答える