兴国安邦

C# 3.0, Linq, Linq To Sql

博客园 首页 新随笔 联系 订阅 管理
  33 Posts :: 0 Stories :: 530 Comments :: 52 Trackbacks
Linq To Sql进阶系列(一) 一文中,我们谈到了数据库中的两种基本关系1:M 与1:1. 而现实世界中,还有一种M:M 的关系。比如,一个老师可以有多个学生,而一个学生也可以有多个老师。老师和学生的关系就是多对多的关系。这些关系在数据库中是如何反映的呢?
C#3.0入门系列(十)-之Join操作一文中,我们提到了M:M 的关系中的join操作。哦,原来,M:M 的关系在数据库中,依然是通过1:M 来体现。比如,在一个域内,一个User可以加入到多个Group中,一个Group也可以包含多个User。 User与Group并没有直接的关系,而是通过第三个表UserInGroup发生关系。User与 UserInGroup的关系为1:M,其关系键为UserId, 而Group与 UserInGroup的关系也为1:M, 其关系键为GroupId,这样,我们通过第三个表,让User与Group发生了关系,他们的关系为M:M.
这三个表的脚本如下:
他们的关系图如下:


创建数据库后,添加一些数据供测试。

使用OR Designer将他们映射为实体。关于OR Designer请参考C#3.0入门系列(七)--之OR工具介绍

现在的问题是:User和Group的实体对象中,可不可以直接引用对方呢?就像User.Groups 或Group.Users。我们可不可以去改变其映射,直接越过UserInGroup,让User和Group直接发生关系呢?回答是肯定的。但是,数据库中,依然是三个表。你不可能在数据库中越过表UserInGroup的。表UserInGroup起了一个纽带的作用,想把它抛弃掉,不太可能。那可不可以,在mapping code中,做些手脚,让Linq To Sql自己去找这个纽带呢?回答是,Linq To Object可以,但是, Linq To Sql不可以。

为什么Linq To Sql不可以?其原因就是Linq To Sql需要先翻译成Sql语句,而,这个映射,必须真实反映数据库里表的情况。也就说,这个映射,无法逾越UserInGroup实体。它必须要有UserInGroup。
那Linq To Object怎么样可以呢?把下面的代码,加入到你的工程中。
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.ComponentModel;
using System;

namespace ConsoleApplication1
{
    
public partial class Group
    
{
        
public List<User> Users
        
{
            
get
            
{
                
return (from u in this.UserInGroups
                        select u.User).ToList();
            }

        }

    }

    
public partial class User
    
{
        
public List<Group> Groups
        
{
            
get
            
{
                
return (from g in this.UserInGroups
                        select g.Group
                            ).ToList();
            }

        }

    }

}


为了不破坏数据库的映射,我们把这部分改动放到partial  class中。这样,我们渴望实现user.Group。
我们来做个测试,看看是不是成功了呢。
太好了。这正是我们想要的。那再来做个反面的测试吧。
        var q = (from u in db.Users
                  
from g in u.Groups
                  
select new { u.UserName, g.GroupName }).ToList();
编译通过,在run-time时,出错。因为,Linq To Sql不知道该怎么去找这个关系。那么下面这个呢?
        var q2 = (from u1 in (from u in db.Users
                  
select u).ToList()
                  
from g in u1.Groups
                  
select new { u1.UserName, g.GroupName }).ToList();
run-time没有问题。纠起原因,其在里面已经取回了数据,是Linq To Object的范畴了。

还可以使用下面的这个映射code。
结合我们的测试例子,请大家仔细比较他们的区别哦。前面那个是一次性取出了。后面这个是用那个取那个。

posted on 2007-07-31 10:31 Tom Song 阅读(4964) 评论(13)  编辑 收藏 所属分类: C# 3.0Linq To Sql

Feedback

#1楼 [楼主] 2007-07-30 15:52 宋国安      
在外部看起来,是直接
User.Groups.
Group.Users

其实,也只是耍了个滑头。有点类似匿名类。匿名类,其实不匿名。
  回复  引用  查看    

#2楼  2007-07-30 16:30 跨越      
studying....
  回复  引用  查看    

#3楼  2007-07-30 17:27 木野狐      
@宋国安
非常感谢,晚上回去后仔细学习一遍 :)

  回复  引用  查看    

#4楼  2007-07-31 10:08 钱彦云      
不错。
  回复  引用  查看    

#5楼  2007-08-01 16:57 onekey      
建立映射CODE没什么用啊,
直接获取不行么?

var q = (from u in db.Users
select new { u.UserName, u.UserInGroups.GroupName }).ToList();
  回复  引用  查看    

#6楼 [楼主] 2007-08-01 19:02 宋国安      
@onekey
行呀。当然可以呀。修改映射code,不是为了让user和group的关系,更直接些吗。
  回复  引用  查看    

#7楼  2007-08-05 21:38 伍迷      
非常感谢,你的教程让我受益良多。
  回复  引用  查看    

#8楼  2007-09-26 21:08 俗人 [未注册用户]
var q = (from u in db.Users
select new { u.UserName, u.UserInGroups.GroupName }).ToList();

u.UserInGroups.GroupName错误,编译不通过,此法不通
环境vs2008+EXPress2005
  回复  引用    

#9楼  2007-12-14 10:24 windwolf      
这种方法只是完成了查询操作以及修改. 增删操作不支持
  回复  引用  查看    

#10楼  2008-03-31 11:27 GG [未注册用户]
难道目前的的MS提供的代码生成工具不能自动检测数据库中表与表之间的1:M,M:M关系,自动生成相应的实体类吗?
  回复  引用    

#11楼  2008-07-25 11:53 lilingyun [未注册用户]
studying,thanks!
  回复  引用    

#12楼  2008-09-28 16:08 Arthur King      
@onekey
感觉你的语句有错误。u.UserInGroups是一个集合。不是一条记录。

对于M:M关系直接使用Linq To Sql, 应该使用关系表作为连接。
我一般这么写:
查询某一个用户的Group信息:
var query =
from user in db.Users
where user.UserId = 用户Id

from userInGroups in db.UserInGroups
where userInGroups.UserId = user.UserId

from group in db.Groups
where group.GroupId = userInGroups.GroupId

select group ;

感觉很麻烦。再次感谢作者提供的知识点,堵塞了几天的思路豁然开朗!
目前我正在用LINQ做项目,也是边学边做。估计是要面对百万PV的项目,性能方面还不知道是否撑得住。架构师一句话:要用ORM! 我们实现框架的就有得受了……

  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)