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. Extjs插入图片

    Extjs并没有提供直接的组件来显示图片.网上通过设置textfield的InputType为Image然后再修改dom对象来实现,其实 image的属性值并没有包含在Extjs的官方文档当中.可以通 ...

  2. @OneToMany---ManyToOne

    http://blog.csdn.net/gebitan505/article/details/22619175 一对多,字段只是在多的一方,SQL数据库和JAVA中不同 SQL数据库表: 多的一方: ...

  3. Java Se :线性表

    Java的集合框架分为两个系列,Collection和Map系列.在大学期间,学习数据结构时,好像学习了线性表.非线性表.树,哎,都给忘了.其实,在Collection系列内部又可以分为线性表.集合两 ...

  4. SQL 扩展事件

    在本篇,我通过使用新建“Session ”对话框来创建新的扩展事件会话.定义一个自己的扩展事件,动作和谓词,并且发布一个以收集事件数据为目的的会话. 首先从UI开始 在SQLServer2008R2以 ...

  5. TSQL--临时表和表变量

    1. 临时表适用数据量较大的情况,因为临时表可以建立索引 2. 表变量适用于数据较小的情况,表变量只能在定义时创建约束(PRIMARY KEY/UNIQUE)从而间接建立索引 3. 临时表是事务性的, ...

  6. Office——EXCEL 显示 隐藏 Ribbon 调用宏

    ==================================声明================================== 本文版权归作者所有 未经作者授权 请勿转载 保留法律追究的 ...

  7. iOS UIButton 图片文字上下垂直布局 解决方案

    实现如图所示效果: 这是一个UIButton,需要改变image和title相对位置. 解决如下: //设置文字偏移:向下偏移图片高度+向左偏移图片宽度 (偏移量是根据[图片]大小来的,这点是关键)b ...

  8. Linux dd

    一.简介 二.实例 1)复制二进制文件指定章节 iflag=skip_bytes bs= count= of=test 2)修改二进制文件指定章节 oflag=seek_bytes bs= count ...

  9. webstorm10 注册码

    亲测注册码适合WebStorm 10的所有版本.WebStorm 是jetbrains公司旗下一款JavaScript 开发工具.被广大中国JS开发者誉为“Web前端开发神器”.“最强大的HTML5编 ...

  10. 我的STL学习之路

    说起STL(标准模板库),相信了解C++的都不会陌生吧^_^.LZ是从大三开始学习C++(ps:不是科班出身),并慢慢接触使用STL的,在学校中使用STL比较多的情况是写数据结构代码,使用STL实现数 ...