1-指定导航属性,会自动生成外键,命名规则为:“表名_主键名”
2-默认情况下与导航属性的主键名称相同的字段会自动被标记为外键
3-通过[ForeignKey]标记指定实体类的属性为外键,
4-方式2的升级版,与导航属性的主键名称相同的字段会自动被标记为外键,然后指定字段对应的数据库中的列名

案例:

组织架构n : 1【组织用户关联】1 :n用户

using System;
/**
* 作者:陈杰
* 时间:2012-08-10 00:25
* 功能:公共字段接口
**/
namespace ElegantWM.EntityModel
{
public interface IEntity
{
Guid Id { get; set; } string CreateUser { get; set; }
DateTime CreateTime { get; set; }
string ModifyUser { get; set; }
DateTime? ModifyTime { get; set; }
Byte[] RowVersion { get; set; }
}
}
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
/**
* 作者:陈杰
* 时间:2012-08-10 00:25
* 功能:公共字段接口实现类
**/
namespace ElegantWM.EntityModel
{
public class Entity:IEntity
{
public Guid Id { get; set; } public string CreateUser { get; set; }
public DateTime CreateTime { get; set; }
public string ModifyUser { get; set; }
public DateTime? ModifyTime { get; set; }
[Timestamp]
public Byte[] RowVersion { get; set; }
}
}

以上两个类为数据库实体的公共属性,但随着业务的复杂度增加,感觉提取实体的公共字段并不是很妥当,可适当折中考虑。

/*  组织架构实体  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ElegantWM.EntityModel
{
public class WMS_Org : Entity
{
public WMS_Org() { } public string OrgName { get; set; }
public string OrgDesc { get; set; }
public int OrgOrder { get; set; }
public string OrgFatherId { get; set; }
public virtual ICollection<WMS_OrgUser> OrgUserIds { get; set; }
}
}
/*  用户实体  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ElegantWM.EntityModel
{
public class WMS_User : Entity
{
public WMS_User() { } public string UserName { get; set; }
public string NickName { get; set; }
public string UserPwd { get; set; }
public string Sex { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string QQ { get; set; }
public string Address { get; set; }
public string Remark { get; set; }
public virtual ICollection<WMS_OrgUser> UserOrgIds { get; set; }
}
}
/* 用户和组织架构的关系 */
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text; namespace ElegantWM.EntityModel
{
public class WMS_OrgUser : Entity
{
public WMS_OrgUser() { }
//3. 指定外键的方式
public Guid OrgId { get; set; }
[ForeignKey("OrgId")]
public virtual WMS_Org Org { get; set; } public Guid UserId { get; set; }
[ForeignKey("UserId")]
public virtual WMS_User User { get; set; } //1. 不指定外键,EF默认会生成 对象_表对象ID,也就是Org_Id,User_Id
public virtual WMS_Org Org { get; set; }
public virtual WMS_User User { get; set; }
} //2. 不适合本案例,因为所有对象的主键都是ID,自动识别
public Guid Id { get; set; }
public virtual WMS_Org Org { get; set; }
......
//4. 指定数据库真实外键名称
[Column("OrgID")]
public Guid Id { get; set; }
public virtual WMS_Org Org { get; set; }
}

根据上面的4个原则,可以在组合出符合自己实际业务的关联类。

建立好了关联类后,需要注意的是,数据库中外键类型必须和主表的主键类型一致,当然外键关系你可以不用强制建立,但类型必须一直,否则会出错。

关联的对象注意声明为virtual,以供延迟加载。

当 EF 访问实体的子实体的时候是如何工作的呢?你的集合是 POCO 的集合,所以,在访问的时候没有事件发生,EF 通过从你定义的实体派生一个动态的对象,然后覆盖你的子实体集合访问属性来实现。这就是为什么需要标记你的子实体集合属性为 virtual 的原因。

