5

nie mogę uzyskać moja głowa okrągłe to, nici całym SO stwierdzić robię wszystkie właściwe rzeczy, ale oczywiście muszę coś przeoczyć ...EF 0..1 do wielu relacji aktualizuje

Zważywszy te dwie obiektów 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; } 
    ... 
} 

A potem kontekst z odpowiednią konfiguracją związku ...

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

Dlaczego kiedy mogę to zrobić ...

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

Czy dostanę ten wyjątek ...

Operacja nie powiodła się: Związek nie mógł być zmieniony, ponieważ jedną lub więcej właściwości obcych klucz nie jest pustych. Po wprowadzeniu zmiany relacji, powiązana właściwość klucza obcego to ustawiona na wartość pustą. Jeśli klucz obcy nie obsługuje wartości pustych, , musi zostać zdefiniowana nowa relacja, właściwość klucza obcego musi być przypisana innej wartości innej niż null lub niepowiązany obiekt musi być usunięty .

EDIT:

myślałem, że chciałbym dodać, jako odpowiedź tutaj faktycznie nie wskazują na realną odpowiedź na problem miałem ...

Okazało się, że odniesienia w pytanie nie był problem miałem w rzeczywistości aktualizującego inną nieruchomość dzieci klasy faktury dalszej kodu przez coś takiego ....

invoice.Lines = MergLines(newVersion, dbVersion); 

Mój kod łączenie pracował w porządku, ale jak każdy zapalony użytkownik EF wiedziałby y nie możesz po prostu "zastąpić kolekcji dzieci" w ten sposób, musisz usunąć stare i dodać nowe, jeśli to konieczne.

+0

Co jeśli nie 'modelBuilder.Entity () hasMany (np. => e.Faktury) .WithOptional (e => e.Block) .HasForeignKey (e => e.BlockingCodeId) '. Przynajmniej tak układa się podobna relacja w pierwszej wersji DB, którą zrobiłem. SideNote: Właśnie dlatego nigdy nie robię kodu jako pierwszy. Wolę ustawić DB, a następnie pozwolić EF to zrozumieć. – juharr

+0

nope ... good call though :( – War

+0

Podejrzewam, że 'Invoice.BlockingCodeId' w DB jest ograniczeniem klucza obcego z niezerową wartością – shadow

Odpowiedz

1

Więc reverse engineering to od tego, co zakładam jest podstawowa struktura tabeli SQL użytkownik pracuje z ...

Blok Tabela:

Block Table Definition

Faktura Tabela:

Invoice Table Definition

Oraz z relacją klucza obcego zdefiniowaną między fakturą.BlockingCodeId i Bl ock.Id ...

FK Relationship

mam następujące klasy Kod Podmiotu pierwszego i kontekst gdy pozwalając EF tworzyć je od fizycznej DB:

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

Kiedy podmioty i kontekst są skonfigurowane jak wyżej, następujący kod wykonuje bez problemu i widzę, co by się spodziewać w bazie danych 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(); 

Po wykonaniu, uzyskany dat stan jest ...

Blok Tabela:

Block Data

Faktura Tabela:

Invoice Data

+0

Dzięki, dokładnie tego mogłem się spodziewać ... Myślę, że błąd, który jest to jest, nie jest bardzo pomocne, a ślad stosu po prostu nie daje mi wystarczającej ilości informacji, aby określić dokładną linię kodu (prawdopodobnie zidentyfikowałem błędną linię) ... Myślę, że prawdopodobnie patrzę na niewłaściwą linię kod i to potwierdza. Wątpię tu bardzo, że EF ponosi winę. – War