EF6:表拆分不起作用

时间:2015-08-12 19:59:14

标签: entity-framework entity-framework-6 table-splitting

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

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

    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; }

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

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

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

  

列名称无效&#39; Address_ID&#39;。   列名称无效&#39; Address_ID&#39;。

根据我对EF6的有限经验,这看起来像是框架内部的某个地方,它希望有一些名为“地址_ID”的字段,可能在访问表中(基于&#39;表格名称&#39; _&#39;字段名称&#39;命名结构我已经看到其他隐式添加的字段。)

我正在尝试做什么?如果是这样,我在配置中缺少什么?

其他信息

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

解决

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

我没有试图解除大量迁移,而是选择吹走数据库,吹走迁移并从头开始。在重新创建数据库之后 - 但是使用了bubi的建议 - 我从备份中重新加载了数据,瞧,我回来了。

为了完整起见,这里的代码我最终不得不进入OnModelCreating方法调用以使地址/访问关系正常工作:

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,因为并非Address表中的每个条目都在Visit表中有一个条目。这似乎是&#34;可选&#34;,而不是&#34;必需&#34;。但它似乎有效,也许&#34;需要&#34; part只是EF的数据库模型的内部,而不是数据库本身。

2 个答案:

答案 0 :(得分:1)

模型中存在两个问题:
- 只有一个密钥可以自动编号,另一个必须获得相同的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();

答案 1 :(得分:1)

除了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应该能够按照惯例来解决它。