执行EF的操作,验证
//1.创建关系
WMS_OrgUser ou = new WMS_OrgUser();
ou.OrgId = Guid.Parse("79DDB55A-1587-4928-A312-58DA0C091459");
ou.UserId = Guid.Parse("9E99FBCF-1517-4ACA-A81D-AE3535AF8E37");
WMFactory.WMSOrgUser.Insert(ou); //2. 根据关系,已知组织ID,获取用户
WMS_OrgUser orguser = WMFactory.WMSOrgUser.GetById("7E632B62-B8EC-4D58-AE94-A412868146E7");
//正常获取了用户对象,正常打印用户昵称
string name = orguser.User.NickName;
//3.测试贪婪加载,见文章后面
orguser = WMFactory.WMSOrgUser.TestNoLazyLoading(Guid.Parse("7E632B62-B8EC-4D58-AE94-A412868146E7")); //4.获取组织架构下的用户
WMS_Org org = WMFactory.WMSOrg.GetById("79DDB55A-1587-4928-A312-58DA0C091459");
ICollection<WMS_OrgUser> coll = org.OrgUserIds;
orguser = coll.ToList()[0];
string orguserid=orguser.Id.ToString();
string orgusername = orguser.User.NickName;
关于延迟加载和贪婪加载

1.延迟加载,当对象使用的时候,再去数据库中加载,例如上面的orguser.User,当我调用这句话的时候,EF会到数据库中加载数据

