SQL查询结果列表<t>映射</t>

时间:2013-01-30 11:08:43

标签: c# visual-studio-2008 .net-3.5

在我的数据库中,我有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

我需要选择该数据并存储到List(或用户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,但我想这是做一个查询来获取用户列表,然后对于每个用户我需要单独的查询来获取他的手机。

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

我正在使用.NET 3.5,并希望避免使用Entity Framework或ORM。

2 个答案:

答案 0 :(得分: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();
        }
    }
}

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

答案 1 :(得分:0)

如果你可以升级到.net 4,那么看看ObjectContext.Translate - 你可以在没有“真实”实体模型的情况下使用它,一个空的unsubclassed objectcontext就足够了,即使它们不是实体。此解决方案没有第三方依赖项,但它比可用的开源库慢一点且不太灵活。

如果.net 4.0不是一个选项,或者您想要更多功能和性能,您可能需要查看第三方库:

  • Dapper很好地展开普通POCO并具有良好的参数化查询。也很快。最新版本是.net 4.0,但也有3.5版本。
  • PetaPoco另一个简单的POCO解包器,.net 3.5
  • ServiceStack.OrmLite我对此不太了解。

每个项目还列出了一些其他竞争对手;我相信你可以在它们中找到一个合适的选择,它允许你用简单的参数化查询编写普通的sql,并将结果自动解包到普通对象中。性能开销几乎为零;所以这个解决方案(IMHO)总是优于原始数据读取器;它在日常使用中更容易。