前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Entity Framework快速入门--一对零到一关系处理

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

作者头像
老马
发布2022-05-10 15:58:26
3510
发布2022-05-10 15:58:26
举报
文章被收录于专栏:老马寒门IT老马寒门IT

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

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

首先我们EDMX实体模型:

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

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

单独插入User实体数据:

代码语言:javascript
复制
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实体两个数据

代码语言:javascript
复制
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:

代码语言:javascript
复制
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时候一定注意这个细节。

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

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

如:

代码语言:javascript
复制
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为:

代码语言:javascript
复制
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表的几个字段取出方法如下:

代码语言:javascript
复制
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脚本为:

代码语言:javascript
复制
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])

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2011-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档