LINQ连接方法的正确返回值是多少?

时间:2012-08-27 20:47:25

标签: c# .net linq-to-sql 3-tier

我正在开发一个3层应用程序。我也在使用LINQ to SQL进行数据访问。

DataLayer有一个返回客户表的函数:

public Table<Customer> getCustomers()
{
    DataContext context = new DataContext();
    Table<Customer> customerTable = context.GetTable<Customer>();

    return customerTable;
}

将其提供给业务层,其中结果将作为IEnumerable<Customer>传递给表示层:

public IEnumerable<Customer> getCustomers()
{
    CustomerDAL customerDAL = new CustomerDAL();

    return from c in customerDAL.getCustomers() select c;            
}

在Presentation-Layer中,我只是将IEnumerable用于DatagridView的DataSource。

如果我有另一个表格如“信息”和相应的customerDAL.getInfo()表怎么办?现在我想在Business-Layer中的方法中进行连接查询。我想象它是这样的:

public IEnumerable<Customer> getCustomerInfo()
{
    CustomerDAL customerDAL = new CustomerDAL ();

    return from c in customerDAL.getCustomers()
                  join i in customerDAL.getInfo() on c.id equals i.InfoID
                  select new { c.id, c.Name, i.DateTime, i.Project };
}

问题是IEnumerable需要对象的类型。我的返回值不再是客户表,而是客户表和信息表的组合。我做对了吗?这里返回值的正确选择是什么?

根据您的建议,我创建了一个自定义类CustomerInfo.cs

public class CustomerInfo
    {        
        string name { get; set; }
        long id { get; set; }
        string dateTime { get; set; }
        string project { get; set; }


        public CustomerInfo(long _id, string _name, string _date, string _project) 
        {
            name = _name;
            id = _id;
            dateTime = _date;
            project = _project;
        }
    }

然后我调用与Reed描述的完全相同的方法。但是在Presentation-Layer中,当我设置DataSource时,我得到了异常:

The query contains references to items defined on a different data context.

实际上并非所有Entity类都在同一个.dbml文件中。可能有什么不对?

4 个答案:

答案 0 :(得分:1)

  

这里返回值的正确选择是什么?

如果要返回强类型类,则需要一个自定义类来表示此类型,例如CustomerInfo类。您需要定义此类,并包含适当的属性和构造函数。然后你可以这样做:

public IEnumerable<CustomerInfo> GetCustomerInfo()
{
        CustomerDAL customerDAL = new CustomerDAL();

        return from c in customerDAL.getCustomers()
                    join i in customerDAL.getInfo() on c.id equals i.InfoID
                    select new CustomerInfo(c.id, c.Name, i.DateTime, i.Project);
}

这将允许您以强类型的方式返回所需的确切信息。我认为在这种情况下创建自定义类尤为重要,因为您已将其定义为公共API的一部分。

答案 1 :(得分:1)

关于第二个错误:

然后我调用与Reed描述的完全相同的方法。但是在Presentation-Layer中,当我设置DataSource时,我得到了异常: 该查询包含对在不同数据上下文中定义的项的引用。

您的DAL很可能是为您要返回的每个表实例化一个单独的上下文实例(在ActiveRecord模式实现中是典型的)。为了使联接起作用,两个表都需要由相同的上下文对象检索。您可能希望修改DAL,以便在DAL的构造函数中注入上下文,以便集中处理上下文的生命周期。

答案 2 :(得分:0)

到目前为止一切看起来都不错。如果您只想在单个方法的范围内使用查询,那么使用匿名类(这是您当前正在进行的操作)就可以了。既然你不是,你需要为你的投影创建一个具体的类,以便你可以返回它。

查询将变为:

select new SomeClassYouAreAboutToCreate { c.id, c.Name, i.DateTime, i.Project };

该类可能只有一堆属性,idName等。您只需在Select中设置这些属性。

答案 3 :(得分:0)

当您创建类似的匿名对象时,其类型为dynamic。因此,要返回这样的匿名对象列表,您将使用以下签名:

public IEnumerable<dynamic> getCustomerInfo() {
    CustomerDAL customerDAL = new CustomerDAL ();

    return from c in customerDAL.getCustomers()
        join i in customerDAL.getInfo() on c.id equals i.InfoID
        select new { c.id, c.Name, i.DateTime, i.Project };
}

但请记住,dynamic类型有其缺点。特别是,您失去了强类型,这可能会引入难以发现的错误。您应该考虑使用Servy's answer来获得更强大的解决方案。