EF循环依赖

1.项目场景:

项目场景:

1.本项目采用了EF架构来建立实体与实体之间的关联关系。

2.一个部门对应多个摄像头

1.部门实体:

 public partial class DepartmentEntity		//部门实体
    { 
        public int Id { get; set; }
        public virtual ICollection< CameraEntity> lstCamera { get; set; }
        /// <summary>
        /// 部门编码
        /// </summary>
        public string DeptCode { get; set; }
        /// <summary>
        /// 部门名称
        /// </summary>
        public string DeptName { get; set; }
        /// <summary>
        /// 经度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lon { get; set; }
        /// <summary>
        /// 纬度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lat { get; set; }
    }

2.摄像头实体:

 public class CameraEntity		//摄像头实体
    {

        public int Id { get; set; }
        /// <summary>
        /// 摄像头名称
        /// </summary> 
        public string CameraName { get; set; }
        /// <summary>
        /// 所属部门Id
        /// </summary>
        public int? DeptId { get; set; }
        public virtual DepartmentEntity dept { get; set; }
        /// <summary>
        /// 经度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lng { get; set; }
        /// <summary>
        /// 纬度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lat { get; set; }

    }  

1.部门 mapping:

public class DepartmentEntityMapping : DataEntityTypeConfiguration<DepartmentEntity>
    {
        public DepartmentEntityMapping()
        {
         	//部门表
            ToTable("Department");		
            HasKey(t => t.Id);
            //一对多
            HasMany(x => x.lstCamera).WithOptional(z => z.dept).HasForeignKey(y=>y.DeptId);	
        }
    }

2.摄像头 mapping:

 public class CameraEntityMapping : DataEntityTypeConfiguration<CameraEntity>
    {
        public CameraEntityMapping()
        {
        	//AssetCameraInfo为数据库表名
            ToTable("AssetCameraInfo");		
            HasKey(t => t.Id);
            //一对多
            HasOptional(x => x.dept).WithMany().HasForeignKey(x => x.DeptId);	
        }
    }

1.controller层 – 调用该接口报错 – error:出现循环调用

 		/// <summary>
        /// 查摄像头集合
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [Route("TmpTest")]
        [HttpPost]
        [AllowAnonymous]
        public IHttpActionResult TmpTest([FromBody] QuerCameraInfo model)
        {
            TipsModel<List<CameraEntity>> tips = new TipsModel<List<CameraEntity>>(false);
            var lst = new AssetCameraInfoServiceV2().GetList(model);
            tips.SetResult(true, lst, "success");
            return Json(tips);
        }

2.Service层

public partial class AssetCameraInfoServiceV2
    {
        readonly Repository<CameraEntity> dao = new Repository<CameraEntity>();
 
        private IQueryable<BMS_D_AssetCameraInfoEntity> QueryCmd(QuerCameraInfo where)
        {
            var query = dao.Table;
            query = query.Where(x => x.DeleteState == 0);
            if (!where.CameraName.IsEmpty())
                query = query.Where(x => x.CameraName.Contains(where.CameraName));
            if (!where.DeptId.IsEmpty())
                query = query.Where(x => x.DeptId == where.DeptId);
            return query;
        }
        
        public List<CameraEntity> GetList(QuerCameraInfo where)
        {
            var temp = QueryCmd(where);
            return temp.ToList();
        }
	}

3.model 传参QuerCameraInfo

 public class QuerCameraInfo
    {
        public int Id { get; set; }
        /// <summary>
        /// 摄像头名称
        /// </summary> 
        public string CameraName { get; set; }
        /// <summary>
        /// 摄像头编码
        /// </summary>
        public string CameraCode { get; set; }
        /// <summary>
        /// 所属部门Id
        /// </summary>
        public int? DeptId { get; set; }
        public virtual DepartmentEntity dept { get; set; }
    }

2.报错内容

1.调用 controller层 的接口 TmpTest 报错如下:

"StatusCode": 408,
"OperateTime": "2022-09-08T14:56:58.9725345+08:00",
"Message": "2022年9月8日\tSelf referencing loop detected with type 'System.Data.Entity.DynamicProxies.BMS_D_AssetCameraInf_6940526873A10F06EF9B905552C9F9854FEA9BBA8CFBCCDBD1E36BF810A687E9'. Path 'ReturnValue[7].dept.lstCamera'.\t\n"

3.原因分析:

通过 GetList() 获得的 lst 集合中,每个相机实体中都有一个部门实体,每个部门中又有相机集合,故而出现死循环。


4.解决方案:

将 lst 转换为 model

1.controller层 – 分页查询camera

		/// <summary>
        /// 查询摄像头信息(分页)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [Route("GetListCameraInfo")]
        [HttpPost]
        [AllowAnonymous]
        public IHttpActionResult GetListCameraInfo([JsonBinder] ElGrid grid)
        {
            TipsModel<ElGrid> tips = new TipsModel<ElGrid>(false);
            var where = grid.CreatePageBase<QuerCameraInfo>();
            AssetCameraInfoServiceV2 serveice = new AssetCameraInfoServiceV2();
            //转model
            tips.ReturnValue = grid.SetData(serveice.GetPageList(where), x => x.Select(y => y.ToModel()));
            //转model,model比entity多一个deptName字段
            tips.ReturnValue = grid.SetData(serveice.GetPageList(where), x => x.Select(y => y.ToInfoModel()));
            tips.IsSuccess = true;
            return Json(tips);
        }

5.补充信息

每个 AutoMapper 都对应一个 Profile

1.CameraInfoModel

public class CameraInfoModel
    {
        public int Id { get; set; }
        /// <summary>
        /// 摄像头名称
        /// </summary> 
        public string CameraName { get; set; }
        /// <summary>
        /// 所属部门Id
        /// </summary>
        public int? DeptId { get; set; }
        /// <summary>
        /// 部门名称
        /// </summary>
        public string DeptName { get; set; }
        /// <summary>
        /// 经度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lng { get; set; }
        /// <summary>
        /// 纬度
        /// </summary>
        [DecimalPrecision(16, 8)]
        public decimal? Lat { get; set; }
   }
  1. AutoMapperExcetions 中的 CameraMapper
 #region	摄像头信息表 CameraEntity
        public static CameraInfoModel ToInfoModel(this CameraEntity entity)
        {
            return entity.MapTo<CameraEntity, CameraInfoModel>();
        }
        public static CameraEntity ToInfoEntity(this CameraInfoModel model)
        {
            return model.MapTo<CameraInfoModel, CameraEntity>();
        }
#endregion

3.CameraProfile.cs
将 entity 转换为 CameraInfoModel, 其中根据 deptId 获取部门名称放在 CameraInfoModel 中进行输出.

 private void CameraProfile() {
            CreateMap<CameraInfoModel, CameraEntity>();
            CreateMap<CameraEntity, CameraInfoModel>()
                .ForMember(x => x.DeptName, y => y.MapFrom(z => z.dept == null ? "" : z.dept.DeptName));
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值