5

我不能讓我的頭一輪這一點,所有的線程在SO狀態我做了所有正確的事情,但顯然我必須錯過了一些東西......EF 0..1一對多的關係更新

鑑於這兩個對象DEFS ...

public class Invoice 
{ 
    [Key] 
    public int Id { get; set; } 

    [ForeignKey("Block")] 
    public int? BlockingCodeId { get; set; } 

    public virtual BlockingCode Block { get; set; } 

    ... 

} 

public class BlockingCode 
{ 
    [Key] 
    public int Id { get; set; } 
    public virtual ICollection<Invoice> Invoices { get; set; } 
    ... 
} 

然後用適當的關係配置上下文...

public class FaureciaContext : EFDataContext 
{ 
    public virtual DbSet<Invoice> Invoices { get; set; } 
    public virtual DbSet<BlockingCode> BlockingCodes { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<Invoice>() 
      .HasOptional(e => e.Block) 
      .WithMany(e => e.Invoices); 
    } 
} 

爲什麼,當我做到這一點...

// assume this invoice has a BlockingCode relationship 
var invoice = db.Invoices.First(); 
invoice.BlockingCodeId = null; 
db.Savechanges(); 

我能得到這個例外...

操作失敗:關係不能被改變,因爲 一個或多個外鍵的屬性是不可爲空。當 更改爲關係時,相關的外鍵屬性 設置爲空值。如果外鍵不支持空值,則必須定義一個新的關係,外鍵屬性必須爲 分配另一個非空值,或者無關對象必須爲 刪除。

編輯:

我以爲我會補充說,像是這裏的答案並沒有真正指出了真正的答案我有問題...

原來,在參考問題是,不是我,其實是更新發票類的其他子類屬性的進一步增長像這樣的代碼問題....

invoice.Lines = MergLines(newVersion, dbVersion); 

我的合併代碼工作正常,但任何敏銳的EF用戶會知道ÿ你不能簡單地「像這樣替換一個孩子集合」,你必須刪除舊的並根據需要添加新的。

+0

如果你所做的'modelBuilder.Entity ()的hasMany(E。 => e.Invoices).WithOptional(e => e.Block).HasForeignKey(e => e.BlockingCodeId)''。至少這就是我在數據庫第一版中設置類似關係的方式。 SideNote:這就是爲什麼我從不先做代碼。我更喜歡設置數據庫,然後讓EF來計算這些東西。 – juharr

+0

nope ...雖然很好,但:( – War

+0

我懷疑數據庫中的Invoice.BlockingCodeId是一個不爲空的外鍵約束 – shadow

回答

1

因此,反向從我假設是您正在使用基本的SQL表結構...

塊表工程這樣的:

Block Table Definition

發票表:

Invoice Table Definition

並且在Invoice.BlockingCodeId和Bl之間定義了外鍵關係ock.Id ...

FK Relationship

我得到了下面的代碼,第一個實體類和背景讓EF時從物理數據庫中創建它們:

[Table("Block")] 
public partial class Block 
{ 
    public Block() 
    { 
     Invoices = new HashSet<Invoice>(); 
    } 

    public int Id { get; set; } 

    [Required] 
    [StringLength(50)] 
    public string Description { get; set; } 

    public virtual ICollection<Invoice> Invoices { get; set; } 
} 

[Table("Invoice")] 
public partial class Invoice 
{ 
    public int Id { get; set; } 

    public int? BlockingCodeId { get; set; } 

    [Required] 
    [StringLength(50)] 
    public string Description { get; set; } 

    public virtual Block Block { get; set; } 
} 

public partial class TestContext : DbContext 
{ 
    public TestContext() 
     : base("name=TestContext") 
    { 
    } 

    public virtual DbSet<Block> Blocks { get; set; } 
    public virtual DbSet<Invoice> Invoices { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Block>() 
      .HasMany(e => e.Invoices) 
      .WithOptional(e => e.Block) 
      .HasForeignKey(e => e.BlockingCodeId); 
    } 
} 

當實體和上下文如上配置,下面的代碼執行沒有問題,我看到我期望在SQL數據庫中:

var context = new TestContext(); 
var block = new Block { Description = "Block 1" }; 
var invoices = new List<Invoice> 
        { 
         new Invoice { Description = "Invoice 1" }, 
         new Invoice { Description = "Invoice 2" } 
        }; 

invoices.ForEach(i => block.Invoices.Add(i)); 
context.Blocks.Add(block); 
context.SaveChanges(); 

block = null; 
var invoice = context.Invoices.First(); 
invoice.Block = null; 
context.SaveChanges(); 

執行後,生成的dat狀態是...

塊表:

Block Data

發票表:

Invoice Data

+0

謝謝,這正是我所期望的......我認爲錯誤是什麼它並不是非常有用,堆棧跟蹤根本沒有給我足夠的信息來確定確切的代碼行(我可能確定了worng行)......我想我可能正在看錯誤的行代碼,這證實了它。在這裏我很懷疑EF是否有過錯。 – War