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 是唯一的)

我的使用类如下所示:

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 ,但我想这是做一个查询来获取用户列表,然后对于每个用户我需要单独的查询来获取他的手机。

我应该如何加载?
我可以只用一个查询吗?
我应该如何填充我的结果集合?
我应该使用列表还是字典?然后我可以Id从 User 类中删除并将其作为字典中的键。

我正在使用 .NET 3.5 并希望避免使用实体框架或 ORM。

4

2 回答 2

2

创建一个电话类并相应地更改用户属性:

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)        
}

制作一个电话存储库:

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
    }
}

和一个用户存储库:

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();
        }
    }
}

您可以通过例如自定义过滤器参数(而不是各种过滤器的不同函数)和属性设置器来极大地扩展和改进此模式,以确保 user 和 user.Phones 始终引用相同的 userID,但这是排序超出了你的问题范围。

于 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,并将结果自动解包到普通对象中。性能开销几乎为零;所以这个解决方案(恕我直言)总是比原始数据阅读器更可取;在日常使用中要容易得多。

于 2013-01-30T11:24:59.647 回答