谈一下linq to sql的试图使用有关问题

谈一下linq to sql的试图使用问题
linq to sql可以通过交互式操作设计实体表,但是在使用视图时显得很不方便,比如建立了
实体表t1,列分别是t1_c1,t1_c2,t1_c3 和 实体表t2,列分别t2_c1,t2_c2,t2_c3,t2_c4
如果要使用两个表连接的视图,该怎么办?
如果返回的是t1表,wcf可以写出:
VB.NET code
<operationcontact>public function t1_t2_view as list(of t1)
return  (from s1 in dc.t1,s2 in dc.t2 where t1.t1_c1=t2.t2_c1 select s1).tolist
end function

如果返回的是t2表,wcf可以这样写:
VB.NET code
<operationcontact>public function t1_t2_view as list(of t2)
return  (from s1 in dc.t1,s2 in dc.t2 where t1.t1_c1=t2.t2_c1 select t2).tolist
end function

如果两个表的列都要返回,该怎么办,问题出在linq to sql中没有对应的两个表的实体
VB.NET code
<operationcontact>public function t1_t2_view as list(of ?)
return  (from s1 in dc.t1,s2 in dc.t2 where t1.t1_c1=t2.t2_c1 select t1.t1_c2 t2.t2_c4).tolist
end function

解决的办法是:在linq to sql中再定义一个实体,这里不妨把它称为视图实体 t1_t2_view,其列为t1_c2,t2_c4,此时wcf就可这样写了:
VB.NET code
<operationcontact>public function t1_t2_view as list(of t1_t2_view)
return  (from s1 in dc.t1,s2 in dc.t2 where t1.t1_c1=t2.t2_c1 select t1.t1_c2 t2.t2_c4).tolist
end function

我想解决视图问题是否可以用上述思路,请诸位讨论评价。






------解决方案--------------------
我谈一下对 ADO.NET Entity Framework 的印象,仅是凭印象,不保证是对的,而且不知道在 LINQ to SQL 中是否有对应的相同效果。

1. 如果不是为了Silverlight,在 EF 中,对于实体的查询,包括多个实体的查询,
除了可以将各个实体的投影以匿名类的方式返回(即 var),还可以以 DbDataRecord 结果集的方式返回,
其数据结构和 DataTable 中的 DataRow 是类似的。
很可惜的是,采用这种方式的话,传递到Silverlight端需要进行转化,和使用DataTable一样。

2. 如果不是在 WCF 中使用,其实以匿名类的方式返回是最为简单的,在同一个应用程序中可以直接使用匿名类。但是更遗憾的是,匿名类由于没有启用[DataContract]、[DataMember],不可能通过WCF进行传输。

3. 要同时在 WCF 和 Silverlight 中使用,就只有采用创建自定义的启用[DataContract]的实体类了,
而且,这样的实体类并非要在 EF 或者 LINQ to SQL 的设计器设计。
事实上,我一直没搞明白,在EF的设计器中,新建的实体(或者是视图)由于在 Storage模型上不能和数据库
的表或视图对应,所以在EF设计器中总是会报大意为“Concept概念模型和Storage模型”的错误的,
但是不影响代码的编译和运行。 ---- 这点我忘了LINQ to SQL有没有相同的现象。

4. 我猜测在 EF 设计器、LINQ to SQL 设计器中可以手工创建新实体、视图的一个更大的用意是为了能对
数据库中的某些表或视图进行 INSERT、UPDATE、DELETE 等操作。


像海哥遇到的这种情况,由于并不涉及到INSERT、UPDATE、DELETE 等操作,所以手工创建实体或者在设计器中创建实体/视图都可以。
但是这样也带来一个值得考虑的问题,究竟应当创建多少个实体才合适?

举例之, 有 User 、 FormA、FormB、FormC 等4个表, User 表有 UserId 和 RealName(真实姓名),
FormA、FormB、FormC 这三个表都有 UserId 字段。
在不同的查询页面,如FormA查询页面,要求显示出 FormA 的 UserId 以及对应的 RealName,
在FormB查询页面,要求显示出 FormB 的 UserId 以及对应的 RealName ...

那么,该创建多少个视图?
方式一: 为每一种组合创建一个视图, 也就是说 FormA+User 为一个视图,FormB+User 为一个视图,FormC+User 为一个视图,
这似乎没有什么问题,可是问题大得很呢, 如果要同时查询 FormA 和 FormB 呢,那不是又得创建 FormA+User + FormB+User 的视图?

方式二: 根据具体的页面来创建 Model ,再根据 Model 来决定要在 WCF 中创建什么视图。
这是很难接受的一种设计方式,WCF端的实体定义竟然受制于Silverlight端,
但是,WCF RIA Services的推广,多多少少会促成这种设计方式。

方式三: 使用 IValueConverter。 这是我最推崇的方式,也就是不会创建任何 FormX + User 的视图,
而是在 Silverlight 端通过 IValueConverter ,将 UserId 转换为 RealName。
如果 User 表是基础数据,强烈推荐这么做。

方式四: 使用导航属性,而且是一对一的导航。
FormX 中除了有 UserId 属性外,还有一个 User类型的 导航属性,如名为 UserObject,
在查询时,通过 LoadWith() 等各种方式将对应的 User 也一起查询出来,然后返回至 Silverlight 端。
这种好处是方便了 Silverlight 端的使用,
坏处是 WCF 端变复杂了, 不仅是 LINQ 语句复杂了,而且很可能造成 SQL 的查询性能极其低下,
同时还要控制好延迟加载,避免因为 User类型 还有子导航属性而不能被序列化。


一下子写了这么多,额,睡觉去了,明天还要赶早班车,体验“被”高速。