EF - 5组合键与其他实体有许多关系

本文关键字:实体 许多 关系 其他 组合 EF | 更新日期: 2023-09-27 18:09:35

在下面的代码中,我首先使用EF代码来设置我的数据库模型。

casecomcommunication实体有一个包含Id列的组合键。如果我让EF完成这项工作,它将尝试使用此列作为到另一个实体的FK,尽管有Many()规范:

HasRequired(x => x.Case).WithMany(x => x.Communications);
HasOptional(x => x.FirstReadBy).WithMany();

为了得到一个正确的模型,我必须明确地设置FK(请阅读代码中的注释)。

HasRequired(x => x.Case).WithMany(x => x.Communications).Map(x => x.MapKey("Case_Id"));
HasOptional(x => x.FirstReadBy).WithMany().Map(x => x.MapKey("FirstReadBy_Id"));

如果我不使用组合键,那么不使用Map()也能正常工作。

我的问题是:EF的逻辑是什么?或者换句话说,我错过了什么?

using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Data.Objects.SqlClient;
using System.ComponentModel.DataAnnotations.Schema;
namespace testef {
    //Model
    public partial class Case {
        public Case() {                
            Communications = new List<CaseCommunication>();
        }
        public Int32 Id { get; set; }
        public virtual ICollection<CaseCommunication> Communications { get; set; }
    }
    public class CaseCommunication  {
        public String CComType { get; set; }
        public Int32 Id { get; set; }
        public virtual Case Case { get; set; }
        public virtual User FirstReadBy { get; set; }
    }
    public class User {
        public Int32 Id { get; set; }
    }
    //Configuration for CObj
    public class UserEFCFConfiguration : EntityTypeConfiguration<User> {
        public UserEFCFConfiguration()
            : base() {
            ToTable("Users", "dbo");
            HasKey(x => x.Id);
            Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }
    public class CaseEFCFConfiguration : EntityTypeConfiguration<Case> {
        public CaseEFCFConfiguration()
            : base() {
            ToTable("Cases", "dbo");
            HasKey(x => x.Id);
            Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);   
        }
    }
    public class CaseCommunicationEFCFConfiguration : EntityTypeConfiguration<CaseCommunication> {
        public CaseCommunicationEFCFConfiguration()
            : base() {
            ToTable("VCaseCommunications", "dbo");
            Property(x => x.CComType).HasColumnType("char").HasMaxLength(2);
            HasKey(x => new { x.CComType, x.Id });
            // OK
            HasRequired(x => x.Case).WithMany(x => x.Communications).Map(x => x.MapKey("Case_Id"));
            HasOptional(x => x.FirstReadBy).WithMany().Map(x => x.MapKey("FirstReadBy_Id"));
            // KO
            //HasRequired(x => x.Case).WithMany(x => x.Communications);
            //HasOptional(x => x.FirstReadBy).WithMany()
            //EF tries to use the x.Id as FK for both Case and FirstReadBy
            //For FirstReadBy this leads to a Model error as x.Id is not nullable
            //But in each case I can't understand how EF expect to give the many relation by using a part of the PK as FK
            // OK
            //HasKey(x => x.Id);
            //HasRequired(x => x.Case).WithMany(x => x.Communications);
            //HasOptional(x => x.FirstReadBy).WithMany()
        }
    }
    public class TestEFContext : DbContext {
        public IDbSet<Case> Cases { get; set; }
        public TestEFContext(String cs)
            : base(cs) {
            Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.Add(new UserEFCFConfiguration());
            modelBuilder.Configurations.Add(new CaseEFCFConfiguration());
            modelBuilder.Configurations.Add(new CaseCommunicationEFCFConfiguration());
        }
    }
    class Program {
        static void Main(String[] args) {
            String cs = @"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";                
            using (TestEFContext c = new TestEFContext(cs)) {
                Console.WriteLine(c.Cases.Count());
            }                                                                
        }
    }
}

EF - 5组合键与其他实体有许多关系

事实上,这似乎是EF的默认行为:如果链接实体键的一部分与引用实体PK具有相同的名称,那么这个命名的属性被用作FK。