1

私のデータベースには2つのテーブルがあります:

id   | name |  city  | street
-------------------------------
   1 | John | London | Street1
   2 | Will | London | Street1
   3 | Adam | LA     | Street1

id   | uid | phone
------------------
   1 |    1| 12345
   2 |    1| 23456
   3 |    2| 16505
   4 |    3| 65909
   5 |    3| 68902
   6 |    3| 15905

そのデータを選択してリスト(またはユーザーIDが一意であるため辞書)に保存する必要があります

私の uses クラスは次のようになります。

public class User
{
    //lock
    private static readonly object userLock = new object();

    public int      Id        { get; set; }
    public string   Name      { get; set; }
    public string   City      { get; set; }
    public string   Street    { get; set; }

    public List<string> Phones { get; private set; }

    public User()
    {
        Phones = new List<string>();
    }

    public void AddPhone(string phone)
    {
        lock (userLock)
        {
            Phones.Add(phone);
        }
    }
}

アイデアは、これらのユーザー情報をアプリケーションにロードし、電話を追加/削除/変更し、変更/削除/追加されたものを保存することです。

ここで解決策のアイデアを見つけました: https://stackoverflow.com/a/11687743/965722、しかし、これは1つのクエリを実行してユーザーリストを取得し、ユーザーごとに個別のクエリを実行して電話を取得する必要があると想像しています。

ロードはどうすればいいですか?
1つのクエリだけでそれを行うことはできますか?
結果コレクションにデータを入力するにはどうすればよいですか?
リストまたは辞書を使用する必要がありますか? Id次に、 User クラスから削除して、辞書内のキーとして使用できます。

私は .NET 3.5 を使用していますが、Entity Framework または ORM を避けたいと考えています。

4

2 に答える 2

2

クラス Phone を作成し、それに応じて User プロパティを変更します。

public class Phone
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string Number { get; set; }
}

public class User
{
    // (etc)
    public List<Phone> Phones { get; set; }
    // (etc)        
}

PhoneRepository を作成します。

public class PhoneRepository
{
    public List<Phone> LoadPhonesFromId(IEnumerable<int> ids)
    {
       // write a query with the ids
       // SELECT * FROM Phones WHERE id IN (@id1, @id2, ...)
       // execute the query
       // convert the results to Phones and put them in a List<Phone>
       // return the list
    }
    public List<Phone> LoadPhonesFromUserId(IEnumerable<int> userIds)
    {
       // write a query with the userIds
       // SELECT * FROM Phones WHERE userId IN (@userId1, @userId2, ...)
       // execute the query
       // convert the results to Phones and put them in a List<Phone>
       // return the list
    }
}

そして UserRepository:

public class UserRepository
{
    public List<User> LoadUsersFromUserIds(IEnumerable<int> userIds)
    {
       // write a query with the userIds
       // SELECT * FROM User WHERE id IN (@id1, @id2, ...)
       // execute the query
       // convert the results to Users and put them in a List<User>
       // return the list
    }

    public void IncludePhones(IEnumerable<User> users)
    {            
        var phones = PhoneRepository.LoadPhonesFromUserId
            (users.Select(x => x.Id));

        for each(var user in users)
        {
            user.Phones = phones
                .Where(x => x.UserId == user.Id)
                .ToList();
        }
    }
}

たとえば、カスタム フィルター パラメーター (さまざまなフィルターのさまざまな関数の代わりに) や、ユーザーとユーザーの電話が同じユーザー ID を参照し続けることを確認するプロパティ セッターを使用して、このパターンを大幅に拡張および改善できますが、それは並べ替えです。あなたの質問の範囲を超えています。

于 2013-01-30T11:39:11.357 に答える
0

.net 4 にアップグレードできる場合は、ObjectContext.Translateを見てください。「実際の」エンティティ モデルなしでこれを使用できます。サブクラス化されていない空の objectcontext で十分であり、エンティティでなくてもオブジェクトをマップします。このソリューションにはサード パーティの依存関係はありませんが、利用可能なオープン ソース ライブラリよりも少し遅く、柔軟性に欠けます。

.net 4.0 がオプションではない場合、またはより多くの機能とパフォーマンスが必要な場合は、サードパーティのライブラリを確認することをお勧めします。

  • Dapperはプレーンな POCO を適切にアンラップし、パラメーター化された優れたクエリを備えています。また、非常に高速です。最新バージョンは .net 4.0 ですが、3.5 バージョンもあります。
  • PetaPoco別のシンプルな POCO アンラッパー、.net 3.5
  • ServiceStack.OrmLiteこれについてはよくわかりません。

各プロジェクトには、他のいくつかの競合他社もリストされています。それらの中から、簡単にパラメーター化されたクエリを使用してプレーン SQL を記述し、結果をプレーン オブジェクトに自動的にアンラップできる適切な選択肢を見つけることができると確信しています。パフォーマンスのオーバーヘッドは事実上ゼロです。したがって、このソリューションは(IMHO)生データリーダーよりも常に望ましいです。毎日の使用がとても簡単です。

于 2013-01-30T11:24:59.647 に答える