实体框架中的一对一或零关系,两个实体都有自己的PK

时间:2016-08-31 15:25:28

标签: c# entity-framework

我试图在实体框架中创建一对一或零关系,并且两个实体都有自己的PK但我无法

public class EmployeeBank
{
        [Key]
        public int Id {get;set;}
        public Name {get;set;}
        public virtual EmployeePaymentMethod EmployeePaymentMethod { get; set; }
}

public class EmployeePaymentMethod
{
        [Key]
        public int Id {get;set;}
        public virtual EmployeeBank EmployeeBank {get;set;}
}

 public class EmployeeBankMapping : EntityTypeConfiguration<EmployeeBank>
 {
        public EmployeeBankMapping()
        {
           this.HasRequired(z => z.EmployeePaymentMethod)
                .WithOptional(zz => zz.EmployeeBank)
                .Map(zzz => zzz.MapKey("EmployeePaymentMethodId"));
        }
 }

如果实现上面的代码,我发现在数据库中创建了一对多的关系。 我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:1)

此处正在使用DataAnnotations

public class EmployeeBank
{
        public int Id {get;set;}

        public string Name {get;set;}

        public virtual EmployeePaymentMethod EmployeePaymentMethod { get; set; }
}

public class EmployeePaymentMethod
{
        [Key, ForeignKey("EmployeeBank ")]
        public override int Id {get;set;}

        public virtual EmployeeBank EmployeeBank {get;set;}
}

此处正在使用Fluent API

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<EmployeeBank>()
       .HasOptional(e => e. EmployeePaymentMethod) // Mark EmployeePaymentMethod property optional in EmployeeBank entity
       .WithRequired(b => b. EmployeeBank); // mark EmployeeBank property as required in EmployeePaymentMethod entity. Cannot save EmployeePaymentMethod without EmployeeBank

}

答案 1 :(得分:0)

您可以使用此解决方案:

public class EmployeeContext : DbContext
{
    public DbSet<EmployeeBank> EmployeeBanks { get; set; }
    public DbSet<EmployeePaymentMethod> EmployeePaymentMethods { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EmployeeBank>()
            .HasMany(e => e.DoNotUseMeSir)
            .WithMany(b => b.DoNotUseMeSir)
            .Map(mc => mc.ToTable("BankToPaymentMethods")
            .MapLeftKey("EmployeeBankId")
            .MapRightKey("EmployeePaymentMethodId"));
    }
}

public class EmployeeBank
{
    public EmployeeBank()
    {
        DoNotUseMeSir = new List<EmployeePaymentMethod>();
    }

    public int EmployeeBankId { get; set; }
    public string Name {get;set;}

    [NotMapped]
    public EmployeePaymentMethod EmployeePaymentMethod
    {
        get { return DoNotUseMeSir.FirstOrDefault(); }
        set
        {
            DoNotUseMeSir.Clear();
            DoNotUseMeSir.Add(value);
        }
    }

    public virtual ICollection<EmployeePaymentMethod> DoNotUseMeSir { get; set; }
}

public class EmployeePaymentMethod
{
    public EmployeePaymentMethod()
    {
        DoNotUseMeSir = new List<EmployeeBank>();
    }

    public int EmployeePaymentMethodId { get; set; }

    [NotMapped]
    public EmployeeBank EmployeeBank
    {
        get { return DoNotUseMeSir.FirstOrDefault(); }
        set
        {
            DoNotUseMeSir.Clear();
            DoNotUseMeSir.Add(value);
        }
    }

    public virtual ICollection<EmployeeBank> DoNotUseMeSir { get; set; }
}

public class EmployeeDatabaseInitialiser : CreateDatabaseIfNotExists<EmployeeContext>
{
    protected override void Seed(EmployeeContext context)
    {
        base.Seed(context);

        var employeeBankIdUc =
            "ALTER TABLE dbo.BankToPaymentMethods ADD CONSTRAINT uq_BankToPaymentMethods_EmployeeBankId UNIQUE(EmployeeBankId)";
        context.Database.ExecuteSqlCommand(employeeBankIdUc);

        var employeePaymentMethodIdUc =
            "ALTER TABLE dbo.BankToPaymentMethods ADD CONSTRAINT uq_BankToPaymentMethods_EmployeePaymentMethodId UNIQUE(EmployeePaymentMethodId)";
        context.Database.ExecuteSqlCommand(employeePaymentMethodIdUc);
    }
}

然后简单地使用它:

Database.SetInitializer(new EmployeeDatabaseInitialiser());
new EmployeeContext().Database.Initialize(true);

var context = new EmployeeContext();
var bank1 = new EmployeeBank{Name = "Bank1"};
var bank2 = new EmployeeBank {Name = "Bank2"};
var epm1 = new EmployeePaymentMethod();
var epm2 = new EmployeePaymentMethod();

context.EmployeeBanks.Add(bank1);
context.EmployeeBanks.Add(bank2);
context.EmployeePaymentMethods.Add(epm1);
context.EmployeePaymentMethods.Add(epm2);
context.SaveChanges();

bank1.EmployeePaymentMethod = epm1;
epm2.EmployeeBank = bank2;
context.SaveChanges();

我使用了多对多关系以及两个关系列的附加UNIQUE约束,这将它转换为One-to-One_or_zero。您还有独立的自动增量ID。此解决方案不是100%实体框架,需要自定义数据库初始化程序来设置约束。