我正在开发一个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文件中。可能有什么不对?
答案 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 };
该类可能只有一堆属性,id
,Name
等。您只需在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来获得更强大的解决方案。