【问题标题】:EF6: Table Splitting Not WorkingEF6:表拆分不起作用
【发布时间】:2015-08-14 01:20:26
【问题描述】:

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

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

    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();

很遗憾,这不起作用。在消除了从地址中删除主索引的脚手架调用之后,我可以更新数据库了(可能是因为添加迁移代码认为主键“仅仅是”一个外键字段)。但是当我运行应用程序时,出现以下错误:

列名“Address_ID”无效。 列名“Address_ID”无效。

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

我正在尝试做的事情可能吗?如果是这样,我在配置中缺少什么?

其他信息

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

分辨率

我终于做了我之前应该做的事情,即检查由正在爆炸的查询生成的实际 T-SQL 代码。事实证明,问题不在于访问/地址链接,而在于涉及另一个表的完全独立的关系。显然,在此过程中,我做了一些事情让 EF 认为其他表(Voters)有一个 Address_ID 外键字段。实际上,Address/Voter 关系应该并且最初是与 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 表中都有一个条目。这似乎是“可选的”,而不是“必需的”。但它似乎有效,也许“必需”部分只是 EF 数据库模型的内部,而不是数据库本身。

【问题讨论】:

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


    【解决方案1】:

    模型存在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();
    

    【讨论】:

    • 感谢您的回复,但没有成功。仍然会生成相同的运行时错误(关于无法找到标记为“Address_ID”的列的投诉,EF 可能正在访问表中查找该列。我更新了我的问题以包含有关调用 modelBuilder 的更多信息。跨度>
    • 我在运行后发送了代码。尝试删除数据库并再次运行代码。
    【解决方案2】:

    除了 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 应该能够按照惯例弄清楚。

    【讨论】:

      猜你喜欢
      • 2014-07-18
      • 2014-01-07
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 2014-03-05
      • 1970-01-01
      • 2018-08-13
      • 2017-09-15
      相关资源
      最近更新 更多