Entity Framework快速入门--一对零到一关系处理

很久不更新blog了,正好趁着端午节的空,把之前一段时间使用关于EF以及工作上经验总结一下。

此文将跟朋友们分享一下关于1对0..1实体模型一些使用包括基本的添加和查询的注意事项。

首先我们EDMX实体模型:

模型很简单,一个用户的实体,另外关联了一个用户信息的实体。有些情况下我们会有这样的需求,用户登录身份验证,而每次再查询用户信息的时候,往往会去查询用户表,而这时候我们仅仅使用了2-3个字段也就是用户账号跟密码是否一致,如果一致就返回true,否则返回false,而我们往往在用户表上挂在很多的其他字段,这样就造成了无谓的性能损失。当然如果访问量很小的话,那也无所谓了。  有时候我们会把一些可以为null或者经常不使用的字段放到一张UserInfo表中,而频繁访问和验证的用户表单独出一个小的表,用于专门来进行身份验证等业务。如上图EDMX的设计,当然只是一个模拟的例子。

根据这个1对0到1的关系,我们自己猜一下也能想到,那就我们在进行将用户信息持久化到数据库时,用户信息表实体(UserInfo)必须挂在到一个User实体上才能持久化到数据库。而User表不受UserInfo表的影响,可以单独插入一条数据。看下面代码都是可以正确执行:

单独插入User实体数据:


static void InsertData()
{
using (CompanyContainer companyContainer = new CompanyContainer())
{
User user = new User();
user.Code = "flydragon";
user.Name = "飞龙天惊";
user.Password = "haha";
companyContainer.User.AddObject(user);
companyContainer.SaveChanges();
}
}

我们也可以同时保存一个整体的数据,如下代码所示:插入User+UserInf实体两个数据


static void InsertFullData()
{
using (CompanyContainer companyContainer = new CompanyContainer())
{
User user = new User();
user.Code = "flydragon3";
user.Name = "飞龙天惊3";
user.Password = "haha3";
companyContainer.User.AddObject(user);

UserInfo userInfo = new UserInfo();
userInfo.Email = "malun666@hotmail.com";
userInfo.Address = "北京上地";
userInfo.Phone = "110";
userInfo.User = user;
userInfo.Rmark = "";
companyContainer.UserInfo.AddObject(userInfo);
companyContainer.SaveChanges();
}
}

上面没什么好说的,也没什么好主意的点。当然在项目中还是遇到了很多细节的问题。当然比较头疼的一个问题就是1对0...1关系模型数据的查询异常的BUG。我们在查询User实体数据的时候,EF帮我们生成的SQL脚本却自动的帮我们对UserInfo表进行Left Out Join。很多情况我们只检索了User表的数据,却也进行了Join的操作,这样使我们本来为了提高用户表数据查询的效率反而进行了Join,数据量成了两个表的笛卡尔积的结果里进行查询,这样效果肯定不好。看下面代码以及SqlProfile追踪到的SQL:


static void Main(string[] args)
{
CompanyContainer companyContainer = new CompanyContainer();
var result = companyContainer.User.Where<User>(u => u.Code == "flydragon3")
.Where<User>(u => u.Password == "haha3")
.FirstOrDefault<User>();
if (result != null)
{
Console.WriteLine(result.Name);
}
Console.ReadKey();
}

下面是用SQLProfile工具追踪到的执行的SQL脚本:

很明显我们看到的是有User表和UserInfo表的Join操作。我猜测EF内部实现的细节可能是初始化User实体的时,由于导航属性UserInfo的关系是1 对0..1做了特殊处理,也将UserInfo的数据取出来初始化了导航属性UserInfo。

这个需要大家使用EF时候一定注意这个细节。

那我们怎样避免这样的结果呢:

下面几种方式是可以杜绝这种外连接的:

如:


static void Main(string[] args)
{
CompanyContainer companyContainer = new CompanyContainer();
var result = companyContainer.User.Where<User>(u => u.Code == "flydragon3")
.Where<User>(u => u.Password == "haha3").Count();
Console.WriteLine(result);
Console.ReadKey();
}

对应产生的SQL为:


SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[User] AS [Extent1]
WHERE (N'flydragon3' = [Extent1].[Code]) AND (N'haha3' = [Extent1].[Password])
) AS [GroupBy1]

另外怎么只查询User,并将User表的几个字段取出方法如下:


static void Main(string[] args)
{
CompanyContainer companyContainer = new CompanyContainer();
var result = companyContainer.User.Where<User>(u => u.Code == "flydragon3")
.Where<User>(u => u.Password == "haha3")
.Select(u => new { Id=u.Id,Name = u.Name }).FirstOrDefault();
if (result != null)
{
Console.WriteLine(result.Name);
}
Console.ReadKey();
}

最终生成的SQL脚本为:


SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[User] AS [Extent1]
WHERE (N'flydragon3' = [Extent1].[Code]) AND (N'haha3' = [Extent1].[Password])

暂时总结到这里,写文章真是费时费力!希望大家都分享自己的知识,大家一起交流一起进步!祝大家端午快乐!

Entity Framework快速入门--索引贴

时间: 2024-09-15 02:33:06

