Entity Framework Code First 简称 EF CF也行,就是在开发的时候,以代码先行的原则,开发人员无需考虑

数据库端的一些问题(开发过程中基本不需要在数据库管理器上操作)

言归正传吧,最近刚刚入手MVC EF 的CF开发,原因就是他的开发效率比较高,适合中小型项目。既然说到项目,那就涉及到稍微复杂点的数据表关系。要使用联合查询,外键等技术才能实现一些功能。

下面举例说明我在实际测试中遇到的一些问题。

场景:用户权限管理系统中的关系——分为 公司 部门 职员 3个表

由于是用CF形式开发,所以我直接在model层写下3个模型,以阐述3个表的关系。

本测试经过3次测试

第一次测试:标准的约定配置,主从表均加入描述:

========================================================
如主表加导航属性 public virtual ICollection<。。。>

从表加引入属性             public int 外键{ get; set; } <-----此处制定外键
                [ForeignKey("外键")]
                  public virtual 引用实体 实体{ get; set; }

代码如下!

WorkGroup

公司表,每个公司有N个角色(总经理,财务部,开发部等)

namespace MvcDemo.Model.System
{
public class WorkGroup
{
[Key]
//公司的唯一ID
public int ID { get; set; }
//公司下可能有子公司所以此表可以作为递归表
public int PID { get; set; }
//公司的名称
public string GroupName { get; set; }
//公司的描述
public string Description { get; set; }
//公司是否通过管理员的验证(本系统可以负责多个公司的人员管理,系统管理员需要审批是否允许某公司使用本系统)
public bool IsPassed { get; set; }
//一个公司下有多个职员
public virtual ICollection<UserBase> UserBase { get; set; }
//一个公司下有多个权限
public virtual ICollection<UserGroup> UserGroup { get; set; }
}
}

UserGroup

职务角色表,每个职务角色都隶属于某个公司,每个职务下面都有N个职员一起共事

namespace MvcDemo.Model.User
{
public class UserGroup
{
[Key]
//职务角色表的唯一ID
public int ID { get; set; }
[Required]
//职务下面可能也有子角色,本表也可以使用递归表,描述更复杂的关系,一般可以不用
public int PID { get; set; }
//该职务的状态,公司的管理者通过控制角色状态来打开或者关闭当前角色的操作权限
public int Status { get; set; }
[Required,MinLength(),MaxLength()]
//职务权限名称
public string GroupName { get; set; }
//权限隶属于某个公司
public int WorkGroupID { get; set; }
[ForeignKey("WorkGroupID")]
public virtual WorkGroup WorkGroup { get; set; }
//一个权限下有多个职员
public virtual ICollection<UserBase> UserBase { get; set; }
}
}

UserBase
职员表,每个职员比如隶属于某个公司,当然他在某个公司下要拥有属于自己的角色,所以他也隶属于某个公司某个职务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using MvcDemo.Model.System; namespace MvcDemo.Model.User
{
public class UserBase
{
[Key]
//职员的唯一ID
public int ID { get; set; }
[Required]
[StringLength(, MinimumLength = , ErrorMessage = "*")]
//登录名
public string LoginName { get; set; }
[Required]
[StringLength(, MinimumLength = , ErrorMessage = "*")]
//密码
public string LoginPass { get; set; }
//状态,他是否通过本公司的验证
public int Status { get; set; } //一个用户隶属于某个公司
public int WorkGroupID { get; set; }
[ForeignKey("WorkGroupID")]
public virtual WorkGroup WorkGroup { get; set; } //一个职员隶属于某个权限
public int UserGroupID { get; set; }
[ForeignKey("UserGroupID")]
public virtual UserGroup UserGroup { get; set; }
}
}

编写数据上下文类,这样就会自动生成数据库了

    public class DbContextBase : DbContext
{
public DbSet<UserBase> UserBase { get; set; }
public DbSet<UserGroup> UserGroup { get; set; }
public DbSet<WorkGroup> WorkGroup { get; set; }
//public DbSet<AdminBase> AdminBase { get; set; }
//public DbSet<SysMenu> SysMenu { get;set;}
//public DbSet<SysOperation> SysOperation { get; set; } public DbContextBase()
: base("DBConn")
{
Database.CreateIfNotExists();
//此处是自动更新数据表,当模型改变的时候。如果需要加测试数据,用下面的DBInitializer,并在Global
//加入Database.SetInitializer<MvcDemo.DAL.DbContextBase>(new MvcDemo.DAL.DBInitializer()); //修改Model后,自动更新数据表
Database.SetInitializer<DbContextBase>(new DropCreateDatabaseIfModelChanges<DbContextBase>());
//this.Configuration.LazyLoadingEnabled = true; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约
}
}

