惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
T
Threatpost
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
S
Secure Thoughts
MyScale Blog
MyScale Blog
O
OpenAI News
P
Palo Alto Networks Blog
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
量子位
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Know Your Adversary
Know Your Adversary
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
I
InfoQ
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
S
Security @ Cisco Blogs
S
Schneier on Security
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
AWS News Blog
AWS News Blog
IT之家
IT之家
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
H
Heimdal Security Blog
I
Intezer
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
W
WeLiveSecurity

博客园 - Tom Song

招聘net 开发 RAR 协议- 探针协议 Linq To Sql 项目从Beta迁移到RTM注意事项 杀人游戏系列 之三 提供游戏代码下载 杀人游戏系列 之二 Linq To Sql进阶系列 -目录导航 C# 3.0入门系列-目录导航 杀人游戏系列 之一 谈Linq To Sql的优劣--纯个人观点 Linq To Sql进阶系列(七)动态查询续及CLR与SQL在某些细节上的差别 Linq To Sql进阶系列(六)用object的动态查询与保存log篇 数据库中使用 Synonym和openquery SQL 语句中特殊字符的处理及预防sql 注射 Linq To Sql进阶系列(五)Store Procedure篇 C# 3.0与Linq To Sql的学习方法--浅谈 C#3.0入门系列(十二)-Lambda表达式中Lifting Linq To Sql进阶系列(四)User Define Function篇 Linq To Sql进阶系列(三)CUD和Log C#3.0入门系列(十一)-之In, Like操作
Linq To Sql进阶系列(二)M:M关系
Tom Song · 2007-07-31 · via 博客园 - Tom Song

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。

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