【高分邀请】ef code first 中间表设计

wilson2017 2020-05-28 11:41:03
情景: 有张会员表, Member 公司表: Company

业务逻辑:

会员只能关联一家公司,所以是一对一
但公司可以允许多个会员同时关联一家公司, 所以从公司的角度,是可以多对一

现在的方案是想设计一张中间表来进行关联,请问下这个中间表应该怎么设计了?
现在是这样设计,但执行 migrations 的时候报错了

public class MemberCompany
{
public Guid CompanyId { get; set; }
public Guid MemberId { get; set; }
public virtual Member Member { get; set; }
public virtual ICollection<Company> Company { get; set; }
}

错误如下:

Unable to determine the relationship represented by navigation property 'Company.MemberCompanies' of type 'ICollection<MemberCompany>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
...全文
681 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
数据库,添加外键约束了吗
joe_free 2020-05-29
  • 打赏
  • 举报
回复
多谢大佬分享
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
虽然你认为是一对多。 但是对于MemberCompany 的一个实例来说,他就是一行数据。 那么他只会有一个company和一个member 而你认为的一对多,应该是Member对象中添加Company、 以及Company对象增加 ICollection<Member> public class MemberCompany { public Guid CompanyId { get; set; } public Guid MemberId { get; set; } public virtual Member Member { get; set; } public virtual ICollection<Company> Company { get; set; } } 改成 public class MemberCompany { public Guid CompanyId { get; set; } public Guid MemberId { get; set; } [ForeignKey("MemberId")] public virtual Member Member { get; set; } [ForeignKey("CompanyId")] public virtual Company Company { get; set; } }
wilson2017 2020-05-28
  • 打赏
  • 举报
回复
补充下会员和公司的表结构 public class Member : ModelBase { [MaxLength(36)] public string WechatUnionId { get; set; } [MaxLength(36)] public string WechatOpenId { get; set; } [MaxLength(50)] public string NickName { get; set; } [MaxLength(100)] public string Avatar { get; set; } public Gender Gender { get; set; } public int? Nation { get; set; } public int? Province { get; set; } public int? City { get; set; } [MaxLength(50)] public string Address { get; set; } [MaxLength(50)] public string Job { get; set; } [Description("来源"), MaxLength(50)] public string Source { get; set; } [Description("会员独立Key")] public Guid MemberKey { get; set; } public MemberType MemberType { get; set; } public bool IsAuth { get; set; } public Guid SysUserAccountId { get; set; } [ForeignKey("SysUserAccountId")] public virtual SysUserAccount SysUserAccounts { get; set; } public virtual ICollection<MemberCompany> MemberCompanies { get; set; } public virtual ICollection<Article> Articles { get; set; } public virtual ICollection<ArticleReply> ArticleReplies { get; set; } public virtual ICollection<Recruitment> Recruitments { get; set; } public virtual ICollection<Wholesale> Wholesales { get; set; } } public class Company : ModelBase { [MaxLength(50)] public string Name { get; set; } public string Logo { get; set; } public string Contact { get; set; } public string Description { get; set; } public string Address { get; set; } public string Website { get; set; } public string FullName { get; set; } public string Legal { get; set; } public decimal RegisteredCapital { get; set; } public DateTime RegisterDate { get; set; } public string CreditNo { get; set; } public string BusinessScope { get; set; } public virtual ICollection<MemberCompany> MemberCompanies { get; set; } }
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
前面说过了,你通过dbfirst方式,直接生成edmx。 然后把dbcontext和class拿出来,就可以作为codefirst了。
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
算了,我直接贴代码给你吧。 Company
public partial class Company
    {
        public Company()
        {
            this.MemberCompany = new HashSet<MemberCompany>();
        }
    
        public int id { get; set; }
        public string name { get; set; }
    
        public virtual ICollection<MemberCompany> MemberCompany { get; set; }
    }
Member
public partial class Member
    {
       
        public Member()
        {
            this.MemberCompany = new HashSet<MemberCompany>();
        }
    
        public int id { get; set; }
        public string name { get; set; }
    
        public virtual ICollection<MemberCompany> MemberCompany { get; set; }
    }
MemberCompany

public int id{get;set;}
public int mid{get;set;}
public int cid{get;set;}

[ForeignKey("mid")]
public Member Member{get;set;}
[ForeignKey("cid")]
public Company Company{get;set;}
wilson2017 2020-05-28
  • 打赏
  • 举报
回复
这样需要在 Member 和 Company 做调整?
wilson2017 2020-05-28
  • 打赏
  • 举报