EF默认是开启延迟加载的,禁用如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration.Conventions;
using ElegantWM.EntityModel;
using System.Configuration;
/**
* 作者:陈杰
* QQ:710782046
* 时间:2012-08-10
* 功能:EF配置文件,支持多数据库
**/
namespace ElegantWM.DAL
{
public class DB : DbContext
{
//public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); //配置连接串,默认数据库DefaultDB
public DB(string _ConnectStr)
: base()
{
Database.Connection.ConnectionString = ConfigurationManager.ConnectionStrings[_ConnectStr].ToString();
Database.SetInitializer<DB>(null);
//这里哦
this.Configuration.LazyLoadingEnabled = false;
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//已经存在的数据库,不然会出现负数
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
//注册到EF
public DbSet<WMS_Role> wmRole { get; set; }
public DbSet<WMS_User> wmUser { get; set; }
public DbSet<WMS_Org> wmOrg { get; set; } public DbSet<WMS_Module> wmModule { get; set; }
public DbSet<WMS_RoleModule> wmRoleModule { get; set; }
public DbSet<WMS_UserRole> wmUserRole { get; set; }
public DbSet<WMS_OrgUser> wmsOrgUser { get; set; }
}
}

2.贪懒加载,一次性把数据组织好,加载到内存,类似join表

例如以上案例4,通过组织架构获取用户,EF延迟加载执行的sql如下:

exec sp_executesql N'SELECT TOP (2)
[Extent1].[Id] AS [Id],
[Extent1].[OrgName] AS [OrgName],
[Extent1].[OrgDesc] AS [OrgDesc],
[Extent1].[OrgOrder] AS [OrgOrder],
[Extent1].[OrgFatherId] AS [OrgFatherId],
[Extent1].[CreateUser] AS [CreateUser],
[Extent1].[CreateTime] AS [CreateTime],
[Extent1].[ModifyUser] AS [ModifyUser],
[Extent1].[ModifyTime] AS [ModifyTime],
[Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[WMS_Org] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0',N'@p__linq__0 uniqueidentifier',@p__linq__0='79DDB55A-1587-4928-A312-58DA0C091459' exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[OrgId] AS [OrgId],
[Extent1].[UserId] AS [UserId],
[Extent1].[CreateUser] AS [CreateUser],
[Extent1].[CreateTime] AS [CreateTime],
[Extent1].[ModifyUser] AS [ModifyUser],
[Extent1].[ModifyTime] AS [ModifyTime],
[Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[WMS_OrgUser] AS [Extent1]
WHERE [Extent1].[OrgId] = @EntityKeyValue1',N'@EntityKeyValue1 uniqueidentifier',@EntityKeyValue1='79DDB55A-1587-4928-A312-58DA0C091459' exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserName] AS [UserName],
[Extent1].[NickName] AS [NickName],
[Extent1].[UserPwd] AS [UserPwd],
[Extent1].[Sex] AS [Sex],
[Extent1].[Phone] AS [Phone],
[Extent1].[Email] AS [Email],
[Extent1].[QQ] AS [QQ],
[Extent1].[Address] AS [Address],
[Extent1].[Remark] AS [Remark],
[Extent1].[CreateUser] AS [CreateUser],
[Extent1].[CreateTime] AS [CreateTime],
[Extent1].[ModifyUser] AS [ModifyUser],
[Extent1].[ModifyTime] AS [ModifyTime],
[Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[WMS_User] AS [Extent1]
WHERE [Extent1].[Id] = @EntityKeyValue1',N'@EntityKeyValue1 uniqueidentifier',@EntityKeyValue1='9D001F8D-E304-4DB3-B5C0-7C5139E888A6'

贪婪加载的方式,如测试3,产生的SQL如下:

 public WMS_OrgUser TestNoLazyLoading(Guid id)
{
return DBSET.Include("User").Include("Org").FirstOrDefault(o => o.Id == id);
}
exec sp_executesql N'SELECT
1 AS [C1],
[Limit1].[Id] AS [Id],
[Limit1].[OrgId] AS [OrgId],
[Limit1].[UserId] AS [UserId],
[Limit1].[CreateUser] AS [CreateUser],
[Limit1].[CreateTime] AS [CreateTime],
[Limit1].[ModifyUser] AS [ModifyUser],
[Limit1].[ModifyTime] AS [ModifyTime],
[Limit1].[RowVersion] AS [RowVersion],
[Extent2].[Id] AS [Id1],
[Extent2].[UserName] AS [UserName],
[Extent2].[NickName] AS [NickName],
[Extent2].[UserPwd] AS [UserPwd],
[Extent2].[Sex] AS [Sex],
[Extent2].[Phone] AS [Phone],
[Extent2].[Email] AS [Email],
[Extent2].[QQ] AS [QQ],
[Extent2].[Address] AS [Address],
[Extent2].[Remark] AS [Remark],
[Extent2].[CreateUser] AS [CreateUser1],
[Extent2].[CreateTime] AS [CreateTime1],
[Extent2].[ModifyUser] AS [ModifyUser1],
[Extent2].[ModifyTime] AS [ModifyTime1],
[Extent2].[RowVersion] AS [RowVersion1],
[Extent3].[Id] AS [Id2],
[Extent3].[OrgName] AS [OrgName],
[Extent3].[OrgDesc] AS [OrgDesc],
[Extent3].[OrgOrder] AS [OrgOrder],
[Extent3].[OrgFatherId] AS [OrgFatherId],
[Extent3].[CreateUser] AS [CreateUser2],
[Extent3].[CreateTime] AS [CreateTime2],
[Extent3].[ModifyUser] AS [ModifyUser2],
[Extent3].[ModifyTime] AS [ModifyTime2],
[Extent3].[RowVersion] AS [RowVersion2]
FROM (SELECT TOP (1) [Extent1].[Id] AS [Id], [Extent1].[OrgId] AS [OrgId], [Extent1].[UserId] AS [UserId], [Extent1].[CreateUser] AS [CreateUser], [Extent1].[CreateTime] AS [CreateTime], [Extent1].[ModifyUser] AS [ModifyUser], [Extent1].[ModifyTime] AS [ModifyTime], [Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[WMS_OrgUser] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0 ) AS [Limit1]
LEFT OUTER JOIN [dbo].[WMS_User] AS [Extent2] ON [Limit1].[UserId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[WMS_Org] AS [Extent3] ON [Limit1].[OrgId] = [Extent3].[Id]',N'@p__linq__0 uniqueidentifier',@p__linq__0='7E632B62-B8EC-4D58-AE94-A412868146E7'

EF5.X Code First表关联与延迟加载的更多相关文章

  1. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  2. 【EF学习笔记06】----------加载关联表的数据 延迟加载

    讲解之前,先来看一下我们的数据库结构:班级表 学生表 延迟加载 //延迟加载 using (var db = new Entities()) { //查询班级 var classes = (from ...

  3. SQL语句分组排序,多表关联排序

    SQL语句分组排序,多表关联排序总结几种常见的方法: 案例一: 在查询结果中按人数降序排列,若人数相同,则按课程号升序排列? 分析:单个表内的多个字段排序,一般可以直接用逗号分割实现. select ...

  4. RDIFramework.NET 中多表关联查询分页实例

    RDIFramework.NET 中多表关联查询分页实例 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用户和开发者最佳的.Net框架部署方案.该框架以SOA范式作为 ...

  5. Solr数据库连接之多表关联

    Solr环境配置好后,有很多时候我们需要把数据库里的数据添加到索引里,这时就需要配置跟数据库的连接,下面我们看配置的步骤. 1. 配置 solrconfig.xml  (在slor 主目录 core ...

  6. MVC3+EF5.0 code first+Flexigrid+ajax请求+jquery dialog 增删改查

    MVC3+EF5.0 code first+Flexigrid+ajax请求+jquery dialog 增删改查 本文的目的:   1.MVC3项目简单配置EF code first生成并初始化数据 ...

  7. hibernate的基础学习--多表关联数据查询

    Hibernate共提供4种多表关联数据查询方式 OID数据查询+OGN数据查询方式 HQL数据查询方式 QBC数据查询方式 本地SQL查询方式(hibernate很少用) 1.OID数据查询+OGN ...

  8. oracle多表关联多字段update

    多表关联多字段update 有代码有J8: update spatial_references set( auth_name, auth_srid, falsex, falsey, xyunits, ...

  9. sql server多表关联update

    一般都是写的单表update语句,很少写多表关联的update,但是事实上,在SQL Server中,update的多表连接更新和select的多表连接查询在使用的方法上其实并没有多大区别. 直接上一 ...

随机推荐

  1. 学习Berkeley DB- 入门

    1 导言 首先,我们要了解Berkeley DB的一些基本特性,在IBM的开发网站上有篇文章对其有比较清晰的介绍: 这篇文章讲到了BDB的设计思想和核心数据结构.以及数据访问算法:并有常用函数使用范例 ...

  2. Timer 实现2秒4秒连环炸

    package com.cn.gbx; import java.util.Date; import java.util.Timer; import java.util.TimerTask; //cla ...

  3. Windows Live Writer编写Octopress

    Windows live Writer是一个可以用来离线编写,并发布博客的工具. Octopress是一个静态博客生成系统.使用群体多是geek,主要有显示代码清晰,git同步,并且不用购买空间的特点 ...

  4. bootstrap学习笔记<五>(表单一)

    表单 bootstrap为表单提供三种样式:默认表单,水平表单,内联表单. <form class="form-horizontal" role="form&quo ...

  5. python操作mongodb之五大量写操作

    import pymongo #库名 db = pymongo.MongoClient('192.168.30.252',27017).bulk_example #test集合插入 db.test.i ...

  6. 使用升级助 升级了win10,黑屏,无桌面 解决方案

    使用U盘重装即可. 事实证明,win10升级助手实在不咋地 优待又2: (1)保留原win7系统,有后悔药: (2)原系统的软件可用: 缺点: (1)装得慢,一上午: (2)开机慢,三分半 (3)开机 ...

  7. ctrl + d 在phpstorm 和 eclipse 中的不同含义

    Ctrl + d 在phpstrom是复制一行,非常的方便,但是eclipse中却是删除一行,非常的特别.感觉上,phpstorm更注重鼠标,但eclipse貌似更多鼠标和键盘的操作, 默认情况下[p ...

  8. Linkclump – 批量打开多个链接[Chrome]

    我的收藏 | 登录 首页 » Chrome » Linkclump – 批量打开多个链接[Chrome] 收藏 2  (1 votes) 青小蛙 on 2016.04.06. Linkclump 是一 ...

  9. JSP Filter

    Servlet过滤器方法 一个过滤器就是一个Java类,它实现了javax.servlet.Filter 接口.javax.servlet.Filter接口定义了三个方法: 序号 方法 &描述 ...

  10. robotframework笔记27

    文档格式 可以使用简单的HTML格式 测试套件 , 测试用例 和 用户关键字 文档和 免费测试套件 元数据 在测试数据,以及当 记录测试 库 . 格式类似于大多数使用的风格 维基百科,它被设计成可以理 ...