5

Tôi không thể làm tròn đầu, chủ đề trên tất cả các trạng thái SO tôi đang làm tất cả những điều đúng nhưng rõ ràng tôi phải có một cái gì đó ...EF 0..1 cho nhiều bản cập nhật mối quan hệ

Given hai defs đối tượng ...

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

Và sau đó bối cảnh với cấu hình mối quan hệ thích hợp ...

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

Tại sao khi tôi làm điều này ...

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

Tôi có nhận được ngoại lệ này ...

Thao tác thất bại: Mối quan hệ không thể thay đổi vì một hoặc nhiều trong những tài sản nước ngoài quan trọng là không nullable. Khi thay đổi đối với mối quan hệ, thuộc tính khóa ngoài có liên quan là được đặt thành giá trị null. Nếu khóa ngoài không hỗ trợ giá trị null, phải xác định mối quan hệ mới, thì thuộc tính khóa ngoài phải là được gán giá trị không null khác hoặc đối tượng không liên quan phải bị xóa .

EDIT:

Tôi nghĩ tôi sẽ thêm, là câu trả lời ở đây không thực sự chỉ ra những câu trả lời thực sự cho vấn đề tôi đã ...

Hóa ra là tài liệu tham khảo trong câu hỏi không phải là vấn đề tôi đã trên thực tế cập nhật khác sở hữu con của lớp hóa đơn tiếp tục lên mã bởi một cái gì đó như thế này ....

invoice.Lines = MergLines(newVersion, dbVersion); 

đang sáp nhập của tôi đã làm việc tốt nhưng như bất kỳ người sử dụng EF tường mới có thể biết y Bạn không thể chỉ đơn giản là "thay thế một bộ sưu tập trẻ em" như thế này, bạn phải loại bỏ cũ và thêm mới khi thích hợp.

+0

gì nếu bạn đã làm 'modelBuilder.Entity () HasMany (e. => e.Invoices) .WithOptional (e => e.Block) .HasForeignKey (e => e.BlockingCodeId) '. Ít nhất đó là cách một mối quan hệ tương tự được thiết lập trong phiên bản đầu tiên của DB mà tôi đã làm. SideNote: Đây là lý do tại sao tôi không bao giờ làm mã đầu tiên. Tôi thích thiết lập DB và sau đó cho phép EF tìm ra thứ này. – juharr

+0

nope ... tốt gọi mặc dù: ( – War

+0

Tôi nghi ngờ rằng 'Invoice.BlockingCodeId' trong DB là một ràng buộc khóa ngoại với không null. – shadow

Trả lời

1

Vì vậy, đảo ngược kỹ thuật này từ những gì tôi giả định là cấu trúc bảng SQL cơ bản bạn đang làm việc với ...

Khối Bảng:

Block Table Definition

Invoice Bảng:

Invoice Table Definition

Và với mối quan hệ khóa ngoài được xác định giữa Invoice.BlockingCodeId và Bl ock.Id ...

FK Relationship

tôi nhận được các lớp thực thể mã đầu tiên sau và bối cảnh khi để cho EF tạo chúng từ DB vật lý:

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

Khi các đối tượng và bối cảnh được cấu hình như trên, đoạn mã sau thực hiện mà không có vấn đề và tôi thấy những gì tôi mong đợi trong cơ sở dữ liệu 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(); 

Sau khi thực hiện, kết quả dat tình trạng là ...

Khối Bảng:

Block Data

Invoice Bảng:

Invoice Data

+0

Cảm ơn, đó là chính xác những gì tôi mong đợi ... Tôi nghĩ rằng lỗi, là những gì nó là, không phải là rất hữu ích và ngăn xếp dấu vết chỉ đơn giản là không cung cấp cho tôi đủ thông tin để xác định dòng chính xác của mã (tôi có khả năng xác định dòng worng) ... Tôi nghĩ rằng tôi có lẽ nhìn vào dòng sai của mã và điều này xác nhận nó. Tôi nghi ngờ rất nhiều ở đây rằng EF có lỗi. – War

Các vấn đề liên quan