Entity Framework快速入门--一对零到一关系处理的相关文章

Entity Framework快速入门--索引贴

此系列在不断完善中,希望能将我关于Entity Framework的知识总结整理到这里跟大家分享,也希望得到大家的指点!共同进步,共同提高!谢谢! Entity Framework快速入门 Entity Framework快速入门--实例篇 DatabaseFirst Entity Framework快速入门--IQueryable与IEnumberable的区别 Entity Framework快速入门--ModelFirst Entity Framework快速入门--CodeOnly PO

Entity Framework快速入门--ModelFirst

Entity Framework带给我们的不仅仅是操作上的方便,而且使用上也很是考虑了用户的友好交互,EF4.0与vs2010的完美融合也是我们选择它的一个理由吧.相比Nhibernate微软这方面做的的确是很不错. 下面我将使用CodeFirst方式来做个简单是实际例子与大家分享. 我们还是和 前面的文章 Entity Framework快速入门--实例篇一样,创建一个控制台项目. 第一步:创建控制台项目 第二步:在项目上右击添加Ado.Net 实体数据模型 如图所示: 第三步: 选择生成实体

Entity Framework快速入门--CodeOnly POCO

前几篇文章我简单介绍了Entity Framework的概念以及介绍了Database First方式实例和Model First方式实例.今天我们将介绍另外一种令人兴奋的开发方式:CodeOnly!当然EF对于POCO(Plain Old CLR Object)的支持是EF4.0中的一大特性.也是EF可扩展性提高的一大进步.废话少说,也是简单给大家演示一下操作的步骤!先简单说一下流程,然后再看下面的截图! 流程:在EDMX设计器里设计 实体模型→根据实体编写相应的实体类代码→编写数据库访问接口

Entity Framework快速入门--实例篇 DatabaseFirst

在上一篇中我们简单了解的EF的定义和大体的情况,我们通过一步一步的做一个简单的实际例子来让大家对EF使用有个简单印象.好,废话少说,直入主题. 第一步:创建控制台项目 这个就不多说了,如果新建项目你还不知道,那先去学学基础吧. 第二步:创建实体模型 在项目上右击 添加新建项目→Ado.Net实体数据模型 如下图所示: 第三步:与现有的数据库进行连接生成EF实体 在做这步之前,首先确定你是否已经有现有数据库,当然在这提供我自己的数据库脚本. View Code -- ---------------

Entity Framework快速入门

实体框架(Entity Framework)简介 实体框架Entity Framework 是 ADO.NET 中的一组支持开发面向数据的软件应用程序的技术.是微软的一个ORM框架. ORM知识补充:什么是O/R Mapping? 广义上,ORM指的是面向对象的对象模型和关系型数据库的数据结构之间的相互转换. 狭义上,ORM可以被认为是,基于关系型数据库的数据存储,实现一个虚拟的面向对象的数据访问接口.理想情况下,基于这样一个面向对象的接口,持久化一个OO对象应该不需要要了解任何关系型数据库存储

Entity Framework快速入门--直接修改(简要介绍ObjectContext处理机制)

在介绍Entity Framework的修改实体到数据库的方法之前呢,我们先简要的介绍一下ObjectContext的处理机制. 1.ObjectContext的处理机制 ObjectContext是Entity Framework封装了数据库访问的上下文,以及实体的映射关系元数据信息等.EF帮我们封装好了这么一个统一的接口.让我们所有的操作都只通过这个一个实体上下文就可以实现了增删查改等所有对应数据库的操作.当然,我们要了解EF的生成SQL的机制我们才能更好的使用EF帮我们生成效率更高的SQL

Entity Framework快速入门--IQueryable与IEnumberable的区别

IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 它继承 IEnumerable 接口,而因为.net版本加入Linq和IQueryable后,使得IEnumerable不再那么单调,变得更加强大和丰富. 为了区别两个接口,我们通过一个实际的例子来解释一下. 根据上篇随笔的实例,编写如下代码: static void Main(string[] a

【转】 .Net Micro Framework 快速入门

   .Net Micro Framework 快速入门 收藏  一.简介   Microsoft .NET Micro Framework 2001年由微软研究院开始研发,并随后在其MSN Direct项目中使用该技术,2007年9月微软对外发布2.0,2008年10月 V3.0.2009年11月 V4.0.2010年5月 V4.1 beta,2009年并入.NET产品组,Digi.Atmel.飞思卡尔等半导体公司都先后为其推出了开发板,该技术可以应用到远程控制.智能家电.教育类机器.医疗电子

Robot Framework 快速入门_中文版

目录 介绍 概述 安装 运行demo 介绍样例应用程序 测试用例 第一个测试用例 高级别测试用例 数据驱动测试用例 关键词keywords 内置关键词 库关键词 用户定义关键词 变量 定义变量 使用变量 组织测试用例 测试套件 启动和卸载 使用标签 创建测试库       介绍 概述 Robot Framework 是一个关键词驱动的自动测试框架.测试用例位于HTML或者TSV(以tab分隔值)文件,使用在测试库中实现的关键词来在测试中运行程序.因为Robot Framework 是灵活和可扩展