zoukankan      html  css  js  c++  java
  • 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快速入门--索引贴

    作者:FlyDragon

    出处:http://www.cnblogs.com/fly_dragon/

    关于作者:专注于微软平台项目架构、管理和企业解决方案。如有问题或建议,请多多赐教!

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通malun666@126.com 联系我,非常感谢。

  • 相关阅读:
    4、Java基本数据类型
    3、Java 对象和类
    2、Java 基础语法标识符、修饰符、变量、 数组、枚举、关键字
    1、Java 开发环境配置
    近期目标
    Java泛型是什么?实战demo
    Java高级篇XML和正则表达式
    Java高级篇反射和注解
    Java高级篇 JVM
    JavaScript执行顺序
  • 原文地址:https://www.cnblogs.com/fly_dragon/p/2072701.html
Copyright © 2011-2022 走看看