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. 对js中Function的浅见

    它到底是什么 String Array 都是系统内置对象(已经定义好,可以直接使用)当然,这货也是一样,我们之前定义的函数,其实就是一个这货的实例. 在JS中,所有的对象都是由函数实现的,函数的数据类 ...

  2. js中的三个编码函数:escape,encodeURI,encodeURIComponent

    1. eacape(): 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / .其他所有的字符都会被转义序列替换.其它情况下es ...

  3. MySQL的Explain命令

    Explain命令是查看查询优化器如何决定执行查询的主要办法.   调用 EXPLAIN   要使用EXPLAIN,只需在查询中的SELECT关键字之前增加EXPLAIN.MySQL会在查询上设置一个 ...

  4. Linux下的压缩zip,解压缩unzip命令详解及实例

    实例:压缩服务器上当前目录的内容为xxx.zip文件 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip filename.zip ====================== ...

  5. 关于TreeView的选中事件

    在使用TreeView的选中事件时,发现,SelectAfter在第一次选中时触发,你再次点击时这个事件并不能引发它.所以找了找,发现有另两种解决办法. 最好的就是使用:NodeMouseClick, ...

  6. HTTP 请求报文 响应报文

    引言 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为了提供一种发 ...

  7. Lucene 4.x Spellcheck使用说明

    Spellcheck是Lucene新版本的功能,在介绍spellcheck之前,我们需要弄清楚Spellcheck支持几种数据源.Spellcheck构造函数需要传入Dictionary接口: pac ...

  8. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  9. [转]阿里云配置mysql远程连接

    默认是不能用客户端远程连接的,阿里云提供的help.docx里面做了设置说明,mysql密码默认存放在/alidata/account.log 首先登录: mysql -u root -h local ...

  10. spring mvc参数绑定

    spring绑定参数的过程 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上.springmvc中,接收页面提交的数据是通过方法形参来接 ...