EF6:Table 拆分不起作用

EF6: Table Splitting Not Working

我正在尝试创建一个 EF6 数据库,其中两个 tables,Addresses 和 Visits,共享相同的值作为主键。从概念上讲,访问是地址的扩展。我拆分 table 是因为地址中的大部分记录不需要访问中包含的字段。

我正在使用代码优先方法。这是地址的相关代码:

    public class Address 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [ForeignKey( "ID" )]
    public virtual Visit Visit { get; set; }

访问次数:

   public class Visit
   {
    [Key]
    [DatabaseGenerated( DatabaseGeneratedOption.Identity )]
    public int ID { get; set; }

    [ForeignKey("ID")]
    public virtual Address Address { get; set; }

根据我的研究,我还需要在我的数据上下文的 OnModelCreating 方法中包含以下内容:

    modelBuilder.Entity<Visit>()
        .HasOptional( v => v.Address )
        .WithRequired();

不幸的是,这不起作用。在消除从 Addresses 中删除主索引的脚手架调用后,我可以正常更新数据库(可能是因为添加迁移代码认为主键是 "merely" 一个外键字段)。但是当我 运行 应用程序时,我收到以下错误:

Invalid column name 'Address_ID'. Invalid column name 'Address_ID'.

根据我对 EF6 的有限经验,这看起来像是框架深处的某个地方,它期望有名为 'Address_ID' 的字段,可能在访问 table 中(基于 'table name'_'field name' 命名结构我见过其他隐式添加的字段)。

我想做的事情可行吗?如果是这样,我在配置中缺少什么?

附加信息

在尝试 bubi 提出的解决方案时,不幸的是它仍然产生相同的错误,我可以消除 OnModelCreating 代码并仍然生成功能迁移代码。

分辨率

我终于做了我早该做的事情,即检查由正在爆炸的查询生成的实际 T-SQL 代码。事实证明,问题不在 Visit/Address 链接中,而是在涉及另一个 table 的完全独立的关系中。显然,在某个地方,我做了一些事情让 EF 认为其他 table(选民)有一个 Address_ID 外键字段。实际上,Address/Voter 关系应该并且最初是与 Voter.AddressID 字段相关联。

我没有尝试取消大量迁移,而是选择取消数据库,取消迁移并从头开始。重新创建数据库后——但使用了 bubi 的建议——我从备份中重新加载了数据,瞧,我又回来了。

为了完整起见,这里是我最终不得不放入 OnModelCreating 方法调用中以使 Address/Visit 关系正常工作的代码:

modelBuilder.Entity<Visit>()
    .HasRequired( v => v.Address )
    .WithRequiredDependent( a => a.Visit );

modelBuilder.Entity<Address>()
    .HasRequired( a => a.Visit )
    .WithRequiredPrincipal( v => v.Address );

我有点困惑为什么我必须使用 HasRequired 才能使用 WithRequiredPrincipal/WithRequiredDependent,因为并非地址 table 中的每个条目在访问 table。那似乎是 "optional",而不是 "required"。但它似乎有效,也许 "required" 部分只是 EF 数据库模型的内部部分,而不是数据库本身。

模型中有 2 个问题:
- 只有一个键可以自动编号,另一个必须获得相同的 ID(这由 EF 独立)。
- 映射问题。
这个模型应该可以。

public class Address
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Description { get; set; }

    public virtual Visit Visit { get; set; }
}

public class Visit
{
    public Visit()
    {
        Address = new Address();
    }

    [Key]
    [ForeignKey("Address")]
    public int Id { get; set; }

    public string Description { get; set; }

    public virtual Address Address { get; set; }
}

使用示例

            var visit = new Visit
            {
                Description = "Visit",
                Address = {Description = "AddressDescription"}
            };

            db.Visits.Add(visit);

            db.SaveChanges();

除了 bubi 提到的内容之外,您的 modelBuilder 陈述与模型相矛盾,因为它没有提到 Address.Visit 作为逆 属性。因此它认为 属性 代表一个单独的关系,并尝试为该关系创建 Address_ID 列。

你需要

modelBuilder.Entity<Visit>()

    // from your description sounds like every Visit needs an Address
    .HasRequired(v => v.Address )

    // need to mention the inverse property here if you have one
    .WithOptional(a => a.Visit); 

...或者完全删除该语句,因为您已经在使用属性,而且 EF 应该能够按照惯例解决它。