【问题标题】:One to one relationship with Entity Framework Fluent API与 Entity Framework Fluent API 的一对一关系
【发布时间】:2013-01-26 10:04:59
【问题描述】:

我在我的一个实体上进行反向导航时遇到问题。

我有以下两个对象:

public class Candidate
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long CandidateId { get; set; } 
    ....

    // Reverse navigation
    public virtual CandidateData Data { get; set; }
    ...

    // Foreign keys
    ....
}

public class CandidateData
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long CandidateDataId { get; set; }

    [Required]
    public long CandidateId { get; set; }

    // Foreign keys
    [ForeignKey("CandidateId")]
    public virtual Candidate Candidate { get; set; }
}

现在我在 CandidateData 对象上的外键导航工作正常。我无法让候选对象的反向导航正常工作(如果可能的话)。

这是我的 OnModelCreating 函数:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Candidate>()
        .HasOptional(obj => obj.Data)
        .WithOptionalPrincipal();

    base.OnModelCreating(modelBuilder);
}

除了在数据库中我得到两个链接到 CandidateId 的列之外,它已经接近工作了。我从 POCO 对象中得到了一个,我得到了另一个列 Candidate_CandidateId,我假设它是由模型构建器创建的。

此刻我很安静。有人可以说明发生了什么吗?

【问题讨论】:

  • 你为什么要定义额外的字段,比如 [Required] public long CandidateId { get;放; } 删除它,你的问题就会消失
  • 我认为你的关系应该是 modelBuilder.Entity().HasOptional(obj => obj.Data).WithRequired(e => e.Candidate);顺便说一句:尽量不要混合 fluent api 和属性。

标签: c# entity-framework ef-code-first ef-fluent-api


【解决方案1】:

一对一问题.... 问题是 EF 和 CODE 首先,当 1:1 时,依赖项具有引用主体的主键。虽然您可以以其他方式定义数据库,实际上使用数据库,您甚至可以在主数据库上拥有可选的 FK。 EF 首先在代码中做出此限制。我认为还算公平……

试试这个:IS 添加了一些意见,如果您不同意,可以忽略:-)

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace EF_DEMO
{
class FK121
{
    public static void ENTRYfk121(string[] args)
    {
        var ctx = new Context121();
        ctx.Database.Create();
        System.Console.ReadKey();
    }
}
public class Candidate
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]// best in Fluent API, In my opinion..
    public long CandidateId { get; set; }
 //   public long CandidateDataId { get; set; }// DONT TRY THIS... Although DB will support EF cant deal with 1:1 and both as FKs
    public virtual CandidateData Data { get; set; }  // Reverse navigation

}
public class CandidateData 
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] // best in Fluent API as it is EF/DB related 
    public long CandidateDataId { get; set; }   // is also a Foreign with EF and 1:1 when this is dependent
   // [Required]
   // public long CandidateId { get; set; }   // dont need this... PK is the FK to Principal in 1:1
   public virtual Candidate Candidate { get; set; } // yes we need this
}
public class Context121 : DbContext
{
    static Context121()
    {
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>());
    }
    public Context121()
        : base("Name=Demo") { }
    public DbSet<Candidate> Candidates { get; set; }
    public DbSet<CandidateData> CandidateDatas { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Candidate>();

        modelBuilder.Entity<CandidateData>()
                    .HasRequired(q => q.Candidate)
                    .WithOptional(p=>p.Data) // this would be blank if reverse validation wasnt used, but here it is used
                    .Map(t => t.MapKey("CandidateId"));    // Only use MAP when the Foreign Key Attributes NOT annotated as attributes
    }
}

}

【讨论】:

  • 谢谢,这或多或少地解决了我的问题。虽然我仍然希望可以使用 CandidateId 字段进行即时编辑,而无需加载 Candidate 对象。 (或者我的解释有误?)再次感谢威廉。
  • 如果您仍然想要外键,您可以将 CandidateId 作为 CandidateData 上的属性,而不是调用 .Map(t => t.MapKey("CandidateId")) 使用 .HasForeignKey(t => t.CandidateId) 那不行吗?
  • @NathanaelSchulte 不幸的是,这不起作用。为什么你不能这样做,我不知道。 .HasForeignKey() 方法仅在使用 many 时才可访问。 phil soady 方法的问题在于,外键 CandidateId 不能作为模型的显式属性公开,即 CandidateId 不能在 CandidateData 类中定义。
【解决方案2】:

我认为外键应该被创建为: .Map(t => t.MapKey("CandidateDataId")) 因为这个外键将被放置在候选表中......

你觉得怎么样?

【讨论】:

    猜你喜欢
    • 2013-08-16
    • 2012-01-20
    • 1970-01-01
    • 2018-10-04
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多