从DataContext.ExecuteQuery <customobject>()检索关系表为IEnumberable

时间:2016-03-01 22:27:20

标签: c# sql .net sql-server linq

首先阅读:这是一个应用程序的一部分,它不控制它正在访问的数据库,因此实体框架是不可能的。这是一个非基于Web的工具,它将现有数据提取到内存中,但数据库已经制作完成,不受我们控制。

我有一个类,表示我想从多个表中检索的数据分组(ClassA)

public class ClassA
{
   public int ID;
   public string Detail;
   public List<string> Objects
}

表格如下所示:

表1

THISID(int)  | SOMETHING1(nvarchar)| SOMETHING2(nvarchar) | OTHERID(int)
1            | foo1                | bar1                 | 99
2            | foo2                | bar2                 | 98

表2

TABLE2ID(int) | OTHERID(int) | SOMETHING3(nvarchar)
100           | 99           | somethingA
101           | 99           | somethingB
102           | 99           | somethingC
103           | 98           | somethingA
104           | 98           | something D

我正在使用像这样的datacontext

string connectionString = (user passed in connection string)
string query = @"SELECT t1.THISID AS ID, t1.SOMETHING1 AS Detail, t2.SOMETHING3 AS Objects
                 FROM Table1 AS t1
                 JOIN Table2 AS t2
                 ON t1.OTHERID = t2.OTHERID";
using(DataContext dc = new DataContext(connectionString))
{
   List<ClassA> aClasses = dc.ExecuteQuery<ClassA>(query);
}

这显然不起作用,但我不确定是否有办法让DataContext或LINQtoSQL处理从查询返回的外来值,如列表(或集合或可枚举)。我知道当你像普通的ORM一样使用它时,Entity Framework会为你做这个,但是我们在这里将结果集映射到一个对象中,我不确定是否有一种机制可以将连接的数据视为一个列表在生成的映射对象中。

有关如何在一次数据库中执行此操作的任何想法? 或者是否有必要从Table1获取第一部分并实例化对象,然后迭代它们并填充其列表并再次访问Table2?

1 个答案:

答案 0 :(得分:1)

我很想使用Entity Framework。我知道你明确表示你不可能,但听起来你的理由只是你不能控制数据库,这意味着你不能先使用代码。但无论如何,它并不重要。

你可以在一次数据库之旅中完成它,但它(当然)需要撤回更多的数据。

无论如何,您必须添加一个班级。

class FlatRow
{
    public int Id { get; set; }
    public string Something1 { get; set; }
    public string Something3 { get; set; }
}
string connectionString = (user passed in connection string)
string query = @"SELECT t1.THISID AS ID, t1.SOMETHING1 AS Detail, t2.SOMETHING3 AS Objects
                 FROM Table1 AS t1
                 JOIN Table2 AS t2
                 ON t1.OTHERID = t2.OTHERID";
using(DataContext dc = new DataContext(connectionString))
{
    List<FlatRow> flat = dc.ExecuteQuery<FlatRow>(query);

    var aClasses = flat
                       .GroupBy(c => new { c.Id, c.Something1 })
                       .Select(c => new ClassA
                                    {
                                        ID = c.Key.Id,
                                        Detail = c.Key.Something1,
                                        Objects = c.Select(x => x.Something3).ToList()
                                    })
                       .ToList();
}

基本上,将其拉平,然后将其分组到内存中。这就是EF会做的,它会为你做的。但这并不是那么糟糕,如果它是你需要的。

尽管如此,我还是试图对每张桌子进行性能测试,然后将它们合并到内存中。您将切换为使用GroupJoin,并且您需要一个额外逻辑点,但是您不会为所有实体提取所有Something1数据多个Something3 s。