深入MVC框架--EF中的导航属性优势与弊端(一)

Web开发框架中EF中提供了一个新鲜的东东--导航属性,某个模型的外键表数据可以自动加载,这样做确实提高了代码效率,那有什么弊端吗
概述
模型
描述
问题
解决
概述

在关系数据库中,表之间的关系(也称为关联)是通过外键定义的。外键 (FK) 是用于在两个表的数据之间建立并强制链接的一列或列组合。有三种关系类型:一对一、一对多和多对多。在一对多关系中,外键是在表示关系多端的表上定义的。多对多关系涉及定义第三个表(也称为接合或联接表),主键由来自两个相关表的外键组成。在一对一关系中,主键还用作外键,两个表都没有单独的外键列。
在实体框架中,实体可以通过关联(关系)与其他实体相关。每个关系都包含两端,它们描述关系中两个实体的实体类型以及类型的多重性(一、零或一、多)。关系可由引用约束控制,该引用约束描述了关系中的哪端为 Role 以及哪端为 Dependent,哪端为 Role 以及哪端为 Function
导航属性为在两个实体类型间导航关联提供了一种方式。针对对象参与到其中的每个关系,各对象均可以具有导航属性。使用导航属性,可以在两个方向上导航和管理关系,返回引用对象(如果多重性为一或者零或一)或集合(如果多重性为多)。也可以选择使用单向导航,在这种情况下,只对参与关系的一种而不是两种类型定义导航属性。

模型
public partial class SystemRole : BaseEntity
{
    public override int Id { get; set; }
    public string RoleName { get; set; }
    /// <summary>
    /// 所属的部门ID
    /// </summary>
    public int? DepartmentID { get; set; }
    [NotMapped]
    public Department Department { get; set; }
    public string DepartmentName
    {
        get
        {
            if (Department != null)
                return Department.DepartmentName;
            return "";
        }
    }
    public bool IsEnabled { get; set; }
    /// <summary>
    /// 该角色具备的功能操作集合。
    /// </summary>
    
    public IList<SystemFunction> Functions { get; set; }
}
/// <summary>
/// SystemRole和SystemFunction的关联表
/// </summary>
public class SystemRoleFunction : BaseEntity
{
       
    public override int Id { get; set; }
    public int RoleID { get; set; }
       
    public SystemRole Role { get; set; }
    public int FunctionID { get; set; }
      
    public SystemFunction Function { get; set; }
}
public class SystemFunction 
{
    public  int Id { get; set; }
    public string FunctionCode { get; set; }
    public string FunctionName { get; set; }
    /// <summary>
    /// 定义的分组名称
    /// </summary>
    public string GroupName { get; set; }
    public int DisplayOrder { get; set; }
}
public IList<SystemRole> GetAllRoles(bool enabledOnly = true, bool loadingFunctions = false)
{
    var queryable = this._roleRepository.TableNoTracking.Include(t => t.Department);
    if (enabledOnly)
        queryable = queryable.Where(t => t.IsEnabled == true);
    var list = queryable.ToList();
    if (loadingFunctions)
    {
        list.ForEach(r =>
        {
            var roleFuncDbSet = this._dbContext.Set<SystemRoleFunction>();
            var funcDbSet = this._dbContext.Set<SystemFunction>();
            var funcs = from re in roleFuncDbSet join f in funcDbSet on re.FunctionID equals f.Id where re.RoleID == r.Id select f;
                   
            r.Functions = funcs.ToList();
        });
    }
    return list;
}
描述

模型关系:SystemRole 和SystemFuction多对多关系,通过SystemRoleFunction关联,关联字段RoleID、FunctionID;SystemRole与Department一对多关系,关联字段DepartmentID。
前提:在Web开发框架中我们并没有采用EF Fluent API使用EntityTypeConfiguration分文件配置Model映射关系,我们只在DBContext中为模型添加了DbSet

问题

我们跑下代码,看下是否配置正确。发现以下两个错误:

错误1
错误2
解决

我们可以看到,都是两个外键惹的祸, 都是需要加载外键相关表的数据,但是都没有加载出来。我们看第一个的现象“SystemRoledId”无效, 从linq语句我们可以看出两个关联模型:SystemRoleFunction和SystemFunction , SystemFunction与SystemRole通过SystemRoleFunctiond的RoleID、FunctionID关联,这个错误说明模型中某个导航属性加载时没有找到相关的外键, 我们来瞧瞧是哪个模型,看哪个数据模型用了导航属性但是没有相关外键的,我们在上面的三个模型里找找看,哦,原来是SystemRole的这段public IList<SystemFunction> Functions { get; set; },Oh,My God,原来在这儿, 明白了,那么我们怎么解决呢,我们的外键是设在SystemRoleFunction这个关联表中,看来在这而添加外键不现实,看来我们只能取消这个导航属性了,把他作为一个数据集,由代码来给这个数据集赋值,在该代码上加上[NotMapped]的特性,运行后结果正常

错误解决1

好了,来看下我们的第二个错误现象,我也有红色字体注明了加上NotMapped后出现的错误,加上后我们就找不到外键关联的导航属性,故而报错,更深层次大家可以看EF相关源码是最直观的思考方式。我们去掉该特性后可以看到结果已经正常。

本站文章除注明转载外,均为本站原创或翻译,欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,共创和谐网络环境。
转载请注明:文章转载自:华晨软件-云微开发平台 » 深入MVC框架--EF中的导航属性优势与弊端(一)
本文标题:深入MVC框架--EF中的导航属性优势与弊端(一)
本文地址:https://www.hocode.com/OrgTec/DB/0003.html

相关文章: 初识Web框架--C# Linq技术基础

电话
电话 18718672256

微信
二维码