回复
引用 17 楼 正怒月神 的回复:
[quote=引用 16 楼 wilson2017 的回复:] [quote=引用 14 楼 正怒月神 的回复:] [quote=引用 13 楼 wilson2017 的回复:] [quote=引用 12 楼 正怒月神 的回复:] 而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
这样执行 migration 的时候会报这个错 Error: 'FK_Members_Companies_CompanyId' 不是约束。 members 或者 company 实体 不需要做调整吗?[/quote] 你要增加foreginKey来指定这个对象的关联外键字段。[/quote] 这样不就会变成是强关联了? 因为会员不一定是有关联公司的,加了这个外键字段,到时候插入会员数据的时候不是得强行要求加入公司信息?[/quote] 你还是没有搞清楚。 这个关联表。只记录真实存在的关联数据。 假设用户UA,UB。公司CA。 现在UA关联CA,那么就会添加关联数据到MemberCompany。 假设UB没有关联公司,那么也根本不需要添加到MemberCompany。 退一步来说,假设你一定要添加数据,那么UB添加到MemberCompany时,company也可以是个null[/quote] 举个实例: 比如会员表实体 public class Member { public Guid Id { get; set; } public string NickName { get; set;} } 公司表实体: public class Company { public Guid Id { get; set; } public string CompanyName { get; set; } } 中间表实体: public class MemberCompany { public Guid Id{get;set;} [ForeignKey("MemberId")] public Guid MemberId { get; set; } [ForeignKey("CompanyId")] public Guid CompanyId { get; set; } }
  • 打赏
  • 举报
回复
你用left 就可以查 b.bid为空的数据了 这就不是强关联了撒
  • 打赏
  • 举报
回复
select a.*,b.* from a,b,c where a.aid = c.aid and b.bid=c.bid sql写出来看得懂不嘛。。。没用left
  • 打赏
  • 举报
回复
卧槽,用户有公司就加到中间表去, 没有就不加就这么难理解? 你不管他有没得 你把表建出来,你写left join 去查, 查出来结果不对算我的, 赶快结帖 说锤子。。。
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
其实这个和用户权限是一个道理。 用户权限, 假设有 用户表,权限表,用户权限表 用户表,记录用户, 权限表,记录各种权限。 用户权限表,记录他们的关系。 一个用户A没有权限,那么需要在用户权限表添加数据吗?明显是不需要的。 因为用户权限表,只记录你给用户添加了权限的数据。
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
这不是什么强关联的问题。 中间表,只是建立两个表的数据是否有联系。 没有联系的数据,也不需要添加进去。
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
引用 16 楼 wilson2017 的回复:
[quote=引用 14 楼 正怒月神 的回复:] [quote=引用 13 楼 wilson2017 的回复:] [quote=引用 12 楼 正怒月神 的回复:] 而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
这样执行 migration 的时候会报这个错 Error: 'FK_Members_Companies_CompanyId' 不是约束。 members 或者 company 实体 不需要做调整吗?[/quote] 你要增加foreginKey来指定这个对象的关联外键字段。[/quote] 这样不就会变成是强关联了? 因为会员不一定是有关联公司的,加了这个外键字段,到时候插入会员数据的时候不是得强行要求加入公司信息?[/quote] 你还是没有搞清楚。 这个关联表。只记录真实存在的关联数据。 假设用户UA,UB。公司CA。 现在UA关联CA,那么就会添加关联数据到MemberCompany。 假设UB没有关联公司,那么也根本不需要添加到MemberCompany。 退一步来说,假设你一定要添加数据,那么UB添加到MemberCompany时,company也可以是个null
wilson2017 2020-05-28
  • 打赏
  • 举报
回复
引用 14 楼 正怒月神 的回复:
[quote=引用 13 楼 wilson2017 的回复:] [quote=引用 12 楼 正怒月神 的回复:] 而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
这样执行 migration 的时候会报这个错 Error: 'FK_Members_Companies_CompanyId' 不是约束。 members 或者 company 实体 不需要做调整吗?[/quote] 你要增加foreginKey来指定这个对象的关联外键字段。[/quote] 这样不就会变成是强关联了? 因为会员不一定是有关联公司的,加了这个外键字段,到时候插入会员数据的时候不是得强行要求加入公司信息?
  • 打赏
  • 举报
回复
不是呀, 设计表不就是俩表主键么 MemberID CompanyID , 俩字段就完了呀, 该表把这俩字段设置联合主键即可,你想怎么玩怎么玩多好
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
引用 13 楼 wilson2017 的回复:
[quote=引用 12 楼 正怒月神 的回复:] 而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
这样执行 migration 的时候会报这个错 Error: 'FK_Members_Companies_CompanyId' 不是约束。 members 或者 company 实体 不需要做调整吗?[/quote] 你要增加foreginKey来指定这个对象的关联外键字段。
wilson2017 2020-05-28
  • 打赏
  • 举报
回复
引用 12 楼 正怒月神 的回复:
而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
这样执行 migration 的时候会报这个错 Error: 'FK_Members_Companies_CompanyId' 不是约束。 members 或者 company 实体 不需要做调整吗?
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
而如果要查某公司下有多少会员, 也就是 var q = MemberCompany.where(x=>x.Company==xxxx)
正怒月神 版主 2020-05-28
  • 打赏
  • 举报
回复
var q = MemberCompany.firstOrDefault(x=>x.会员id==xxxx) if q==null就代表了没有关联公司。
加载更多回复(8)

62,039

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