此处附webconfig的链接字符串,本例直接用MS SQL,这样可以方便以后测试的时候观测具体执行的SQL语句是否是我们想要的!sql profiler

  <connectionStrings>
<add name="DBConn" connectionString="Data Source=(local);Initial Catalog=MvcDemoData;Persist Security Info=True;User ID=sa;Password=tommyheng" providerName="System.Data.SqlClient" />
</connectionStrings>

此时我们DEBUG,提示出错:

“/”应用程序中的服务器错误。


将 FOREIGN KEY 约束 'FK_dbo.UserGroup_dbo.WorkGroup_WorkGroupID' 引入表 'UserGroup' 可能会导致循环或多重级联路径。请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
无法创建约束。请参阅前面的错误消息。

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.Data.SqlClient.SqlException: 将 FOREIGN KEY 约束 'FK_dbo.UserGroup_dbo.WorkGroup_WorkGroupID' 引入表 'UserGroup' 可能会导致循环或多重级联路径。请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
无法创建约束。请参阅前面的错误消息。

源错误:

行 24:         public T Add(T entity)
行 25: {
行 26: context.Set<T>().Add(entity);
行 27: context.SaveChanges();
行 28: return entity;

源文件: f:\MVCWEB\MvcDemo.Web\MvcDemo.DAL\BaseRepository.cs    行: 26

第二次测试:标准的约定配置,主从表均加入描述,但不加自定义的外键:

========================================================

如主表加导航属性 public virtual ICollection<。。。>

从表加引入属性       public virtual 引用实体 实体{ get; set; }

注意:::这里木有任何自定义的外键,也就是说,我们让系统给我们自动生成外键,而不再自己指定外键!

代码如下!

WorkGroup

原样不变!!!!

UserGroup

职务角色表,每个职务角色都隶属于某个公司,每个职务下面都有N个职员一起共事
{为了简化篇幅,我们仅仅把需要修改的地方贴出来。注释掉下面几行,也就是去掉手写的外键}

//权限隶属于某个公司
//public int WorkGroupID { get; set; }
//[ForeignKey("WorkGroupID")]

UserBase
{注释掉下面几行,也就是去掉手写的外键}
职员表,每个职员比如隶属于某个公司,当然他在某个公司下要拥有属于自己的角色,所以他也隶属于某个公司某个职务

//一个用户隶属于某个公司
//public int WorkGroupID { get; set; }
//[ForeignKey("WorkGroupID")]
public virtual WorkGroup WorkGroup { get; set; } //一个职员隶属于某个权限
//public int UserGroupID { get; set; }
//[ForeignKey("UserGroupID")]
public virtual UserGroup UserGroup { get; set; }

完毕!!!

DEBUG测试!成功!说明罪魁祸首就是自己手动写的这个外键了!

附图:数据库表结构图!

第三次测试:非标准的约定配置,主或从表均加入描述,即,要么在主表加导航属性virtual ICollection,要么在从表加引用属性virtual 引用实体 实体:

========================================================

如主表加导航属性 public virtual ICollection<。。。>

或者

从表加引入属性       public virtual 引用实体 实体{ get; set; }

注意:::这里木有任何自定义的外键,也就是说,我们让系统给我们自动生成外键,而不再自己指定外键!

这里就不附代码了!测试结果,均通过!至于为啥自己加外键不行…… 我没继续研究。呵呵,有懂的,就告诉下吧!实现功能就好了!

在使用EF Code First开发时,遇到的“关系”问题,以及解决方法的更多相关文章

  1. 关于Angular2与蚂蚁的NG-ZOORO一同开发时[disabled]="true"动态绑定失效的解决方法

    在使用Angular2与蚂蚁的NG-ZOORO一同开发时,当我们的表单使用的是formControlName="value"时[disabled]="true" ...

  2. 利用SSH框架开发时遇到的各种Bug及解决方法

    .hibernate自动生成的配置文件 hibernate.cfg.xml 有时候是有问题的,会出现 org.hibernate.HibernateException: Could not parse ...

  3. Brophp框架开发时连接数据库读取UTF8乱码的解决(转)

    Brophp框架开发时连接数据库读取UTF8乱码的解决办法 (2012-09-15 10:41:22) 转载▼ 标签: 杂谈 it php 分类: 建站技术 Brophp框架开发时连接数据库读取UTF ...

  4. 记一次SpringBoot 开发中所遇到的坑和解决方法

    记一次SpringBoot 开发中所遇到的坑和解决方法 mybatis返回Integer为0,自动转型出现空指针异常 当我们使用Integer去接受数据库中表的数据,如果返回的数据中为0,那么Inte ...

  5. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  6. 安装CentOS、Linux系统时,GPT分区不能引导的解决方法

    安装系统:CentOS 5.9_64bit时,分区后, 提示如下错误. 解决方法: 1.按ctrl+alt+F2 进入命令行 2.先查看分区 sh #fdisk -l    以下假设分区是/dev/s ...

  7. 百度编辑器ueditor 异步加载时,初始化没办法赋值bug解决方法

    百度编辑器ueditor 异步加载时,初始化没办法赋值bug解决方法 金刚 前端 ueditor 初始化 因项目中使用了百度编辑器——ueditor.整体来说性能还不错. 发现问题 我在做一个编辑页面 ...

  8. Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法

    Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法 2014-03-27 11:44:46|  分类: Easy UI|举报|字号 订阅     可以使用$.parser.pa ...

  9. 加载驱动模块时Device or resource busy的解决方法

    加载驱动模块时Device or resource busy的解决方法 加载驱动模块时Device or resource busy的解决方法 insmod或modprobe驱动模块时Device o ...

随机推荐

  1. JAVA 8 Lambda表达式-Lambda Expressions

    Lambda表达式介绍 Lambda表达式是在java规范提案JSR 335中定义的,Java 8 中引入了Lambda表达式,并被认为是Java 8最大的新特性,Lambda表达式促进了函数式编程, ...

  2. JAVA中获取路径

    内容来自于snannan_268 关键字: java中获取路径 JAVA中获取路径: 1.jsp中取得路径:   以工程名为TEST为例: (1)得到包含工程名的当前页面全路径:request.get ...

  3. CDC 2013 北京站手记

    受搜狐畅游的邀请,这次能够有机会参与2013中国开发者大会北京站的活动. 本次大会的主题是“游戏”和“移动”,因此上午的峰会安排了5个主讲,分别就搜索.云存储服务器.游戏媒体.移动应用和游戏渠道等多方 ...

  4. mysql Lock wait timeout exceeded; try restarting transaction

    查看innodb的事务表INNODB_TRX,看下里面是否有正在锁定的事务线程,看看ID是否在show full processlist里面的sleep线程中,如果是,就证明这个线程事务一直没有com ...

  5. mysql源码解读之事务提交过程(一)

    mysql是一种关系型数据库,关系型数据库一个重要的特性就是支持事务,这是区别于no-sql产品的一个核心特性.当然了,no-sql产品支持键值查询,不能支持sql语句,这也是一个区别.今天主要讨论下 ...

  6. Spring 整体架构

    1. Core Container:核心容器(core.Beans.Context.Expression Language   Core.Beans框架基础构成,提供IOC.依赖注入特性.BeanFa ...

  7. IntelliJ IDEA14.1中java项目Maven中没有配置JDK时的问题

    在IntelliJ IDEA 14.1中使用在java项目中使用Maven时当没有在Maven中配置JDK编译版本.源码版本时,IDEA将默认的编译版本.源码版本设置为jdk5. 在IDEA中Lang ...

  8. perl多线程理解

    Thread:在使用多线程处理比较大的数据量的扫描,遇到读写文件可能死锁的问题. Perl 线程的生命周期 1.使用 threads 包的 create() 方法: use threads; sub ...

  9. linux监控命令nc用法

    一.nc命令检测端口的用法 # nc -v -w 10 %IP% -z %PORT% -v 显示指令执行过程. -w <超时秒数> 设置等待连线的时间. -u 表示使用UDP协议 -z 使 ...

  10. NOIP2005过河[DP 状态压缩]

    题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...